This GitHub Action packages and deploys your Ghost theme
from GitHub to a Ghost site through the Ghost Admin API.
-
Generate a set of Ghost Admin API credentials, by configuring a new Custom Integration in Ghost Admin → Integrations.
-
On GitHub, navigate to your theme repository → Settings → Secrets and variables → Actions. Create a secret called
GHOST_ADMIN_API_URLcontaining the API URL and another one calledGHOST_ADMIN_API_KEYcontaining the Admin API Key. Both must be copied exactly from Ghost Admin → Integrations. -
Once your secrets are in place, copy this example config into
.github/workflows/deploy-theme.yml. Then commit and push your changes:
name: Deploy Theme
on:
push:
branches:
- master
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Deploy Ghost Theme
uses: TryGhost/action-deploy-theme@v2
with:
api-url: ${{ secrets.GHOST_ADMIN_API_URL }}
api-key: ${{ secrets.GHOST_ADMIN_API_KEY }}This workflow deploys the theme after every push to master or main. To use a different trigger, see GitHub's workflow trigger documentation.
The with section must provide the API URL and key. Store both values under the repository's Settings → Secrets and variables → Actions, then reference them with the secrets context as shown above. See GitHub's guide to using secrets in GitHub Actions.
| Key | Value Information | Type | Required |
|---|---|---|---|
api-url |
The base URL of your Ghost Admin API, found by configuring a new Custom Integration in Ghost Admin → Integrations | string |
Yes |
api-key |
The authentication key for your Ghost Admin API, found by configuring a new Custom Integration in Ghost Admin → Integrations | string |
Yes |
version |
The minimum Ghost Admin API version the action expects the target site to support. Defaults to v6.0 |
string |
No |
exclude |
A space-separated list of files and folders to exclude from the generated zip file in addition to the defaults, e.g. "gulpfile.js *dist/*" |
string |
No |
theme-name |
A filename-safe custom theme name that overrides the default name in package.json. Useful if you use a fork of Casper, e.g. "my-theme" |
string |
No |
file |
Path to a trusted, built zip file, resolved from working-directory. The path must stay inside the workspace. If set, exclude and theme-name are ignored |
string |
No |
working-directory |
A directory inside the workspace to zip when a theme is in a subdirectory, e.g. packages/my-theme |
string |
No |
💡 Use exclude to reduce the size of the zip file & keep deployment times minimal.
Generated archives reject symbolic links in the theme source so files outside the workspace cannot be packaged accidentally. This applies even when a symlink matches a custom exclude pattern; paths covered by the action's built-in exclusions are ignored. Prebuilt archives supplied with file are uploaded as-is and should come from a trusted build step.
Don't forget to 🌟 Star 🌟 the repo if you like this GitHub Action!
See CONTRIBUTING.md for the development, validation, and release commands.
Copyright (c) 2013-2026 Ghost Foundation - Released under the MIT license.

