A tribute to our friend Jack, who wants to haunt for you after he passes. Tell him who to haunt — he'll handle the rest.
🌐 Live at jackhaunts.us
Jack is dying — but he's not done working. This site lets friends submit Haunt Requests: tell Jack who or what to haunt on your behalf, and he'll get right to it once he's crossed over. While he can still review them, every request gets his personal attention.
Once Jack passes, the site flips to Haunting mode: the form closes, and the Wall of Haunts becomes a record of his active work.
Built by friends who love Jack, with accessibility-first design in his honor. He's the expert.
npm install
npm start # starts dev server at http://localhost:8080
npm run build # builds to dist/Submissions come in as GitHub Pull Requests. To publish a haunt:
- Open the PR in GitHub
- Review the request (see checklist in the PR template)
- Change
status: pending→status: approvedin the.mdfile frontmatter - Merge the PR — Cloudflare Pages auto-deploys on merge to
main
To reject a request, close the PR without merging.
- Go to Actions → Toggle Site Mode
- Click Run workflow
- Choose
requestingorhauntingfrom the dropdown - Click Run workflow
This commits a change to src/_data/siteConfig.json and triggers a redeploy.
Edit src/_data/siteConfig.json:
{
"mode": "haunting",
"haunterIsGone": true
}Commit and push to main.
| Secret | Description |
|---|---|
CLOUDFLARE_API_TOKEN |
Cloudflare API token with Pages deploy permission |
CLOUDFLARE_ACCOUNT_ID |
Your Cloudflare account ID |
| Secret | How to set |
|---|---|
GITHUB_TOKEN |
npx wrangler secret put GITHUB_TOKEN — a GitHub PAT with repo scope on this repo |
TURNSTILE_SECRET_KEY |
npx wrangler secret put TURNSTILE_SECRET_KEY — from the Turnstile dashboard (see below) |
Turnstile is the spam-protection widget on the submission form. It requires two keys: a Site Key (public, goes in the site config) and a Secret Key (private, goes in the Worker).
- Go to Cloudflare Dashboard → Turnstile
- Click Add widget
- Name it anything (e.g.
jackhaunts.us) - Add your hostname:
jackhaunts.us - Click Create
Copy the Site Key from the Turnstile dashboard and paste it into src/_data/siteConfig.json:
{
"turnstileSiteKey": "0x4AAAAAAA...your-site-key-here..."
}Commit and push — this value is public and safe to store in the repo.
Copy the Secret Key from the Turnstile dashboard. Never commit this to the repo. Instead, set it as a Worker secret:
npx wrangler secret put TURNSTILE_SECRET_KEY
# Paste your secret key when promptedCreate a Cloudflare Pages project. The projectName should match the one set in .github/workflows/deploy.yml.
npx wrangler pages project create projectNameThe GitHub Actions deploy workflow now deploys both the Pages site and the submission worker on pushes to main.
For first-time setup or manual redeploys:
cd worker
npx wrangler deploy
npx wrangler secret put GITHUB_TOKEN
npx wrangler secret put TURNSTILE_SECRET_KEYThis app is generic by design and released to the public domain (The Unlicense). All Jack-specific content lives in one file:
src/_data/siteConfig.json
Update these fields:
{
"haunterName": "Your person's name",
"haunterPronounSubject": "they",
"haunterPronounObject": "them",
"haunterPronounPossessive": "their",
"siteTitle": "Whoever Haunts Us",
"siteUrl": "https://yourdomain.com",
"tagline": "Your tagline here.",
"description": "Your site description here.",
"turnstileSiteKey": "REPLACE_WITH_YOUR_TURNSTILE_SITE_KEY"
}Then update wrangler.toml with your Worker name and follow the secrets setup above.
The haunt markdown files in src/haunts/ are your content — replace or remove them.
- Static site: Eleventy (11ty) v3, Nunjucks templates
- Hosting: Cloudflare Pages (auto-deploy on push to
main) - Form pipeline: Cloudflare Worker → GitHub API → Pull Request
- Spam protection: Cloudflare Turnstile + honeypot field
- Accessibility CI: pa11y-ci at WCAG2AAA on every PR
- Mode toggle: GitHub Actions
workflow_dispatch - License: The Unlicense (public domain)