- Astro 52.8%
- TypeScript 42.4%
- CSS 4.5%
- Dockerfile 0.2%
- JavaScript 0.1%
| .astro | ||
| dist | ||
| docs | ||
| migrations | ||
| node_modules | ||
| public | ||
| research | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| astro.config.mjs | ||
| docker-compose.deploy.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| MASTER-PLAN.md | ||
| package.json | ||
| PAGES-BRIEF.md | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
Ekaii Hosting — hosting.ekaii.fr
Independent European hosting platform: VPS & dedicated (resold Hetzner, automated), managed web/WordPress/Minecraft/SaaS on our own hardware in France, storage, domains, and an AI build service. Radical pricing with published margins, card + Bitcoin + Lightning + Monero, no-JS/Tor-friendly checkout, AI-crawlable.
Live: https://hosting.ekaii.fr — deployed on herbesvertes behind Coolify's Traefik.
Stack
- Astro 5 SSR (Node adapter, standalone) — pages render server-side, work with JavaScript disabled.
- Postgres 17 — orders, services, events, prices, build briefs.
- pg-boss worker — provisioning queue, Hetzner price sync (6h), stale-order expiry.
- Stripe / BTCPay / Monero payment rails, all env-gated (a rail is hidden until configured).
- Design system in
src/styles/(OKLCH, warm-dark ekaii brand + acid-green price accents, Fraunces + Rubik + IBM Plex Mono, self-hosted).
Layout
| Path | What |
|---|---|
src/lib/catalog/products.ts |
Typed product catalog (source of truth) |
src/lib/catalog/landings.ts |
Per-category landing copy (FR/EN) |
src/lib/catalog/pricing.ts |
Hetzner live-cost → public price (margin, cached in DB) |
src/lib/catalog/compare.ts |
Dated competitor price snapshot (from research/) |
src/lib/payments/ |
stripe / btcpay / monero — each *Enabled() gated |
src/lib/provisioning/ |
pg-boss queue + drivers (hetzner auto, coolify, manual) |
src/pages/ |
Public pages, /commander/[slug], /commande/[token], /admin, /api/* |
src/content/guides/ |
Docs guides (content collection) |
migrations/ |
SQL migrations (applied on web boot) |
Run locally
pnpm install
docker run -d --name pg -e POSTGRES_USER=hosting -e POSTGRES_PASSWORD=pw -e POSTGRES_DB=hosting -p 5432:5432 postgres:17-alpine
export DATABASE_URL=postgres://hosting:pw@localhost:5432/hosting SESSION_SECRET=dev ADMIN_PASSWORD=dev
pnpm build && node --experimental-strip-types scripts/migrate.ts && pnpm start
Deploy (herbesvertes)
docker-compose.deploy.yml — web + worker + db, web joins the coolify network with Traefik labels (host hosting.ekaii.fr, LE cert). Deploy dir: /srv/fast/services/hosting-ekaii. .env holds secrets (never committed).
rsync -az --exclude node_modules --exclude dist --exclude .git ./ herbesvertes:/srv/fast/services/hosting-ekaii/
ssh herbesvertes 'cd /srv/fast/services/hosting-ekaii && docker compose -f docker-compose.deploy.yml up -d --build'
Configuring rails / provisioning (post-launch)
Set in .env on the server, then redeploy:
STRIPE_SECRET_KEY+STRIPE_WEBHOOK_SECRET→ card rail. Webhook:POST /api/stripe/webhook.BTCPAY_URL+BTCPAY_STORE_ID+BTCPAY_API_KEY+BTCPAY_WEBHOOK_SECRET→ BTC/LN. Webhook:POST /api/btcpay/webhook.MONERO_ADDRESS→ XMR rail (manual confirmation via/adminuntil wallet-rpc watcher wired).HETZNER_TOKEN(dedicated project) → automated VPS provisioning + live price sync.COOLIFY_URL+COOLIFY_TOKEN→ managed-stack deploys.UMAMI_WEBSITE_ID→ first-party analytics.
Until a rail is set it is hidden from checkout and orders fall back to the manual/quote queue in /admin.
Legal
Pages under /mentions-legales, /cgv, /confidentialite, /dpa, /abuse are drafts (noindex, visible "brouillon" banner) with [placeholders] for the operator to complete and have reviewed before commercial launch.