{"id":13423713,"url":"https://github.com/herschel666/phox","last_synced_at":"2025-03-15T17:32:12.364Z","repository":{"id":57323206,"uuid":"102256050","full_name":"herschel666/phox","owner":"herschel666","description":"[discontinued] 🦊 Create a photo blog powered by Next.","archived":true,"fork":false,"pushed_at":"2019-07-28T09:06:39.000Z","size":2608,"stargazers_count":19,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-18T08:39:26.704Z","etag":null,"topics":["gallery","next","nextjs","photography","react","static-site-generator"],"latest_commit_sha":null,"homepage":"https://phox.netlify.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/herschel666.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-03T10:12:13.000Z","updated_at":"2024-09-05T12:52:27.000Z","dependencies_parsed_at":"2022-08-26T01:11:26.196Z","dependency_job_id":null,"html_url":"https://github.com/herschel666/phox","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herschel666%2Fphox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herschel666%2Fphox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herschel666%2Fphox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herschel666%2Fphox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/herschel666","download_url":"https://codeload.github.com/herschel666/phox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243767200,"owners_count":20344889,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gallery","next","nextjs","photography","react","static-site-generator"],"created_at":"2024-07-31T00:00:41.092Z","updated_at":"2025-03-15T17:32:11.616Z","avatar_url":"https://github.com/herschel666.png","language":"TypeScript","funding_links":[],"categories":["Boilerplates"],"sub_categories":[],"readme":"\n[discontinued] 🦊 Phox\n====\n\n\u003e Create a static photo site powered by Next.js 🖼\n\n[![Build Status](https://travis-ci.org/herschel666/phox.svg?branch=master)](https://travis-ci.org/herschel666/phox)\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![Current package version](https://img.shields.io/npm/v/phox.svg)](https://npm.im/phoxg)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\n## PSA\n\nphox will be discontinued. I built this tool to be able to create a nice photo website. Today I deployed a new version of that nice photo website, which is based on [Gatsby](https://gatsbyjs.com) now. Though next.js is a great tool, it is far too basic for what I need for building a photo website. Gatsby however comes with batteries included regarding those kind of sites.\n\nIf you're relying on phox (and from what the \"Used by\"-button at the top of this page tells me, you probably aren't… 😅) feel free to have a look at the [source of my photo website](https://github.com/herschel666/photoblog/) and get inspired for your migration to Gatsby.\n\nCheers.\n\n## Features\n\n- Automatic detail pages for every photo with contents from EXIF \u0026 IPTC metadata\n- Overview pages for every keyword\n- Manage your contents with Markdown files like in Gatsby or Jekyll\n- Server-side rendered HTML for maximum performance\n- Client-side routing for ease of use\n- Image compression during build step\n\n## Idea\n\n[Next.js](https://npm.im/next) is great when it comes to building web applications. But setting up the above mentioned features for a (static) online gallery is a rather tedious task. Here **phox** comes into play: it enables you to manage your contents in Markdown files and inside the image metadata, so you can focus on building the site.\n\nTo achieve this **phox** relies on an opinionated set of views, which it provides the generated data for via an HTTP-API. Additionally **phox** provides a function for gathering all the pages of your photo site for a static export.\n\nWhat **phox** doesn't provide is any kind of React views. It equips you with a way to fetch the data — you then build your Next.js site on top of it. To get and idea of how this might look like, have a look at the code of the [Simple Example](https://github.com/herschel666/phox/tree/master/examples/simple).\n\n## Built with phox 🚀\n\n - ~~[ek|photos](https://photos.klg.bz/) — [[source](https://github.com/herschel666/photoblog/)]~~\n - [Simple Example](https://phox.netlify.com/) — [[source](https://github.com/herschel666/phox/tree/master/examples/simple)]\n\n## How to use\n\n### Setup\n\nInstall the requirements:\n\n```shell\n$ npm install phox next react react-dom --save\n```\n\nAdd a `scripts`-block to your `package.json`, like …\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"node server.js\",\n    \"export\": \"phox\"\n  }\n}\n```\n\nSet up a `server.js` in your project-root.\n\n```js\nconst { createServer } = require('phox');\n\ncreateServer().then(({ server }) =\u003e\n    // phox uses port 3000 by default; see section\n    // \"Configuration\" to learn how to change that\n    server.listen(3000, (err) =\u003e {\n        if (err) throw err;\n        console.log('Server running on port 3000 ...');\n    }));\n```\n\nCreate content and pages. The folder structure should look like this:\n\n```\n./\n├── content/\n│   ├── albums/\n│   │   ├── my-awesome-album/\n│   │   │   └── index.md\n│   │   └── my-other-awesome-album/\n│   │       └── index.md\n│   ├── a-random-page/\n│   │   └── index.md\n│   └── index.md\n├── pages/\n│   ├── album.js\n│   ├── default.js\n│   ├── image.js\n│   ├── index.js\n│   └── tag.js\n└── static/\n    └── albums/\n        ├── my-awesome-album/\n        │   ├── image-1.jpg\n        │   └── image-2.jpg\n        └── my-other-awesome-album/\n            ├── image-1.jpg\n            └── image-2.jpg\n```\n\nStart the dev-server:\n\n```shell\n$ npm run dev\n```\n\nThe site is now available on http://localhost:3000/.\n\nWhen everything is up and running and ready to be released, set up a `next.config.js` in the project's root:\n\n```js\nconst { getPathMap } = require('phox');\n\nmodule.exports = {\n    async exportPathMap() {\n        return getPathMap();\n    },\n};\n```\n\nNow run …\n\n```shell\n$ npm run export\n```\n\nThat's it. The static site will be in the `./out`-folder.\n\n## Albums\n\nAlbums are represented by folders inside `./content/albums/`. They just contain an `index.md`, that holds the text contents of the album page. Frontmatter — like in Jekyll — is supported. \n\n**Example**\n\n```markdown\n---\ntitle: My awesome ride\ncreated: 2017-09-03\n---\n\nLorem **ipsum** dolot [look ma I am a link](http://example.org).\n```\n\nTo populate the album page with photos, create an album-folder in `./static/albums/` with the same name as your album and put all images in there. The **phox**-HTTP-API will provide you with a list of all the images of an album and their metadata.\n\nEach image will also get a detail page. The content of these detail pages will be fetched directly from the metadata. This means title, description, etc. are managed in e.g. Lightroom or any other application, that let's you manage metadata.\n\nThe following list shows, which data is currently derived from [EXIF](https://npm.im/exif)/[IPTC](https://npm.im/node-iptc) and how it is exposed to the application:\n\n```\niptc.object_name       =\u003e title\niptc.caption           =\u003e description\niptc.keywords          =\u003e tags\niptc.date_created      =\u003e createdAt\nexif.image.Model       =\u003e camera\nexif.exif.LensModel    =\u003e lens\nexif.exif.ISO          =\u003e iso\nexif.exif.FNumber      =\u003e aperture\nexif.exif.FocalLength  =\u003e focalLength\nexif.exif.ExposureTime =\u003e exposureTime\nexif.exif.Flash        =\u003e flash\nexif.gps               =\u003e gps (transformed to { lat, lng })\n --                    =\u003e orientation ('portrait', 'landscape' or 'square')\n --                    =\u003e width (in px)\n --                    =\u003e height (in px)\n```\n\nThe `description` can hold Markdown! All the metadata for an image is provided by the **phox**-HTTP-API.\n\n## Frontpage \u0026 other pages\n\nBesides the albums there's a frontpage (`./content/index.md`) required for your site to work.\n\nYou also have the possibility to add additional static pages, e.g. `./content/about/index.md`. Because linking in static static Next sites is not trivial, it is not possible to nest static pages.\n\n## Views\n\nViews are located in the `./pages/`-folder. There are four of them to represent the different kind of pages.\n\n```\n─ album.js   // For the album view\n─ default.js // For arbitrary pages\n─ image.js   // For the detail pages of images\n─ index.js   // For the frontpage\n─ tag.js     // For the overview page of a keyword\n```\n\nInside their `getInitialProps`-method they can fetch their contents from the respective **phox**-HTTP-API.\n\n## Configuration\n\nConfiguration is optional in **phox**. But if you want to change the default settings, set up a `./phox.config.js` and in there export your configuration object.\n\n```js\nmodule.exports = {\n    // my settings ...\n};\n```\n\nThere are the following options.\n\n| Name                | Type      | Default       | Description |\n| :-----------------  | :-------: | :------------ | :---------- |\n| `contentDir`        | `string`  | `'content'`   | Location of your Markdown contents. |\n| `albumsDir`         | `string`  | `'albums'`    | Location of your album folders — Markdown contents \u0026 images |\n| `outDir`            | `string`  | `'out'`       | Location of the exported, static site. |\n| `port`              | `number`  | `3000`        | Port of the **phox**-HTTP-API |\n| `hostname`          | `string`  | `'localhost'` | Hostname of the **phox**-HTTP-API |\n| `server`            | `string`  | `'server.js'` | Filename of the server file |\n| `imageOptimization` | `object`  |               | Holds configuration for the image optimization during the export |\n| `imageOptimization.progressive`     | `boolean` | `true`        | Lossless conversion to progressive JPGs. |\n| `imageOptimization.quality`         | `string`  | `'65-80'`     | Quality of PNG-compression ([more infos](https://www.npmjs.com/package/imagemin-pngquant#quality)) |\n\nThe config inside `./phox.config.js` is also respected by `bin/phox`.\n\n## **phox**-HTTP-API\n\n`phox/server` provides you with all the data you need in your views.\n\n### `/data/index.json`\n\nReturns the frontpage's contents and a list of all the albums with metadata \u0026 `\u003cLink /\u003e`-props.\n\n### `/data/albums/(:album).json`\n\nReturns the contents of the album \u0026 a list of all photos, including metadata and `\u003cLink /\u003e`-props for the detail pages.\n\n### `/data/albums/(:album)/(:image).json`\n\nReturns all the metadata of an image. Additionally there are the title \u0026 the `\u003cLink /\u003e`-props of the previous and the next image, (if available).\n\n### `/data/tag/(:tag).json`\n\nReturns the contents of the overview page of a given keyword.\n\n### `/data/(:page).json`\n\nReturns the contents of arbitrary pages.\n\n_Note: if you set a custom value for `albumsDir` in the configuration, the HTTP-endpoint for albums \u0026 images will change accordingly._\n\n## Adding custom routes to the server\n\nIn the `server.js` import the `Router`, define your custom routes and pass the router into the `createServer`-function.\n\n```js\nconst { createServer, Router } = require('phox');\nconst router = Router();\n\nrouter.get('/api/say/:text/', (req, res) =\u003e res.json({\n  text: decodeURIComponent(req.params.text),\n}));\n\ncreateServer(router).then(({ server }) =\u003e server.listen(…);\n```\n\nThe `Router` exported by **phox** is the one from [Express](http://expressjs.com/). So you can refer to [their documentation](http://expressjs.com/en/guide/routing.html#express-router) to learn more about its usage.\n\nHave in mind that you can only use these custom routes during development. They won't be available after you'va statically built your site with **phox**.\n\n## Contributing\n\nIf you have a question or found a bug, feel free [to open an issue](https://github.com/herschel666/phox/issues). If you have an idea, what is wrong, you're highly encouraged, to open a pull request.\n\n## Author\n\nEmanuel Kluge ([@Herschel_R](https://twitter.com/Herschel_R))\n\n## LICENSE\n\nCopyright 2019 Emanuel Kluge\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this\nsoftware and associated documentation files (the \"Software\"), to deal in the Software\nwithout restriction, including without limitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of the Software, and to permit persons\nto whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or\nsubstantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING\nBUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherschel666%2Fphox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fherschel666%2Fphox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherschel666%2Fphox/lists"}