Getting Started
This guide gets you from zero to a running portfolio in five steps. You'll need Node.js 20 or later and a terminal.
1. Clone and Install
git clone https://github.com/jemayer/obscura.git my-portfolio
cd my-portfolio
npm install
That gives you the Obscura engine, the default theme, and the example content. Your config and content live inside a site/ directory created in the next step — separated from the engine code, so pulling updates later won't touch your files.
2. Initialise the Example Site
npm run init
This creates site/ with a sample gallery, config files, pages, and a blog post. You can skip this step if you prefer to start from scratch.
3. Add Your Content
Photos
Create a gallery by adding an entry to site/config/galleries.yaml:
galleries:
- slug: street
title: Street Photography
description: Moments from the city
listed: true
Then drop your photos into the matching folder:
mkdir -p site/content/photos/street
cp ~/Pictures/best-of/*.jpg site/content/photos/street/
Obscura handles the rest — resizing, WebP conversion, thumbnails, EXIF extraction. When you build, it auto-generates a sidecar YAML file for each photo, pre-filled with whatever metadata your camera embedded.
Blog Posts
Create a Markdown file in site/content/posts/ with a bit of frontmatter:
---
title: My First Shoot
date: 2026-03-20
tags:
- street
summary: A morning walk through the city with a camera.
---
Your text goes here. You can embed photos from any gallery
using a shortcode:
{{</* photo "street/morning-light" */>}}
The welcome post has a working example you can use as a starting point.
4. Fill In Your Metadata
The interactive sidecar editor walks you through each photo with a preview:
npm run sidecar
It prompts for title, location, caption, and tags — the things your camera doesn't know. Press Enter to skip any field. You can also edit the YAML files by hand if you prefer.
5. Build and Preview
npm run dev
Open http://localhost:3000. Your site rebuilds automatically when you change files — photos, posts, and pages alike.
When you're happy, build for production:
npm run build
The output lands in dist/ — plain static files ready to deploy anywhere.
What's Next
- Deploy your site — rsync to your own server, or push to GitHub Pages, Netlify, or Cloudflare Pages. The Five-Minute Deploy post walks through each option.
- Customise your config — Edit
site/config/site.yamlto set your site title, URL, and display preferences. The Content Model Reference covers all the options. - Write a blog post — Create a Markdown file in
site/content/posts/and use photo shortcodes to embed your images. The welcome post shows you how. - Stay up to date — Everything under
site/is yours — config, posts, pages, and metadata. Only large photo binaries are gitignored. Updating Obscura is justgit pull && npm install. Your content is never affected.
Optional: Fork Instead of Clone
If you'd like to contribute back to Obscura — or prefer a fork-based workflow — you can fork the repository instead of cloning it directly. Since everything under site/ except photo binaries can be committed, your config, posts, pages, and sidecar metadata travel with your repo. Add the original repo as an upstream remote to pull engine updates:
git remote add upstream https://github.com/jemayer/obscura.git
git fetch upstream && git merge upstream/main
This is entirely optional. A plain clone works perfectly for most workflows.