Nuxt 3 frontend with a Directus-powered content layer for:
- site settings
- blog posts
- photo archive
Make sure to install the dependencies:
pnpm installCreate a .env file with the Directus connection details:
NUXT_PUBLIC_DIRECTUS_URL=https://your-directus-instance.example.com
DIRECTUS_TOKEN=your_directus_static_tokenDIRECTUS_TOKEN should be a read token with access to the public-facing collections below. If your Directus instance exposes these collections publicly, you can omit the token and the site will still render.
The site expects these collections:
Use a single item with these fields:
site_namestringsite_taglinetextsite_descriptiontextgithub_urlstringsupport_urlstringnav_cta_labelstringnav_cta_urlstringposts_labelstringphotos_labelstring
statusstringslugstringtitlestringexcerpttextcontenttext or rich text HTMLcover_imagefilepublished_atdatetimefeaturedbooleantagsJSON string array
statusstringslugstringtitlestringdescriptiontextimagefilepublished_atdatetimetaken_atdatetimelocationstringcamerastringlensstringfeaturedbooleantagsJSON string array
Only items with status = published are exposed on the public site.
Start the development server on http://localhost:3000:
pnpm run devBuild the application for production:
pnpm run buildLocally preview production build:
pnpm run previewThere is a reusable photo ingest CLI for agent-driven uploads:
pnpm run photos:prepare -- --manifest /tmp/photo-manifest.json /absolute/path/to/photo-1.jpg /absolute/path/to/photo-2.jpg
pnpm run photos:validate -- --manifest /tmp/photo-manifest.json
pnpm run photos:upload -- --manifest /tmp/photo-manifest.jsonOptional Directus schema helpers:
pnpm run photos:setup-motion
pnpm run photos:setup-shots
pnpm run photos:setup-taxonomies
pnpm run photos:setup-timelinesThe intended workflow is:
- Run
photos:preparewith exported image paths or--paths-file. - Let the agent inspect the images and ask a couple of concise questions about the journey, story, and grouping.
- Fill in each photo's
title,description,slug, andsetSlugsin the generated manifest. - Optionally add
setsdefinitions for custom photoset titles and descriptions. - Run
photos:validate, thenphotos:upload.
The manifest includes EXIF-derived metadata, suggested auto-set candidates, and a storyContext section the agent can use while writing titles and descriptions.
TIFF uploads are converted to JPEG automatically before being sent to Directus.
If an edited export is missing GPS or place fields, the ingest CLI will also look for matching original raw and XMP sidecar files under PHOTO_INGEST_ORIGINAL_ROOTS (defaults to /mnt/h/DCIM) and merge that metadata into the manifest and converted upload.
If GPS exists but no readable place name does, photos:prepare will reverse geocode the coordinates through Nominatim and cache the result locally. You can override this with PHOTO_INGEST_REVERSE_GEOCODE_URL, PHOTO_INGEST_REVERSE_GEOCODE_CACHE, PHOTO_INGEST_REVERSE_GEOCODE_USER_AGENT, or disable it with PHOTO_INGEST_REVERSE_GEOCODE=0.
If a photo should behave like a motion sequence, add motionFrameSourcePaths to that photo entry in the manifest. Those files will also be converted to JPEG when needed and linked as motion frames before the final hero image.
If a photo needs attached still variants under the same slug, add a shots array to that photo entry. Each shot can include sourcePath, role, title, and description. This is intended for alternates, details, and nearby frames that belong to one published photo without turning into a full set.
You can also add structured metadata and story placement:
locationMetafor structured placescameraMetaandlensMetafor lookup-backed gear metadatatimelineEntriesfor placing a photo inside one or more story timelines with optionalchapterTitleandstoryText