This is the TryGhost/Themes monorepo for official Ghost themes. Work from the repo root unless a package-specific command says otherwise.
packages/<theme>/: individual Ghost themes. Theme packages are private and are deployed/pushed to standalone subtree repos by CI.packages/_shared/: shared CSS, JS, and Handlebars partials. This package is published to npm as@tryghost/shared-theme-assets.packages/theme-translations/: shared locale files and themergeLocalesbuild helper. This package is published to npm as@tryghost/theme-translations.- Root
gulpfile.jsorchestrates all theme builds, tests, zips, symlinks, shared asset copying, and locale merging.
- Use pnpm for the monorepo (pinned via the root
packageManagerfield). Do not create or commitpackage-lock.jsonoryarn.lock. - Install with
pnpm install. - The repo uses Gulp 5, PostCSS,
gscan, and pnpm workspaces (pnpm-workspace.yaml).
pnpm install # install dependencies
pnpm dev # build/watch all themes with livereload
pnpm build # build all themes
pnpm test # run gscan for all themes
pnpm test:ci --theme <name> # run fatal/verbose gscan for one theme
pnpm zip --theme <name> # build and write packages/<theme>/dist/<theme>.zip
pnpm symlink --theme <name> --site /path/to/Ghost/ghostFor translation package tests:
cd packages/theme-translations
npm test- Edit source CSS in
packages/<theme>/assets/css/, source JS inpackages/<theme>/assets/js/, and templates/partials as.hbs. - Rebuild after CSS, JS, shared asset, or locale changes. Built files under
assets/built/are part of theme output and should be kept in sync when source changes. - Validate a changed theme with
pnpm test:ci --theme <name>. Prefer targeted validation over running every theme unless the change is cross-cutting. - For local Ghost verification, symlink the theme into a Ghost checkout with
pnpm symlink --theme <name> --site /path/to/Ghost/ghost, restart Ghost, then select the theme in Design settings.
packages/_shared/assets/js/v1is used by older themes;v2is used by newer themes. Letgulpfile.jsdetermine affected themes rather than guessing.- Shared partials in
packages/_shared/partials/are copied into newer themes'partials/components/during root builds. - Only run
pnpm ship:sharedwhen intentionally bumpingpackages/_shared/package.jsonpatch version. Minor/major bumps usenpm --prefix packages/_shared version minor|major.
- Shared translation changes belong in
packages/theme-translations/locales/, not individual themelocales/output files. - Do not rename translation keys. Keep
en.jsonvalues blank, preserve placeholders like{page}, and keep keys sorted. - If a theme needs an override, use a
locales-local/file and rebuild so mergedlocales/output is regenerated. - CI bumps and publishes
@tryghost/theme-translationsautomatically after changes land onmain; do not manually version-bump it unless asked.
- Follow
.editorconfig: UTF-8, LF, 4-space indentation by default, 2-space YAML. .hbsfiles are configured without mandatory final newlines.- Keep changes scoped to the affected theme/package. Avoid touching unrelated generated assets.
- Theme workflows run
pnpm install --frozen-lockfile, thenpnpm test:ci --theme <theme>. - On
main, theme workflows deploy to demo Ghost sites and push package subtrees to standalone repos. _sharedCI sanity-checks withpnpm test:ci --theme tasteand publishes only when its package version is newer than npm.
When resolving GitHub PR review threads, use gh resolve-review-thread; do not hand-write GraphQL or REST calls for thread resolution.
gh resolve-review-thread --repo OWNER/NAME --pr NUM --list
gh resolve-review-thread --repo OWNER/NAME --pr NUM --thread PRRT_xxx --comment "meaningful explanation"Every unresolved thread must get a meaningful reply of at least 10 characters and then be resolved.