Documentation  🇨🇭

Quickstart

From Payrexx checkout to a deployed Swiss-sovereign SaaS in under an hour. Same Next.js you already know — wired against a Swiss + European stack.

🇨🇭 Already CH is the Swiss-sovereign sibling of already. Same Next.js 15 + Supabase + Drizzle code, swapped Stripe → Payrexx, Resend → Infomaniak, Vercel → Exoscale + Coolify, PostHog → Matomo, Sentry → GlitchTip. 16 modules. CHF 199.

Prerequisites

You need these installed before you start. All free.

  • Node.js 20+ — check with node --version
  • pnpm 9+ — install via npm i -g pnpm
  • Docker Desktop — for local Supabase + Caddy + Redis
  • Supabase CLIbrew install supabase/tap/supabase

Cloud accounts: Payrexx (free, Swiss), Infomaniak (CHF 6/mo SMTP), Exoscale (free credit), plus optional Matomo Cloud (or self-host on the same Exoscale VM). All Swiss / EU. No US sign-up needed.

1. Purchase

01
Buy on Payrexx → accept GitHub invite

Buy a Solo (CHF 199) or Team (CHF 399) licence at already-ch.wait-what.shop/#buy-solo. Payrexx handles the checkout — pay with TWINT, PostFinance, Visa, Mastercard, AmEx, Apple Pay, or Google Pay. Swiss VAT (8.1%) is invoiced automatically.

Within 1–2 minutes you'll get a GitHub repository invite via Infomaniak SMTP. Accept it, then click "Use this template" on the private already-ch-template repo to create your own copy.

2. Clone

02
Clone and install
git clone https://github.com/YOUR_USERNAME/YOUR_REPO_NAME
cd YOUR_REPO_NAME
pnpm install

3. Env vars

Copy the example file and fill it in:

cp .env.example .env.local

The minimum to boot locally:

DATABASE_URL
Local: postgres://postgres:postgres@localhost:54322/postgres
NEXT_PUBLIC_SUPABASE_URL
Local Supabase URL after supabase start
NEXT_PUBLIC_SUPABASE_ANON_KEY
Printed by supabase CLI
SUPABASE_SERVICE_ROLE_KEY
Server-only. Inject from macOS Keychain, never commit.
PAYREXX_INSTANCE
Your Payrexx tenant name
PAYREXX_API_KEY
Test mode key from Payrexx dashboard
PAYREXX_WEBHOOK_SECRET
For signed webhook validation
SMTP_HOST / USER / PASS
Infomaniak: mail.infomaniak.com:587

See full env vars reference below.

4. Local dev

04
Start everything
supabase start
pnpm dev

This boots Next.js on localhost:3000, local Supabase on 54322/54323, and the Payrexx webhook tunnel via the included ngrok config. Hit localhost:3000/health to confirm DB + Redis connections.

5. Deploy

Already CH ships a Docker-based deploy flow. Two paths:

A. Exoscale Marketplace (recommended)

Spin up a CHF-billed VM from the pre-built QCOW2 image:

exo compute instance create my-app \
  --template "already-ch-coolify" \
  --zone ch-gva-2 \
  --instance-type standard.medium

The cloud-init script pulls Coolify, wires Caddy with MaxMind GeoIP2 (sets x-geo-country), and seeds the service stack. SSH in, point Coolify at your GitHub repo, click deploy.

B. Bring your own Coolify

If you already run Coolify, import infra/coolify/services.json. The stack defines Next.js, Postgres, Redis, Matomo, GlitchTip, Unleash, and Caddy with sensible defaults.

Payrexx

Payrexx replaces Stripe. Two big differences to keep in mind:

  • No Customer object. We identify the org via referenceId set to orgId during checkout. Webhooks look up the org by that field.
  • Plan key is derived from transaction amount. Keep plan prices unique in config/billing.ts — duplicates make plan derivation ambiguous.

Webhooks are idempotent via the payment_events table. Failed events route to payment_events_failed for /debug-webhook.

// config/billing.ts
export const billingConfig = {
  currency: 'CHF',
  vatRate: 0.081, // Swiss VAT 8.1%
  plans: {
    solo: { amount: 19900, gateway: 'pop-up-solo' },
    team: { amount: 39900, gateway: 'pop-up-team' },
  },
};

Infomaniak SMTP

Transactional email goes through Infomaniak's Swiss-hosted SMTP. Use nodemailer via lib/messaging/index.ts — never call nodemailer directly. The notify(userId, ...) helper handles channel routing (email, in-app, both).

SMTP_HOST=mail.infomaniak.com
SMTP_PORT=587
SMTP_USER=your-infomaniak-mailbox
SMTP_PASS=your-app-password
SMTP_FROM="Already CH <[email protected]>"

Exoscale + Coolify

Exoscale runs the whole stack in Geneva (ch-gva-2) or Zurich (ch-dk-2). Coolify on top gives you push-to-deploy without locking into Vercel.

  • Hosting: Exoscale compute (standard.medium handles dev + staging fine)
  • Postgres: Self-hosted Supabase via the included Docker compose
  • Redis: Exoscale managed Redis (rate limits, queue)
  • Object storage: Exoscale SOS (S3-compatible, CHF-billed)
  • CDN / TLS: Caddy with Let's Encrypt + MaxMind GeoIP2

Matomo

Matomo runs cookie-free on the same Exoscale VM as the app. Because it stores no cookies and uses a daily-rotating fingerprint, no consent banner is required under nFADP or GDPR.

NEXT_PUBLIC_MATOMO_URL=https://analytics.your-domain.ch
NEXT_PUBLIC_MATOMO_SITE_ID=1

The tracker lives in components/providers/analytics-provider.tsx and only runs in production.

nFADP data register

Every personal-data processing activity should appear in the data_processing_activities table. The admin UI lives at /admin/data-register and follows the structure required by Art. 12 nFADP (controller, purposes, legal basis, recipients, retention period, transfers, security measures).

Seed entries for Payrexx, Infomaniak, Supabase, Matomo, and GitHub are pre-loaded. Edit them to match your actual processing, then export the register as PDF for your DPO.

Env vars reference

Public (build-time, baked into the bundle):

  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • NEXT_PUBLIC_MATOMO_URL
  • NEXT_PUBLIC_MATOMO_SITE_ID
  • NEXT_PUBLIC_FRIENDLY_CAPTCHA_SITE_KEY

Server-only (inject from macOS Keychain via ~/.keychain-secrets.sh, never put in .env):

  • DATABASE_URL, DATABASE_URL_DIRECT
  • SUPABASE_SERVICE_ROLE_KEY
  • PAYREXX_API_KEY, PAYREXX_WEBHOOK_SECRET
  • SMTP_PASS
  • MISTRAL_API_KEY (primary AI provider)
  • UNLEASH_API_TOKEN
  • GLITCHTIP_DSN
  • CRON_SECRET, BETTER_AUTH_SECRET

Commands

  • pnpm dev — Next.js + local Supabase + Caddy reverse proxy
  • pnpm test — Vitest unit + integration
  • pnpm test:e2e — Playwright
  • pnpm db:migrate — apply Drizzle migrations
  • pnpm db:seed — synthetic test data
  • pnpm already doctor — verify env vars, DB, Payrexx connection
  • pnpm build — Docker-style standalone build for Coolify

Modules

16 modules ship in Already CH. Same scope as already, with Swiss-stack defaults.

  • Auth (TOTP, passkeys, MFA mandate)
  • Billing (Payrexx + TWINT + Swiss VAT)
  • Multi-tenant orgs + RBAC + RLS
  • Admin dashboard + impersonation
  • Messaging (Infomaniak SMTP + in-app)
  • Background jobs + cron sidecar
  • Security hardening (CSP, headers, Friendly Captcha)
  • Suspicious activity detection
  • AI integration (Mistral primary, US fallbacks optional)
  • Feature flags (Unleash)
  • Observability (GlitchTip, Matomo)
  • Migration assistant
  • nFADP data register (Art. 12)
  • i18n (DE, FR, IT, EN)
  • Growth features (referrals, student discount)
  • Developer experience (CLAUDE.md, doctor, Biome)