This is the static site generator that creates the digital gardens at:
gemini://gem.travisbriggs.com
A Digital Garden is like a blog, as it's a place to share personal thoughts, projects and other things on the web (or on Gemini). However it differs in that it is setup more as a graph of nodes that are connected and evergreen instead of a dreaded reverse chronological ordering of "posts". For more information on Digital Gardens, see the post that inspired me by Maggie Appleton.
This static site generator is built off the awesome template Eleventy Garden by Binyamin Aron Green. That in turn uses the awesome Eleventy static site generator, which is more or less a clone of Jekyll in Javascript that winds up being more flexibile and more easily extensible.
npm install
npm run devnpm testRuns build-integration tests that build both the www and Gemini site into
temp directories. They set DISABLE_MASTODON=1 so no statuses are posted.
That's a standing warning worth generalizing: any ad-hoc build should set
DISABLE_MASTODON=1 unless you actually intend to post to Mastodon.
The tests inject throwaway fixture files (zz-test-fixture.*) into the
source tree and clean them up afterwards. Two safeguards make a leaked
fixture (from a crashed test run) harmless: the fixture node carries
testFixture: true frontmatter, which the Mastodon-posting code refuses to
post for, and npm run build / deploy_gemini.sh sweep leaked fixture
files away before building (scripts/preflight-fixtures.js).
Drop image files in assets/img/garden/ and reference them from a node's
markdown with . On www, images are
run through @11ty/eleventy-img to produce responsive variants, and the
first image in a node's body becomes that node's og:image (an absolute
URL, falling back to the site avatar if the node has no images). On Gemini,
images render as => link lines and the original files are shipped
alongside the capsule content.
scripts/suggest-links.js uses Claude Code with your Claude subscription
to suggest wikilinks and cross-references between garden notes. Install
the Claude Code CLI and sign in with claude auth login using your
subscription account, not a Console/API account.
node scripts/suggest-links.js # all notes
node scripts/suggest-links.js --limit 5 # first 5 notes
node scripts/suggest-links.js --node now # one note by slug
node scripts/suggest-links.js --out /tmp/link-suggestions.htmlThe default output is link-suggestions.html; garden files are never
modified. Each note is analyzed with Opus and consumes your subscription
allowance. The script ignores inherited API credentials and does not load
.env; it checks for a subscription login before analyzing notes.
Claude runs in safe mode with tools and MCP servers disabled, so local
hooks and plugins do not participate. Use a current Claude Code version
with --safe-mode and --json-schema support. Any subscription extra-usage
billing you have enabled still applies.
First, build the site. Warning: this will create a Mastodon post for every new garden node, assuming you have a MASTODON_API_KEY entry in a top-level .env file.
npm run buildNext deploy to Netlify (--prod to skip the preview step):
netlify deploy --prod -d _siteFinally, commit the code and push to Github (left to the reader). It's important that this step is last, because the comments.sqlite3 (where the Mastodon ids for node comments live) database is commited as part of the repo, and will be out of date if the repo is pushed before deploying.
The Gemini capsule is hosted on a Hetzner box using the Agate server, with Let's Encrypt certificates auto-renewed via Cloudflare DNS-01. Agate serves each vhost from /srv/gemini/content/<hostname>/. To deploy the Gemini site, run:
npm run deploy-geminiThis runs Eleventy in Gemini mode and rsyncs the built _gemini/ tree into the gem.travisbriggs.com content root on the box. Defaults (host gem.travisbriggs.com, user root, key ~/.ssh/id_skynet, dest /srv/gemini/content/gem.travisbriggs.com) can be overridden with the GEM_HOST, GEM_USER, GEM_KEY, and GEM_DEST env vars.
There's a local-only CMS for editing garden content, vibe coded with Claude. It's a Vue 3 SPA with an Express backend that reads and writes the markdown files in garden/ directly.
cd cms
npm install
npm run dev:all
# Open http://localhost:5173Features: sortable/filterable file list, frontmatter form with quality/importance dropdowns, CodeMirror 6 markdown editor with [[wikilink]] autocomplete, image upload (drag-drop, paste, or the 📷 toolbar button), and new page creation with slug auto-generation. Run npm run dev in the repo root alongside it if you want the preview links to work.
If you're in this section, I'm sad for you. You probably want to first delete all existing comments. Then run:
node create_comments_db.jsFinally, follow the build and deploy steps above.
0 comments
log in to comment.