hsiegeln 2ec4a86e3d
Some checks failed
ci / build-test (push) Failing after 5m24s
ci: skip app.cameleer.io in linkinator (auth host)
CI's lint:links step started failing while app.cameleer.io is in
maintenance — linkinator follows the sign-in/sign-up CTAs out to
the Logto host and surfaces transient 502s as build failures.

The skip list already covered auth.cameleer.io but missed the
app.cameleer.io rename from commit fa12df8. Add it alongside
the other internal hosts.

Trade-off: CI no longer catches a real breakage of the auth URLs.
Acceptable because (a) the auth host has its own deploy gates,
(b) maintenance windows there should not red-bar marketing-site
deploys, (c) the site's middleware/header tests still verify the
URL shape via the auth.test.ts schema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:52:37 +02:00

cameleer-website

Marketing site for cameleer.io — zero-code observability for Apache Camel.

This is a static Astro 5 site. Hosted on Hetzner Webhosting L, fronted by Cloudflare, deployed via Gitea Actions.

Development

npm ci
npm run dev       # http://localhost:4321
npm run test      # vitest — auth config + middleware header tests
npm run build     # produces dist/
npm run preview   # serves dist/

Quality gates (run in CI)

npm run lint:html     # html-validate on dist/
npm run lint:links    # linkinator on dist/
npm run lh            # Lighthouse CI (>=0.95 on all 4 categories)

Environment variables

See .env.example. All are PUBLIC_* (build-time, embedded in HTML).

Var Purpose
PUBLIC_AUTH_SIGNIN_URL Logto sign-in URL (redirected to by "Sign in" buttons)
PUBLIC_AUTH_SIGNUP_URL Logto sign-up URL (redirected to by "Start free trial")
PUBLIC_SALES_EMAIL Sales email (mailto: target for "Talk to sales")

Deployment

Manual trigger only. Merging to main does NOT auto-deploy. To ship: Gitea → Actions → deploy → Run workflow on main. The workflow runs tests, builds, then rsyncs dist/ to Hetzner over SSH (ed25519 key on port 222, host-key-pinned), and post-deploy curls the live site to verify security headers.

Rollback: trigger the deploy workflow on the previous main commit (Actions UI lets you pick a ref).

Placeholder mode

To put the site into "back shortly" mode, trigger Gitea → Actions → deploy-placeholder → Run workflow. To bring the real site back, trigger Actions → deploy → Run workflow on the desired main commit. Both workflows share the deploy-production concurrency group, so they can never run simultaneously.

The placeholder is hand-authored static HTML in placeholder/ and does NOT depend on npm/astro build — it is deliberately decoupled from the main build so it can ship even when that build is broken.

Scope note. The placeholder serves HTTP 200 (not 503), so Cloudflare's edge will cache it normally. This is fine for short planned maintenance windows. For longer outages or incident fallback, purge Cloudflare's cache (or set a short-TTL Cache Rule for the maintenance window) before triggering recovery via deploy.yml, otherwise the edge may serve the placeholder past recovery until TTL expires.

Security headers (HSTS, CSP, X-Frame-Options, etc.) are owned by Cloudflare Transform Rules, not by anything in this repo. Hetzner Webhosting L ignores file-based .htaccess (AllowOverride None), so origin-side header config is impossible from code. See OPERATOR-CHECKLIST.md §2.

See OPERATOR-CHECKLIST.md for the one-time Hetzner + Cloudflare setup.

Design & plan

  • docs/superpowers/specs/2026-04-24-cameleer-website-design.md — the approved spec.
  • docs/superpowers/plans/2026-04-24-cameleer-website.md — the implementation plan that built this repo.
Description
Marketing website for cameleer.io — zero-code observability for Apache Camel. Astro 5 static site on Hetzner, Cloudflare-fronted, Gitea-Actions-deployed.
Readme 3.2 MiB
Languages
Astro 72.3%
TypeScript 15.7%
JavaScript 6.6%
HTML 4.2%
CSS 1.2%