askesis
Docs Self-hosting & configuration

Docs / More

Self-hosting & configuration

Run Askesis yourself: setup, environment variables and push reminders.

Run it locally

git clone https://github.com/Romflz/askesis-project.git
cd askesis-project
pnpm install
cp .env.example .env          # then set BETTER_AUTH_SECRET (openssl rand -base64 32)
pnpm db:up && pnpm db:push    # start Postgres in Docker, push the schema
pnpm dev                      # web on :3000, API on :4000

You need pnpm 12 and Docker. Node is pinned in package.json and downloaded by pnpm. For local development, pnpm db:push applies schema changes straight to the database.

Environment variables

Everything lives in one .env at the repository root.

VariablePurpose
DATABASE_URLPostgres connection string.
BETTER_AUTH_SECRETSecret for sessions, at least 32 characters.
WEB_ORIGINPublic URL of the web app. Auth cookies are issued for it, so sign in on this origin.
API_HOST, API_PORTWhere the API listens.
API_URLWhere the web server reaches the API (server-side only).
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECTOptional. Enables daily push reminders.

Push reminders

pnpm --filter @askesis/api vapid   # prints a VAPID key pair for .env

Add the keys and a contact address (VAPID_SUBJECT=mailto:[email protected]) to .env, then restart the API. It checks every two minutes and sends each subscribed user one reminder per study day. Browsers only allow push and service workers over HTTPS (localhost is the exception).

How it fits together

PartRole
apps/webTanStack Start: server-rendered pages, server functions, the PWA files.
apps/apiFastify: REST endpoints, Better Auth, grading, imports and the reminder job.
packages/coreScheduling (SM-2 and FSRS), dashboard stats, XP and trophies, CSV.
packages/dbDrizzle schema for Postgres.
packages/contractsZod schemas shared by web and API, including the default preset.

The browser only talks to the web app. Its server functions call the API with the user’s session cookie, and /api/auth is proxied to the API so cookies stay on one origin.

Production

  • Use versioned migrations instead of push: run pnpm db:generate with every schema change and commit the SQL in packages/db/migrations. The API applies pending migrations each time it starts, so a deploy updates the database by itself; pnpm db:migrate does the same on demand.
  • pnpm build builds the web app with Nitro. Set NITRO_PRESET to target Node, Bun, Vercel, Netlify, Cloudflare and others.
  • Serve both apps over HTTPS so sign-in cookies, the service worker and push work.