Features

Responsive Images

Every photo is automatically resized to multiple breakpoints and converted to WebP. Obscura generates the srcset and sizes attributes so browsers load the right size for each screen. You drop in a JPEG; your visitors get a fast, sharp image whether they're on a phone or a 5K display.

EXIF Extraction

Camera model, lens, focal length, aperture, ISO, shutter speed, date — Obscura reads all of it directly from your image files. No manual data entry for the things your camera already recorded.

Sidecar Metadata

Each photo can have a companion YAML file for the information your camera doesn't capture: a title, a location name, a caption, tags. Obscura auto-generates these sidecars at build time, pre-filled with EXIF data. You fill in the rest — by hand, or using the interactive npm run sidecar editor that shows you each photo with a terminal preview and prompts for the missing fields.

Galleries

Photos are organised into galleries, each with a title, description, and URL slug. Choose between masonry (variable-height tiles) and grid (uniform cells) layouts, per gallery or site-wide. Mark galleries as unlisted to keep working photos out of the index while still referencing them in blog posts.

Photo Shortcodes

Reference any photo from any gallery inside a blog post with a single shortcode:

{{< photo "street/morning-light" >}}

Obscura renders it as a styled photo card with the image and its metadata. If the photo name is unique across galleries, you can use just the bare slug. Broken references are caught at build time — no dead images in production.

Blog

Write about your shoots, your gear, your process. Blog posts are Markdown files with frontmatter for title, date, tags, and an optional summary. Photo shortcodes let you weave your images into the narrative. Posts are listed chronologically with tag filtering and an RSS feed.

Pages

Simple Markdown pages for your about, contact, or any other static content. Each file in site/content/pages/ becomes a top-level page on your site.

Theming

Obscura ships with the editorial theme — a clean, magazine-inspired design with automatic dark mode, a PhotoSwipe lightbox, and CSS custom properties for easy colour and typography tweaks. Drop a custom theme into site/themes/ to override the built-in one — your customisations live alongside your content, safe from upstream updates.

Incremental Builds

Image processing is the slowest part of any photo site build. Obscura caches processed images and skips unchanged photos on subsequent builds. A portfolio of 100 photos rebuilds in under a second when only content has changed. Need a guaranteed-fresh build? npm run build:clean starts from scratch.

Static Output

The generated site is plain HTML, CSS, and JavaScript — no application server, no database, no runtime dependencies. Host it on any static file server: GitHub Pages, Netlify, Cloudflare Pages, your own VPS, or anything else that serves files over HTTP. It's your site — put it wherever you want.