|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .vscode | ||
| public | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| .prettierrc.js | ||
| astro.config.mjs | ||
| eslint.config.js | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| wrangler.jsonc | ||
alexislours.com
My photography portfolio built with Astro and TailwindCSS.
License
This project's code is under the MIT license.
Features
- Photo Gallery: Grid layout displaying photography with image optimization
- Flickr Integration: Loads images and EXIF data from Flickr
- RSS Feed: XML feed for photo updates
- JSON API: API endpoints for accessing photo data
- Responsive Design: Mobile-first layout
- Optimizations: Optimized images, perfect Lighthouse score
- Minimal JavaScript: JavaScript only used for the map page, optional everywhere else
- SEO: Structured data, meta tags, and sitemap generation
- Social Links: LinkTree style page
- Accessibility: Keyboard navigation and semantic HTML
Environment Variables
To run this project, you will need to create a .env file in the root directory and add the following environment variables to it:
FLICKR_API_KEY, a Flickr API key, used to retrieve the pictures.MAPBOX_ACCESS_TOKEN, a Mapbox access token with access to theStatic Images APIandTemporary Geocoding API, used to generate the map preview found in the picture pages and the reverse geocoding informations.
Additionally, the content.config.ts file should be updated to fetch data from another Flickr album.
Installation
After cloning the project, you only need to install the dependencies using:
npm install
Building
The project can be built using the following command:
npm run build
The build step can be long due to:
- Astro generating responsive AVIF variants of all images
- Having to make multiple calls to the Flickr API to retrieve EXIFs
- Having to make multiple calls to the Mapbox API to retrieve reverse geocoding data.
After the first build and the images cached, an incremental build takes around 30s for ~250 pictures.
API Reference
The project provides a read only JSON API to retrieve photo data.
Each photo is returned as an object of this format:
{
"id": "54782096887",
"title": "Common Moorhen",
"description": "Portrait of a common moorhen (Gallinula chloropus).",
"date_taken": "2025-09-12T13:08:44.000Z",
"imageUrls": {
"sq_75px": {
"height": 75,
"width": 75,
"orientation": "square",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_s.jpg"
},
"100px": {
"height": 67,
"width": 100,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_t.jpg"
},
"sq_150px": {
"height": 150,
"width": 150,
"orientation": "square",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_q.jpg"
},
"240px": {
"height": 160,
"width": 240,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_m.jpg"
},
"320px": {
"height": 213,
"width": 320,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_n.jpg"
},
"500px": {
"height": 333,
"width": 500,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618.jpg"
},
"640px": {
"height": 427,
"width": 640,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_z.jpg"
},
"800px": {
"height": 533,
"width": 800,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_c.jpg"
},
"1024px": {
"height": 683,
"width": 1024,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_9da26f1618_b.jpg"
},
"1600px": {
"height": 1067,
"width": 1600,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_34d8599109_h.jpg"
},
"2048px": {
"height": 1365,
"width": 2048,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_d8f12c371f_k.jpg"
},
"original": {
"height": 4640,
"width": 6960,
"orientation": "landscape",
"url": "https://live.staticflickr.com/65535/54782096887_622b6ef4b3_o.jpg"
}
},
"exifs": {
"model": "Canon EOS R7",
"lens": "RF200-800mm F6.3-9 IS USM",
"exposureTime": "1/2500",
"fNumber": "f/8.0",
"focalLength": "600 mm",
"iso": "4000"
},
"location": {
"latitude": 48.934882,
"longitude": 2.314252,
"locationName": "Gennevilliers, Hauts-de-Seine, France"
}
}
Get all photos
Returns an array of all photo objects.
GET /api/photos/all
Get a photo by ID
Returns a single photo from its ID.
GET /api/photos/${id}