A static, dependency-free gallery for the Heimdall
application database. It is a drop-in replacement for the old
https://apps.heimdall.site/ site.
The catalogue is not baked into the page. At runtime the browser fetches
https://appslist.heimdall.site/list.json
(CORS is open) and renders the tiles, so the site never needs to be redeployed
when apps are added or changed upstream.
- Gallery of ~563 app tiles (icon with lettered fallback, name,
Enhancedbadge, light/dark tile styling driven by each app'stile_background). - Live counts: Foundation and Enhanced computed from
list.json; open app-requests read from the GitHub search API, with a graceful link fallback when the API is rate-limited. - Instant client-side search over name + description (hand-rolled, no library).
- Filters: All / Foundation / Enhanced, plus a bonus license filter.
- Click a tile for a hash-routed detail view (
#/app/<appid>) with the description, website, license, a zip download link, and a link to the app's source folder on GitHub. - Prominent Request an app call to action and a Submit an Enhanced app link.
- Dark theme by default (Heimdall's dark-navy aesthetic) with a
prefers-color-scheme: lightvariant, a responsive grid, and accessible semantic HTML (skip link, alt text, keyboard nav, focus states).
.
├── index.html # markup
├── css/styles.css # all styling (dark default + light + responsive)
├── js/urls.js # URL builders, shared by the browser and tests
├── js/app.js # gallery logic (fetch, render, search, routing)
├── tests/verify-urls.js # live smoke test (icon + zip return HTTP 200)
├── favicon.svg # Heimdall mark
├── CNAME # apps.heimdall.site (GitHub Pages custom domain)
├── .nojekyll # tell Pages to serve files as-is
├── package.json # convenience scripts only, no dependencies
└── .github/workflows/deploy.yml
There is no build step and there are no runtime dependencies — just static HTML, CSS, and vanilla JavaScript.
list.json is published by CI from the
linuxserver/Heimdall-Apps
repository (see its index.js). Each app record drives three URLs:
| What | URL pattern |
|---|---|
| App catalogue | https://appslist.heimdall.site/list.json |
| Icon | https://appslist.heimdall.site/icons/<app.icon> |
| Downloadable zip | https://appslist.heimdall.site/files/<app.sha>.zip |
| Source folder | https://github.com/linuxserver/Heimdall-Apps/tree/master/<FolderName> |
<FolderName> is the display name with every non-letter/number character
removed (verified to hold for all apps). These builders live in js/urls.js
so the page and the test share one source of truth.
No tooling is required — open index.html in a browser, or serve it so that
fetch() and relative paths behave exactly as they do in production:
# any static server works; pick one you have
python3 -m http.server 8080 # then open http://localhost:8080
# or
npx --yes serve .Edit index.html, css/styles.css, js/app.js, or js/urls.js and reload.
tests/verify-urls.js fetches the live list.json and asserts that the icon
and zip URLs for both a Foundation app and an Enhanced app return HTTP 200
(it needs network access and Node 18+ for the global fetch):
node tests/verify-urls.js
# or
npm testThe included workflow (.github/workflows/deploy.yml) uploads the repo root as
a Pages artifact and deploys it with actions/deploy-pages on every push to
main. To stand the site up:
-
Create the repository and push this code to it on the
mainbranch:git init git add -A git commit -m "Static Heimdall apps gallery" git branch -M main git remote add origin git@github.com:<org-or-user>/<repo>.git git push -u origin main
-
Enable Pages via GitHub Actions. In the repo, go to Settings → Pages and set Source to GitHub Actions (not "Deploy from a branch"). The first push to
mainthen runs the deploy workflow; watch it under the Actions tab. -
Set the custom domain. Still under Settings → Pages, enter
apps.heimdall.sitein the Custom domain field and save. TheCNAMEfile in this repo already contains that hostname, so Pages keeps it across deploys. -
Point DNS at GitHub. At the DNS provider for
heimdall.site, add aCNAMErecord:apps.heimdall.site. CNAME linuxserver.github.io.(Use whichever GitHub org/user owns the Pages site as the target,
<owner>.github.io. For the linuxserver org that islinuxserver.github.io.) DNS can take a little while to propagate. -
Enforce HTTPS. Once GitHub has validated the domain, tick Enforce HTTPS under Settings → Pages. GitHub provisions the TLS certificate automatically; this may take a few minutes after the DNS check passes.
After that, every push to main redeploys automatically.
MIT.