Maintenance

For developers

A short appendix for self-builders — Signal's build commands, tech stack, file map, the i18n workflow, and the stable data-* hook contract.

This page is the short reference for developers customizing Signal from source. Most site editors won't need anything here — uploading the pre-built signal.zip is enough. If you want to fork the theme, change styles at the source level, or rebuild after edits, read on.

Custom code is overwritten on theme update

If you modify theme files directly and then upload an updated signal.zip through Ghost Admin, your changes are erased. Fork the repo, commit your changes to your fork, and rebuild your own zip — don't edit files in place on a production install. For small CSS or JavaScript tweaks, prefer Ghost's Settings → Code injection, which survives theme updates — see Code injection for the stable selectors Signal exposes for exactly this.

Build requirements

  • Node.js v22.12.0 or later
  • Yarn (v1.x)
  • Ghost v6.0.0 or later for the running site that will host the built theme

Tech stack

Signal is built with Vite (bundling), Tailwind CSS v4 (styling, with the typography plugin for episode content), and vanilla JavaScript (no framework) for interactivity — the persistent player, transcripts, chapters, navigation, and Library. Media playback uses Media Chrome for uploaded video and lite-youtube / lite-vimeo facades for embeds. Templates are standard Ghost Handlebars.

Build commands

All commands run from the theme root.

CommandWhat it does
yarn installInstall dependencies.
yarn devVite dev server with HMR. Useful when iterating on CSS or JS in a local Ghost install pointed at the theme directory.
yarn buildProduction build to assets/built/.
yarn lintRuns lint:i18n (translation-parity check) then lint:theme (GScan compliance against Ghost's theme-API expectations).
yarn testAlias for yarn lint.
yarn vitestRuns the unit tests (transcript / chapters parsing and related helpers).
yarn zipRun test + build, then package signal.zip for upload. Excludes node_modules, .git, demo files, scripts, tests, and other source-only files.

File map

The repo's root templates and key partials at a glance.

Templates (root)

FilePurpose
default.hbsMaster layout — the persistent player host (#mp-player-host), routing chrome, and the dark-mode resolver.
index.hbsHomepage: hero (six layouts) plus the platforms band, featured, hosts, guests, about, sponsors, support, and newsletter sections.
post.hbsEpisode page: video/audio hero, tabs (show notes, chapters, transcript, comments, hosts & guests), up-next sidebar.
page.hbsGeneric page wrapper.
page-episodes.hbs, page-blog.hbsThe /episodes/ and /blog/ collection archives.
page-subscribe.hbs, page-guests.hbs, page-hosts.hbs, page-contact.hbs, page-library.hbsThe slug- and route-activated special pages.
tag.hbs, author.hbsTopic and people (guest/host) archives.
error.hbs, error-404.hbsError pages.

Key partials

PartialPurpose
partials/site-header.hbs, site-footer.hbs, mobile-menu.hbsHeader (logo, nav, search, member links), footer, and mobile drawer.
partials/home/*.hbsThe homepage hero variants and sections.
partials/episode/*.hbsThe episode page tabs and components (title block, audio hero, tabs, transcript, chapters, people, up-next).
partials/media/*.hbs, partials/audio-player.hbsThe media stage and audio player.
partials/library/*.hbsThe Library header widget and per-episode bookmark toggle.
partials/icons/*.hbsSingle-path SVG icons, including social brand marks.

Assets

PathPurpose
assets/css/index.cssTailwind v4 entry, design tokens, typography. Feature styles split into components.css, players.css, prose.css.
assets/js/index.jsEntry point — wires the chrome-once and reinit module lifecycles.
assets/js/signal-core/*.jsThe content-swap router, theme resolver, Library stores, watch-progress, and members-form rebinding.
assets/js/media/*.jsThe player engine, media stage, audio player, source extraction, and transcript/chapters parsing.
vite.config.jsVite build config.

i18n workflow

Signal currently ships English only (locales/en.json), and the yarn lint:i18n parity check is enforced — never add a {{t "..."}} call to a template without also adding the matching key to locales/en.json.

  • Add the key to en.json first, then reference it in the template.
  • Use Ghost's interpolation syntax ({{t "Members of {site}" [email protected]}}) instead of string concatenation, so word order stays correct if a locale is ever added.
  • Never hardcode user-visible English in a template.

To translate the interface, a self-builder can add a locale file (for example locales/fr.json) with the same keys; Ghost loads it based on the site's publication language.

The data-* hook contract

Signal's templates carry a documented styling API — the data-region / data-component / data-variant / data-part attributes. If you fork the theme, treat these as public contract: site owners build Code-injection CSS against them, and renaming or removing one breaks that CSS. Add new hooks freely (and document them), but keep existing names stable. The full vocabulary: Hook reference.