Source for www.dragonapp.com — the marketing site for Dragon App, a small studio reviving beloved, discontinued macOS apps as fast, native, open-source rebuilds.
This repo does not contain any app source. Each app is built in its own repository; this repo only hosts the marketing pages — one landing page per app, in seven languages.
Production Sparkle appcasts are not hosted here. Every app self-hosts its own
feed in its own repository, which the app reads over raw.githubusercontent.com.
Three retired mirrors survive under docs/ as frozen files: they are kept
deliberately as a one-hop bridge for installs older than the release that pointed
SUFeedURL at the app-owned URL, and they are never republished.
The site is served by GitHub Pages from the docs/ folder.
| App | Page | Source repo |
|---|---|---|
| ClipMenu 2 | /clipmenu-2/ | teddychan/clipmenu-2 |
| Yahoo KeyKey 2 | /yahoo-keykey-2/ | teddychan/yahoo-keykey-2 |
| Ice 2 | /ice-2/ | teddychan/ice-2 |
| Spectacle 2 | /spectacle-2/ | teddychan/spectacle-2 |
docs/index.html is the studio hub that links to all of
them. /clipmenu/ and /keykey/ are redirect stubs kept for old links.
docs/ ← published by GitHub Pages
index.html GENERATED studio hub (app cards)
<app>/index.html GENERATED one landing page per app
<locale>/ GENERATED localized pages (es, fr, ja, ko, zh-Hans, zh-Hant)
sitemap.xml GENERATED with hreflang alternates
<app>/appcast.xml frozen, retired Sparkle mirror (3 apps only) — see above
shared/dragon.css source: design system (per-app accent via a <body> theme class)
shared/*.js source: consent banner + i18n runtime
robots.txt, CNAME, favicons, app icons
i18n/ page sources — templates/, apps/, strings/, changelogs/
scripts/cache-bust.sh fingerprints CSS/JS/images before publishing
scripts/fetch-changelogs.py pulls each release's What's New into i18n/changelogs/
Every page under docs/ is generated output. Never hand-edit a generated
page — the next build overwrites it. Edit the sources under
i18n/ instead:
| Source | What it holds |
|---|---|
i18n/templates/*.html |
page structure, with {{ key }} placeholders |
i18n/apps/<slug>.json |
per-app facts; i18n/apps/_index.json lists the apps |
i18n/strings/en-US.json |
English copy — the source of truth, edit this first |
i18n/strings/<lang>.json |
the other six locales |
i18n/changelogs/<slug>.json |
"What's new" data — generated, see below |
docs/shared/dragon.css, docs/shared/*.js, docs/robots.txt, docs/CNAME
and the icons are hand-maintained sources that happen to live under docs/;
those you do edit in place.
Then rebuild and publish:
python3 i18n/build_i18n.py && ./scripts/cache-bust.shRun them in that order and don't touch docs/ afterwards: build_i18n.py
writes asset URLs bare, so cache-bust.sh has to follow it or the ?v=
fingerprints are lost. Commit on a branch and open a PR — never push straight
to main.
i18n/changelogs/*.json is data, not copy. Each app's release CI sends a
repository_dispatch after it publishes, and
refresh-changelogs.yml refetches
every release's whats-new.json asset — the app's own What's New pane, in each
language it ships — reruns the build, and opens a pull request. Merging that
pull request is what publishes the changelog. A weekly scheduled run is a
backstop for a dispatch that never arrived.
To fix wording, fix the app's What's New strings and ship them in its next release. A hand-edit here is overwritten by the next fetch.
Adding a new app = a new i18n/apps/<slug>.json, an entry in
i18n/apps/_index.json, and its copy in i18n/strings/. Neither
docs/sitemap.xml nor docs/robots.txt needs touching: the sitemap is
regenerated by the build, and robots.txt already allows the whole site.
The site content, design, and brand assets are © 2026 Teddy Chan, all
rights reserved — see LICENSE. The repo is public for
transparency, not for reuse. The apps marketed here are licensed separately in
their own repositories. The privacy policy for the website and all apps lives
at https://www.dragonapp.com/privacy.html (generated from i18n/).