Documentation menu
Vercel + Supabase private beta
The owner selected this topology on 2026-10-22. The Next.js app runs on Vercel; Supabase provides PostgreSQL. Memtru retains its existing password/session and API-token authentication. Supabase Auth and browser database access are not used.
Current state (2026-10-22)
The hosted beta is live at https://memtru.com (MEMTRU_PUBLIC_URL). The domain is
registered at Cloudflare and keeps Cloudflare DNS: the apex A records and the
www CNAME point to Vercel with proxying off, and www redirects to the apex.
https://memtru.vercel.app still serves the app, but the CLI and browser sessions
should use the canonical domain (same-origin checks compare against it).
- Supabase project
zyveakirlpxoftlajmko(organization "DevAtzma's Org", regionap-south-1, PostgreSQL 17). Migration0001_memtru.sqlis applied; thememtru_appruntime role has LOGIN with a generated password that exists only in Vercel'sDATABASE_URL. - Vercel project
memtru(teammemtru), root directoryapps/web, Node 24.x, Production variables:DATABASE_URL(transaction pooler, port 6543),DATABASE_SSL_CA,MEMTRU_SIGNUP=open(public registration since 2026-10-22, rate-limited per client address),MEMTRU_PUBLIC_URL.vercel.jsonno longer pinsMEMTRU_SIGNUP; without the variable, production stays closed.MIGRATION_DATABASE_URLis also present in Vercel at the owner's request; the application does not read it. The administrator password it contained was rotated afterwards, so it no longer authenticates. - Remote TLS verification uses the Supabase Root 2021 CA (
DATABASE_SSL_CA). Without it Node rejects the pooler certificate (SELF_SIGNED_CERT_IN_CHAIN). - The operator account was provisioned with
admin:provision; the owner created the first organization through onboarding. - Git-triggered deployments require the commit author to map to a GitHub account on the Vercel team; commits authored by an unknown identity are blocked.
- Verified on 2026-10-22 against https://memtru.com: 36 hosted checks (database role privileges, row-level security, migration checksum, session cookie flags, cross-organization and cross-origin denial, real CLI uploads, idempotency, token revocation, membership removal) passed with synthetic accounts that were deleted afterwards. A read-only, application-schema backup was encrypted locally and restored into an in-memory PostgreSQL; all 13 tables matched. This is not a substitute for a provider-level restore into a separate project.
Database setup
- Inspect the project's schemas, roles, exposed API schemas and backup settings.
Preserve existing objects. If
memtruormemtru_metaalready exists, stop and reconcile its history before applying this application's migrations. - Obtain an operator direct or session pooler connection from Supabase's
Connect dialog. Set
MIGRATION_DATABASE_URLonly in a protected operator environment. Do not store it in the repository or in Vercel runtime variables. - From
apps/web, runnpm run db:migrate:postgres. Versioned SQL lives indb/postgres. Migrations use one transaction, an advisory lock and a checksum ledger. They never run from an HTTP request or duringnext build. - The migration creates a private
memtruschema and amemtru_approle withNOLOGIN. Through a protected database administration session, enable LOGIN with a newly generated password for this role. Store that password directly in the deployment's encrypted secret configuration, never in a chat or SQL file. Do not reuse the project's administrator password. - Runtime
DATABASE_URLuses the transaction pooler, custom usernamememtru_app.<project-ref>, the actual pooler host from Connect and port- Percent-encode credentials when constructing URLs. Do not guess the region or pooler hostname from the project reference.
TLS certificate validation is mandatory for remote connections. Supply Supabase's
root CA (downloadable from the project's database settings) as the server-only PEM
DATABASE_SSL_CA; do not disable verification. Named prepared statements and
session-persistent tenant context are not used, so transaction pooling is safe.
The runtime role has DML privileges only in the application schema. RLS is enabled
on every application table; its policy permits the trusted server role. Tenant
authorization remains enforced by Memtru's services, not by per-user RLS claims.
Untrusted roles have no schema access. Keep memtru and memtru_meta out of the
Supabase Data API's exposed schemas, and never grant the browser memtru_app.
Optional local-data cutover
Do not assume that the local SQLite database should be uploaded. Inspect data
ownership first. A new beta can start empty and use admin:provision for the
verified operator account.
When preserving the local application's data is required:
- Stop local writes and create an integrity-checked snapshot using
db:backup. - Set
SQLITE_IMPORT_PATHto that snapshot and keep the operator migration URL. - Run
npm run db:import:sqliteto rehearse. This executes the actual inserts, foreign keys and count checks, then rolls everything back. - Inspect the count-only result. Run
npm run db:import:sqlite -- --applyfor the actual cutover. It refuses to merge into any populated application table. The source is opened read-only. Account/password hashes, organization roles, token hashes/revocations and report contents are preserved. Existing browser sessions are invalidated so local sessions cannot become public sessions. - Verify sign-in, report contents, token revocation and cross-organization denial before allowing the cohort to use the new site. Retain the source snapshot.
Vercel project
- Import the existing private GitHub repository. Root directory:
apps/web. - Keep Include source files outside of the Root Directory in the Build Step
enabled: the published Markdown lives in the repository's
docs/directory. Next.js tracing explicitly includes those files in the documentation functions. - Node.js:
24.x. Framework: Next.js. Install:npm ci. Build:npm run build. The repository includesapps/web/vercel.json; use default Next.js output. - Set encrypted, server-only
DATABASE_URLto the runtime role's pooled URL. - Set
MEMTRU_SIGNUP=closedandMEMTRU_PUBLIC_URLto the approved HTTPS origin. - Never set
MEMTRU_INSECURE_COOKIESon Vercel. - Keep Preview and Production variables separate. Previews must use an isolated database, never a production connection copied into all environments.
- Initially deploy the reviewed branch to Preview with platform access protection. Promote the verified revision only after the hosted checks below pass. Keep registration closed for the private beta.
Without DATABASE_URL, Vercel requests fail instead of creating an ephemeral
SQLite file. Build-time rendering does not migrate or seed a database. No Supabase
administrator key, anonymous key or browser SDK is required for this topology.
Hosted checks and operations
Before inviting users, verify on the actual HTTPS origin: /api/health, secure
cookies, same-origin mutations, closed signup, provisioned operator login and
onboarding, synthetic CLI upload/read/idempotency, foreign organization denial,
revoked token denial, and rate limiting across independent requests.
All service transactions share a PostgreSQL advisory lock during this controlled beta. Database write triggers acquire the same lock, including administrative membership changes. This intentionally preserves the single-writer authorization ordering of the tested SQLite implementation. It is not a high-throughput scaling claim. Query/lock deadlines are set inside transactions. Pools use at most three connections each and close idle clients after ten seconds. Review pooler client capacity and metrics under realistic Vercel concurrency before expanding access.
Rate-limit buckets are atomic PostgreSQL rows with hashed keys, expiration and bounded cleanup. They survive cold starts and are shared across instances. A database failure does not fall back to an uncoordinated local limiter.
Choose backup retention and restore objectives based on the actual Supabase plan;
PITR is not assumed. Rehearse restoring a database backup into a separate project.
Reconcile revoked credentials and password changes before reopening traffic after
restore. SQLite's db:backup command explicitly refuses cloud configurations.
Keep previous compatible application revisions for rollback. Do not roll back to the earlier synchronous SQLite-only build while pointing at PostgreSQL. Do not drop schemas or overwrite existing Supabase data as a rollback technique.