Maintenance

For developers

An appendix for self-builders: Quiet's build commands, stack, file map, the checks that gate a release, the translation workflow, and the stable hook contract.

Most site editors will never need anything here. This page is for developers who want to build the theme from source, add a language, or extend it in a fork.

You do not need any of this to use Quiet

The theme you downloaded is already built. Upload the zip and it works. Everything below is about working on the source.

Build requirements

Node.js22.12.0 or later
Yarn1.x
Ghost6.0.0 or later, for a local preview

Stack

  • Vite for the asset build.
  • Tailwind CSS v4, configured entirely in CSS. There is no tailwind.config.js.
  • Vanilla ES modules. No framework, no jQuery, no Alpine.
  • Handlebars templates, as Ghost requires.
  • Two vendored or bundled front-end pieces: a YouTube facade, a patched Vimeo facade that requests do-not-track, Media Chrome for uploaded video, and PhotoSwipe for the photo viewer.

Build commands

yarn install     # install dependencies
yarn dev         # Vite in watch mode, for use alongside a local Ghost
yarn build       # production assets into assets/built/
yarn lint        # translation parity, contrast sweep, gscan
yarn vitest      # the unit and DOM tests
yarn test        # lint plus vitest
yarn zip         # test, build, and package quiet.zip

The checks that gate a release

yarn lint runs three gates, all of which have to pass:

  • Translation parity (scripts/check-i18n.mjs). Fails if a template uses a string that is not in locales/en.json, if en.json declares a string no template uses, or if any of the other seventeen locale files is missing a key or holds an empty value.
  • Contrast (scripts/check-contrast.mjs). Scores every text colour against the surfaces its own mode puts behind it, in light and dark, and fails on anything below the threshold.
  • gscan, Ghost's own theme validator. Zero errors and zero warnings.

yarn vitest runs 26 test files covering the JavaScript modules, most of them DOM tests against real markup.

assets/built is committed

There is no build step in CI, so whatever is committed under assets/built/ is what a site serves. After any CSS or JavaScript change, run yarn build and commit the result along with the source.

File map

Templates

Sixteen at the root:

FileServes
default.hbsThe shared layout for every template except private
home.hbsThe homepage
index.hbsThe article archive
post.hbsA post, including episodes and films
page.hbsA page, including projects and homepage section pages viewed directly
tag.hbs, author.hbsGhost's tag and author archives
podcast.hbs, videos.hbsThe two collection routes. Not custom templates: they need posts and pagination
custom-contact.hbs, custom-gallery.hbs, custom-newsletter.hbs, custom-projects.hbsThe four templates in the editor's dropdown
error.hbs, error-404.hbsErrors
private.hbsThe door on a password-protected site. Standalone, with inlined CSS, because Ghost blocks theme assets before authentication

Directories

PathHolds
partials/home/The homepage dispatcher and the ten bands, plus the introduction's three layouts
partials/post/Feature image, byline, gate teaser, share row, author card, post navigation, related posts
partials/video/, partials/podcast/, partials/project/The cards and heroes for those three content types
partials/icons/Inline SVG icons
assets/css/index.css (design tokens and base), plus components, prose, koenig, players
assets/js/One module per feature, each with its tests beside it
assets/js/quiet-core/The soft-navigation router, the re-init lifecycle, the progress bar, active-nav
assets/js/media/The video player: stage, sources, controls, artwork
locales/The translation files, en.json first among them
routes.yamlThe optional routing file

Adding a language

No build needed

Translation files are plain JSON and are read at runtime, so adding one does not require a build.

  1. Copy locales/en.json to locales/<code>.json.
  2. Translate the values, leaving the keys and any placeholders ({name}, %number%) alone.
  3. Set Settings → General → Publication language to that code.
  4. Run yarn lint to confirm parity.

Quiet is a left-to-right theme in this release; right-to-left languages are not supported until they have been tested in a future version.

The hook contract

Quiet exposes four attributes as a public styling API: data-region, data-component, data-variant and data-part. The rules, if you are extending the theme:

  • Additive only. Renaming or removing a handle is a breaking change and belongs in the changelog.
  • Do not hook a load-bearing element. Anything a script measures or rebuilds (the menu list, the player host, the photo rails, the masonry walls) gets a wrapper for styling instead.
  • Reserved prefixes: data-mp-, data-nav-, data-quiet-, data-gallery-, data-copy- and data-footer-nav are the theme's own machinery; data-portal, data-members- and data-ghost- belong to Ghost. Two of Quiet's own are authored by customers in code injection (data-quiet-social-links, data-quiet-podcast-links, data-quiet-videos-links and their meta-tag names), so renaming them breaks live sites silently.
  • Every new handle is documented in the hook reference.

Source and licence

The theme is distributed as a zip with the source in it: templates, CSS, JavaScript and locales are all readable and editable. The licence covers what you may do with it, and is in LICENSE.md inside the zip.