export const GH_ACTION_CONTENT = `# Learn more → https://github.com/TryGhost/action-deploy-theme#getting-started name: Build and deploy theme on: push: branches: - main jobs: build: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' - run: npm ci - run: npm run build - name: Deploy theme uses: TryGhost/action-deploy-theme@v1 with: api-url: \${{ secrets.GHOST_ADMIN_API_URL }} api-key: \${{ secrets.GHOST_ADMIN_API_KEY }}`; export const DEFAULT_TEMPLATE_CONTENT = ` {{meta_title}} {{!-- Add preconnect for jsdelivr --}} {{!-- Critical script for dark mode to prevent flash. Replaced during build. --}} {{ghost_head}}
{{> "header"}}
{{{body}}}
{{> "footer"}}
{{ghost_foot}} `; export const POST_TEMPLATE_CONTENT = `{{!< default}} {{#post}}
{{> "feature-image"}}
{{content}}
{{#if comments}}
{{comments}}
{{/if}}
{{/post}} {{!-- Related posts --}} {{#if @custom.show_related_articles}} {{#get "posts" include="authors" filter="id:-{{post.id}}" limit="4" as |related|}} {{#if related}} {{/if}} {{/get}} {{/if}}`; export const INDEX_TEMPLATE_CONTENT = `{{!< default}}
{{#foreach posts}} {{> "card"}} {{/foreach}} {{pagination}}
`; export const PAGE_TEMPLATE_CONTENT = `{{!< default}} {{#post}}
{{#match @page.show_title_and_feature_image}}

{{title}}

{{> "feature-image"}}
{{/match}}
{{content}}
{{/post}}`; export const AUTHOR_TEMPLATE_CONTENT = `{{!< default}}
{{#author}} {{!-- author header --}} {{/author}}
{{#foreach posts}} {{> "card"}} {{/foreach}}
{{pagination}}
`; export const TAG_TEMPLATE_CONTENT = `{{!< default}}
{{#tag}}

{{name}}

{{#if description}} {{description}} {{else}} A collection of {{plural ../pagination.total empty='zero posts' uint='one post' other='% posts'}} {{/if}}

{{/tag}}
{{#foreach posts}} {{> "card"}} {{/foreach}}
{{pagination}}
`; export const ERROR_404_TEMPLATE_CONTENT = `{{!< default}}

404

Page not found

Sorry, we couldn't find the page you're looking for. It might have been moved or deleted.

Back to Home
`; export const CARD_PARTIAL_CONTENT = `
{{#if feature_image}} {{/if}}
{{#primary_tag}} {{name}} {{/primary_tag}}

{{title}}

{{excerpt words="30"}}

`; export const HEADER_PARTIAL_CONTENT = `
{{navigation}}
{{#if @member}} {{t "Account"}} {{else}} {{t "Subscribe"}} {{/if}}
`; export const FOOTER_PARTIAL_CONTENT = ``; export const NAVIGATION_PARTIAL_CONTENT = ``; export const GHOST_CSS_CONTENT = `/* Ghost image styles */ .kg-width-wide img { max-width: 80vw; width: 100%; margin: 2rem auto; } .kg-width-full img { max-width: 100vw; width: 100%; margin: 2rem auto; } .kg-card figcaption { text-align: center; font-size: 0.8rem; margin-top: 0.5rem; opacity: 0.6; }`; export const INDEX_CSS_CONTENT = `@import "ghost.css"; `; export const CRITICAL_CSS_CONTENT = `@import "reset.css"; `; export const CSS_RESET = ` /* https://www.joshwcomeau.com/css/custom-css-reset/ */ /* 1. Use a more-intuitive box-sizing model */ *, *::before, *::after { box-sizing: border-box; } /* 2. Remove default margin */ *:not(dialog) { margin: 0; } /* 3. Enable keyword animations */ @media (prefers-reduced-motion: no-preference) { html { interpolate-size: allow-keywords; } } body { /* 4. Increase line-height */ line-height: 1.5; /* 5. Improve text rendering */ -webkit-font-smoothing: antialiased; } /* 6. Improve media defaults */ img, picture, video, canvas, svg { display: block; max-width: 100%; } /* 7. Inherit fonts for form controls */ input, button, textarea, select { font: inherit; } /* 8. Avoid text overflows */ p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; } /* 9. Improve line wrapping */ p { text-wrap: pretty; } h1, h2, h3, h4, h5, h6 { text-wrap: balance; } `; export const PACKAGE_JSON_TEMPLATE = (name: string) => `{ "name": "${name}", "description": "A new Ghost theme", "version": "0.1.0", "engines": { "ghost": ">=6.0.0" }, "author": { "name": "Example Name", "email": "name@example.com", "url": "https://example.com" }, "license": "MIT", "keywords": [ "ghost-theme", "Ghost", "Theme" ], "config": { "posts_per_page": 25, "image_sizes": { "50": { "width": 50 }, "100": { "width": 100 }, "400": { "width": 400 }, "600": { "width": 600 }, "800": { "width": 800 }, "1000": { "width": 1000 }, "1200": { "width": 1200 }, "1600": { "width": 1600 }, "2000": { "width": 2000 } }, "custom": { "show_related_articles": { "type": "boolean", "default": true } } }, "scripts": { "dev": "gtb dev", "build": "gtb", "lint": "gtb lint", "check": "gtb check", "zip": "gtb zip" }, "devDependencies": { "@royalfig/gtb": "latest", "eslint": "^10.7.0", "@eslint/js": "^10.0.1", "globals": "^17.7.0", "@types/eslint__js": "^9.14.0", "@types/node": "^26.1.1", "typescript": "^7.0.2", "typescript-eslint": "^8.63.0", "stylelint": "^17.14.0", "stylelint-config-standard": "^40.0.0", "stylelint-config-recess-order": "^7.7.0" }, "type": "module" } `; export const ESLINT_CONFIG_TEMPLATE = `{ extends: [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/stylistic", ], rules: { "no-console": 1, }, } `; export const STYLELINT_CONFIG_TEMPLATE = `{ "extends": ["stylelint-config-standard", "stylelint-config-recess-order"], "rules": { "import-notation": null, "hue-degree-notation": "number" } }`; export const DARK_MODE_CRITICAL_JS = `function toggleDarkModeShareButton(newMode: string) { const shareButton = document.querySelector("share-button"); if (!shareButton) { return; } const modeAsBool = newMode === "dark" ? "true" : "false"; shareButton?.setAttribute("dark-mode", modeAsBool); } function autoDarkMode() { if ( window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ) { document.documentElement.dataset.mode = "dark"; } else { document.documentElement.dataset.mode = "light"; } } function setDarkMode() { const prefers = localStorage.getItem("s-dark-mode"); if (prefers) { document.documentElement.dataset.mode = prefers; } else { autoDarkMode(); } } window .matchMedia("(prefers-color-scheme: dark)") .addEventListener("change", (e) => { const prefers = localStorage.getItem("s-dark-mode"); // Abort if user has already set a preference if (prefers) { return; } if (e.matches) { toggleDarkModeShareButton("dark"); } else { toggleDarkModeShareButton("light"); } autoDarkMode(); }); setDarkMode();`; export const DARK_MODE_HANDLER_JS = `export function darkModeHandler() { const darkModeToggleButton = document.querySelectorAll(".s-dark-mode-toggle"); if (!darkModeToggleButton) { return; } const mode = document.documentElement.dataset.mode!; toggleDarkModeShareButton(mode); Array.from(darkModeToggleButton).map((btn) => btn.addEventListener("click", () => { const newMode = invertMode(); toggleDarkModeShareButton(newMode); document.documentElement.dataset.mode = newMode; localStorage.setItem("s-dark-mode", newMode); }) ); } export function toggleDarkModeShareButton(newMode: string) { const shareButton = document.querySelector("share-button"); if (!shareButton) { return; } const modeAsBool = newMode === "dark" ? "true" : "false"; shareButton?.setAttribute("dark-mode", modeAsBool); } export function invertMode() { const currentMode = document.documentElement.dataset.mode!; return currentMode === "dark" ? "light" : "dark"; }`; export const DARK_MODE_TOGGLE_HBS = ``; export const EXTERNAL_ASSETS = [ "*.png", "*.jpg", "*.jpeg", "*.svg", "*.gif", "*.woff", "*.woff2", "*.ttf", "*.otf", ] as const; export const FEATURE_IMAGE_PARTIAL_CONTENT = `{{#if feature_image}}
{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}} {{#if feature_image_caption}}
{{feature_image_caption}}
{{/if}}
{{/if}}`; export const LOCALES_EN_JSON_CONTENT = `{ "Search": "Search", "Subscribe": "Subscribe", "Account": "Account", "Read more": "Read more" }`; export const GITIGNORE_CONTENT = `node_modules assets/built .DS_Store .env`;