# Build a full-stack TypeScript web app with checked access

> Build a private TypeScript reading queue with shared Zod contracts, an Express API, Supabase Auth and owner-only rows, then check the real app and release.

By BIGCHANGE.AI Editorial

Published: 2026-10-23T10:46:14.415Z
Updated: 2026-10-23T10:46:14.415Z
Canonical: https://bigchange.ai/blog/full-stack-typescript-reading-queue-app-guide

![Conceptual charcoal illustration of two separate wooden reading compartments: one open with blank books and the other closed.](https://bigchange.ai/api/media/file/private-reading-queue-compartments-hero-v3.png)
AI-generated conceptual illustration by BIG CHANGE.

TypeScript can catch disagreements between files before a build ships. It cannot tell whether an HTTP request contains an unwanted `user_id`, whether a signed-in person owns a database row, or whether a production email link reaches the right app. This guide takes one small web app through those boundaries: a private reading queue with a browser, API, Auth service and database. The complete, reviewed source is embedded below so you can inspect the actual implementation and adapt it to an app you are authorized to build.

## The big change

- **What changed:** One npm workspace shares Zod request and response schemas between a Vite browser and Express API, while Supabase Auth, SQL grants and row-level security control access to stored items.
- **Why it matters:** The reference gives an AI coding agent a concrete contract to modify and gives the owner observable tests for inputs, ownership, version conflicts and release behavior.
- **What to watch:** Local build and five pure tests passed. Real Supabase sign-in, database permissions, browser behavior and Render deployment remain to be tested in the reader's own accounts.

## Before you start

You need authority over the app's purpose, repository, users, data, development and production Supabase projects, email sender and hosting release. Use permitted synthetic identities and reading items for testing. Have Node 24 and npm 11 for this exact package tree, Python 3.10 or later to reconstruct the embedded source, and a Git and Render account if you intend to release. Check the current [Supabase](https://supabase.com/pricing) and [Render](https://render.com/pricing) plans, limits and spending controls before provisioning anything. The guide does not assume a fixed bill or that your account permits a particular feature.

The example is deliberately specific. An enrolled user can save an HTTP(S) link and title, see their own items, switch an item's read status and delete it. The list displays the newest 100 items and has no pagination. There is no sharing, upload, payment, background job or audit log. Write down any different behavior your real app needs before asking an AI agent to change this code. The goal is an exact, owner-verified app, or a recorded hold where a required check fails.

## 1. Define the contract, then inspect the source

The embedded `reference/` directory has npm workspaces for `packages/contracts`, `apps/api` and `apps/web`, plus `database/001_reading_items.sql`, a lockfile, tests and a blank `acceptance-record.md`. `packages/contracts/src/index.ts` defines `CreateItem`, `ChangeStatus`, `Item` and `ItemList` with Zod. The schemas infer TypeScript types for both sides and validate data at runtime. The create schema admits a trimmed title and HTTP(S) URL; its strict object shape rejects an extra `user_id`. The status request requires `status` and a positive `expectedVersion`. The API checks these shapes again when requests arrive. [Zod's documentation](https://zod.dev/basics) describes parsing and inferred types; [TypeScript strict mode](https://www.typescriptlang.org/tsconfig/strict) only checks the code it can see at compile time.

Inspect the API route and SQL together. Each protected request needs a bearer token. The API creates a caller-scoped Supabase client and asks `auth.getUser(token)` to confirm the user; a browser `getSession()` supplies a token but is not the server's authorization decision. The table grants authenticated access and uses row-level security policies comparing `user_id` with `auth.uid()` for select, insert, update and delete. That database boundary enforces owner isolation for these operations. [Supabase's server Auth](https://supabase.com/docs/reference/javascript/auth-getuser) and [RLS guidance](https://supabase.com/docs/guides/database/postgres/row-level-security) explain the two checks.

The API's status change calls `set_reading_status` with an expected version. Its SQL update matches the caller, item ID and version in one statement, increments the version and returns the complete row. The API validates that returned row, including the private `user_id`, then projects only the public fields into a strict `Item` response. An empty result becomes a generic conflict. This version rule covers the reference API/RPC path. An authenticated owner with direct table write access could update their own row outside that protocol; RLS still bars other owners' rows, but it does not make the version rule universal. The browser's sign-out helper reports success only when Supabase returns no error. Returned errors and rejected calls warn that the session may remain active.

For a different app, settle its actors, enrollment, records, permissions, retention, states and endpoints first. Give a coding agent the exact source revision and ask for a diff against that contract. Require it to explain every change to a field, endpoint, policy, Auth flow or build command. Review the diff and repeat the affected checks yourself. A generated type or successful compile does not establish data access behavior.

## 2. Reconstruct the local reference

The Python block below contains the entire reviewed source, including the lockfile and SQL. Copy every line inside that block to a new UTF-8 file named `restore_reviewed_source.py`. Give it one absolute path to a **new, nonexistent directory** under an existing local directory you control. The command reconstructs files only; it does not install packages, run the app, run SQL, contact a provider or deploy. The script checks its embedded ZIP and all 22 file hashes before creating the output directory. It refuses an existing target. If a write fails partway through, inspect the partial directory; the script never deletes or overwrites it.

On macOS or Linux, replace the example path with your own new path:

```shell
python3 restore_reviewed_source.py /absolute/path/to/new-reference
```

On Windows, use an absolute path under an existing directory you control:

```powershell
py -3 restore_reviewed_source.py "C:\absolute\path\to\new-reference"
```

Expected result: 22 verified files in the new directory's `reference/` subfolder and printed archive SHA-256 `084799240a574810c1902c83a4cac3f6e3b1baa52ef56e173e6a3bb6ff386180`. Keep the script and its output local. Review the dependency list, lockfile, SQL, code and `.env.example` before any further action. If the hash check fails, recopy the entire block from the article. Never edit the base64 to make it pass.

## 3. Set up the development project, build and test the boundaries

Record the approved development Supabase project reference, region, budget, schema, grants, RLS state and migration history. Inspect whether `reading_items` or `set_reading_status` already exists. If the SQL conflicts with existing objects or a migration, stop for an owner-reviewed migration plan. Apply the reviewed `database/001_reading_items.sql` once through your controlled migration route to the confirmed development project, then read back the actual table, constraints, grants, policies and function. The file creates owner-indexed rows, authenticated grants, owner policies and an invoker status function. A successful SQL submission without those readbacks is incomplete.

Configure email sign-in and the exact local redirect origin in Supabase Auth. Enroll two permitted test users under the project's actual policy. The browser requests an email link with `shouldCreateUser: false`; confirm the setting and actual behavior in your project. An API response to that request does not show that mail arrived or that the callback authenticated the right account. Put the confirmed development URL and publishable key into a local `.env` based on `.env.example`; `.env` is Git-ignored. The `VITE_` values are built into the browser and therefore public. This route uses no service-role key. Keep secrets and personal records out of source, browser variables and public evidence.

From the reconstructed `reference/` folder, in an owned Node 24 environment, run:

```shell
node --version
npm ci
npm run build
npm run typecheck
npm test
```

The reviewed packet used Node 24.19.0 and npm 11.17.0 on Windows. `npm ci`, build, typecheck and five pure tests passed with fake syntax-only public configuration; this did not connect to Supabase. The tests cover two request contract cases, two status-response cases using synthetic complete RPC rows, and sign-out success/error/rejection handling. An earlier fake-configuration HTTP smoke saw `/health` and static `/` return 200 and an anonymous `/v1/items` return 401; it was not rerun after the focused repairs. None of those checks proves an authenticated read, RLS enforcement, a real sign-out or a working production app. If your local build fails, save the exact error, Node/npm versions and lockfile hash before changing a dependency or code path.

If you need more detail on one boundary, the earlier guides to [adding sign-in and protected data to a React app](https://bigchange.ai/blog/react-supabase-email-auth-protected-data-guide) and [setting up a managed database](https://bigchange.ai/blog/managed-database-ai-assisted-web-app-guide) address those narrower tasks. This reference uses a Vite TypeScript browser and combines both with an API contract.

Start the API and Vite development server from `reference/` in separate terminals:

```shell
npm run dev:api
```

```shell
npm run dev:web
```

Open the localhost URL Vite reports. Its proxy sends `/v1` requests to Express; the built Express service later serves both API and browser from one origin. Sign in with the first approved identity and record the actual redirect, user, create response, list, reload persistence, status change/version increment and delete. Confirm a successful sign-out clears the session, then cause or observe a failed sign-out and confirm the UI does not say “Signed out” while the session is uncertain.

Use the second approved identity and direct API requests to check the denial boundary: anonymous list GET must return 401; the second user's list must exclude the first user's item, and PATCH or DELETE with the first user's item ID must neither reveal nor alter it. Submit an invalid URL, extra `user_id`, invalid status and stale version. Send two status changes with the same version through the Express API and confirm one increment and one conflict in the actual database. Confirm a successful PATCH response omits `user_id`. Test with 101 synthetic items if complete history matters: this UI returns only the newest 100, so pagination is a required change for a longer queue. Fill the supplied `acceptance-record.md` with observations and evidence; its original blank cells are not results.

## 4. Prepare production before Render's first deploy

Treat production as a separate approved Supabase project. Inspect its migration history and apply/read back the reviewed production schema only with the owner's authority. Confirm enrollment, email sender, exact public redirect origin, backup capability and recovery procedure under the actual plan. Keep development and production project references apart. Do not use a reset command or substitute development data to clear a failed check.

Freeze the reviewed Git commit SHA and branch. Before choosing **Create Web Service** in Render, set the root to `reference/` if your repository nests it, choose Node 24, build `npm ci && npm run build`, start `npm start`, and set health path `/health`. Confirm region, plan, audience, access, production `SUPABASE_URL`, `SUPABASE_PUBLISHABLE_KEY`, `VITE_SUPABASE_URL`, `VITE_SUPABASE_PUBLISHABLE_KEY` and `PORT` if needed. Check every value against the approved production project. Render starts the first build/deploy when the service is created; turning later auto-deploys off does not postpone that initial action. [Render's deployment guide](https://render.com/docs/deploys) documents deploy history and deploying a specific commit. A changed `VITE_` value needs a new browser build.

The separate guide to [deploying an existing web app on Render](https://bigchange.ai/blog/existing-web-app-render-verified-release-guide) covers a broader existing-app inventory. Here the release settings apply to the exact reading-queue source below.

Save the actual deploy ID, live commit, effective build/start/health settings, project reference and URL. Check HTTPS, email delivery/callback, permitted CRUD, anonymous and cross-user denial, stale-version conflict, persistence after reload and relevant logs. `/health` only shows that Express answered; it does not query Auth or the database. Hold acceptance until the real identity and data checks pass. Record the current plan, email, compute, database and backup costs from the accounts you use; the sample has no observed charge.

If a release fails, identify the exact build, health, Auth, RLS or data step and keep its logs and readbacks. A code rollback to a specific commit requires comparing that code with the *current* service variables, environment groups, Supabase schema and Auth settings before deploying it. Code rollback does not undo a migration or restore deleted data. A database restore is a separate, plan-dependent operation requiring its own authority and verification. Repeat permitted and denied user journeys after any approved recovery.

## Complete reviewed source

The following is the full public source delivery. Python 3.10 or later and its standard library are required only to reconstruct the files. Copy the block byte for byte; use a new directory controlled by you. The embedded archive SHA-256 and all 22 file hashes are checked before writing. Source reconstruction does not mean the application has been installed or tested in your account.

```python
#!/usr/bin/env python3
"""Reconstruct the reviewed 22-file TypeScript reference into one NEW local folder.

Python 3.10+ standard library only. This does not install dependencies, execute
application code or SQL, contact a service, or publish or deploy anything.
"""
import base64
import hashlib
import io
from pathlib import Path, PurePosixPath
import stat
import sys
import zipfile

ARCHIVE_SHA256 = "084799240a574810c1902c83a4cac3f6e3b1baa52ef56e173e6a3bb6ff386180"
ARCHIVE_B64 = (
    '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'
    'fXFiSWQFAAAKCwAAHgAAAAAAAAAAAAAApAHuAAAAcmVmZXJlbmNlL2FjY2VwdGFuY2UtcmVjb3Jk'
    'Lm1kUEsBAhQAFAAAAAgAAABXXdijLSA1AQAAYgIAAB8AAAAAAAAAAAAAAKQBjgYAAHJlZmVyZW5j'
    'ZS9hcHBzL2FwaS9wYWNrYWdlLmpzb25QSwECFAAUAAAACAAAAFdd55r/hxIGAACoEgAAIAAAAAAA'
    'AAAAAAAApAEACAAAcmVmZXJlbmNlL2FwcHMvYXBpL3NyYy9zZXJ2ZXIudHNQSwECFAAUAAAACAAA'
    'AFdd7y8GeAoCAAByBAAALgAAAAAAAAAAAAAApAFQDgAAcmVmZXJlbmNlL2FwcHMvYXBpL3NyYy9z'
    'dGF0dXMtcmVzcG9uc2UudGVzdC50c1BLAQIUABQAAAAIAAAAV123W+LttAEAAF0DAAApAAAAAAAA'
    'AAAAAACkAaYQAAByZWZlcmVuY2UvYXBwcy9hcGkvc3JjL3N0YXR1cy1yZXNwb25zZS50c1BLAQIU'
    'ABQAAAAIAAAAV12P4ET5xQAAADkBAAAgAAAAAAAAAAAAAACkAaESAAByZWZlcmVuY2UvYXBwcy9h'
    'cGkvdHNjb25maWcuanNvblBLAQIUABQAAAAIAAAAV11SWXrJtwAAAAMBAAAdAAAAAAAAAAAAAACk'
    'AaQTAAByZWZlcmVuY2UvYXBwcy93ZWIvaW5kZXguaHRtbFBLAQIUABQAAAAIAAAAV12Q7sOC+QAA'
    'ALkBAAAfAAAAAAAAAAAAAACkAZYUAAByZWZlcmVuY2UvYXBwcy93ZWIvcGFja2FnZS5qc29uUEsB'
    'AhQAFAAAAAgAAABXXZy72IzfAAAA1wEAACsAAAAAAAAAAAAAAKQBzBUAAHJlZmVyZW5jZS9hcHBz'
    'L3dlYi9zcmMvYXV0aC1hY3Rpb25zLnRlc3QudHNQSwECFAAUAAAACAAAAFddAaJZr5YAAADbAAAA'
    'JgAAAAAAAAAAAAAApAH0FgAAcmVmZXJlbmNlL2FwcHMvd2ViL3NyYy9hdXRoLWFjdGlvbnMudHNQ'
    'SwECFAAUAAAACAAAAFdd8cf1JTAIAAArFgAAHgAAAAAAAAAAAAAApAHOFwAAcmVmZXJlbmNlL2Fw'
    'cHMvd2ViL3NyYy9tYWluLnRzUEsBAhQAFAAAAAgAAABXXQGI2eHRAAAAQQEAACAAAAAAAAAAAAAA'
    'AKQBOiAAAHJlZmVyZW5jZS9hcHBzL3dlYi90c2NvbmZpZy5qc29uUEsBAhQAFAAAAAgAAABXXc4c'
    'ENdsAQAAiAIAACEAAAAAAAAAAAAAAKQBSSEAAHJlZmVyZW5jZS9hcHBzL3dlYi92aXRlLmNvbmZp'
    'Zy50c1BLAQIUABQAAAAIAAAAV12ldYRutAIAABUIAAAoAAAAAAAAAAAAAACkAfQiAAByZWZlcmVu'
    'Y2UvZGF0YWJhc2UvMDAxX3JlYWRpbmdfaXRlbXMuc3FsUEsBAhQAFAAAAAgAAABXXVRfXfXKSgAA'
    'c2YBABsAAAAAAAAAAAAAAKQB7iUAAHJlZmVyZW5jZS9wYWNrYWdlLWxvY2suanNvblBLAQIUABQA'
    'AAAIAAAAV10uPRS7GwEAANYCAAAWAAAAAAAAAAAAAACkAfFwAAByZWZlcmVuY2UvcGFja2FnZS5q'
    'c29uUEsBAhQAFAAAAAgAAABXXRqLtgbqAAAA1wEAACkAAAAAAAAAAAAAAKQBQHIAAHJlZmVyZW5j'
    'ZS9wYWNrYWdlcy9jb250cmFjdHMvcGFja2FnZS5qc29uUEsBAhQAFAAAAAgAAABXXROSZBxBAQAA'
    'FgMAADIAAAAAAAAAAAAAAKQBcXMAAHJlZmVyZW5jZS9wYWNrYWdlcy9jb250cmFjdHMvc3JjL2Nv'
    'bnRyYWN0cy50ZXN0LnRzUEsBAhQAFAAAAAgAAABXXTaAZaJHAQAA/gIAACkAAAAAAAAAAAAAAKQB'
    'AnUAAHJlZmVyZW5jZS9wYWNrYWdlcy9jb250cmFjdHMvc3JjL2luZGV4LnRzUEsBAhQAFAAAAAgA'
    'AABXXSOYvgjOAAAATgEAACoAAAAAAAAAAAAAAKQBkHYAAHJlZmVyZW5jZS9wYWNrYWdlcy9jb250'
    'cmFjdHMvdHNjb25maWcuanNvblBLBQYAAAAAFgAWAOUGAACmdwAAAAA='
)
EXPECTED_FILES = {
    'reference/.env.example': 'bdd27b4cb05c986cf9a0686d52da07353d2ea78db54696d95dd96e0818fa68f2',
    'reference/.gitignore': 'a459038af144bb649dd32c98f20e160838ec500ed5580fb1669ed0860196e140',
    'reference/acceptance-record.md': 'fd22cbc3604c326f4d835fa1ca89934ce438b7e9da022efc4e2347a48e20912d',
    'reference/apps/api/package.json': '782f94adc230cb8177fd4c35f3ed42a049a88dceb17b670f62700dec8bf8f0af',
    'reference/apps/api/src/server.ts': 'e35aed31ff781c42a584105e4dd0b218d4cc895eae23b13223888e4e4e69ac7e',
    'reference/apps/api/src/status-response.test.ts': '6fc60c449dc52aeeec8353c33929cfb323e41bde604ad8366ea727650db59ab6',
    'reference/apps/api/src/status-response.ts': 'c88955e2225b673ac9aa9d650dbf6d3f1cde35929cd4ec70ca9b17ef2311aaed',
    'reference/apps/api/tsconfig.json': '1c43c49db4250f99b7ecd6ba1d542beb962ea3013f9ee0ab2f1c9cfe5e2ce1c5',
    'reference/apps/web/index.html': '620e74e3d0849e4030230a087e7b3c4598c908f5fbecd7b230f2f7a6f42d9bae',
    'reference/apps/web/package.json': 'fc3d88e763fbd21db3ca3ac451290ed7b404c6b5dddc3ad9f0138b59fcc32f08',
    'reference/apps/web/src/auth-actions.test.ts': '924be2736cb7eeae2ae186950f5edb50401e3c9e9c406a6150c5a92ef43eb4b7',
    'reference/apps/web/src/auth-actions.ts': '8e08b6b98a84ef9c5c4f8bb5af6df33c0b4214d47ba14f2d49978b6f7e90ec42',
    'reference/apps/web/src/main.ts': '305239d8b9c3eac670dbdbaa76658b3f6d5e0dfadc1cd9e02cff3181940e1586',
    'reference/apps/web/tsconfig.json': '1f41b00223b783293f2b9f1f4486070504d57635fc8ee85a04a2a58ec1c0ceb4',
    'reference/apps/web/vite.config.ts': 'caf9f30f5aa80322ee893be099d104f16376f92cc6d05b5969577b9bf5a08813',
    'reference/database/001_reading_items.sql': '50358af2e109fbcb716a3c9b471b908a22fa85bfe0bdb99e9522de0520dd3fcf',
    'reference/package-lock.json': 'f18b20bfad5155ddc3d11bb361da2956bcb7d0efefa8f5f23575e74a544b5383',
    'reference/package.json': 'a8c297bef5ce539daed702fdb3d92c1d5d576469a4fd7151dc143b8d0cb500bc',
    'reference/packages/contracts/package.json': 'fa5157673b451a101bb7f166c5518a1e9d48d32ed35af12633372e30b398a227',
    'reference/packages/contracts/src/contracts.test.ts': '56bdd39742074fec07e1c84e392fbaa74c5addf8584a5c011e278100bf7dd015',
    'reference/packages/contracts/src/index.ts': 'a17294ddf45aa7e37fd6625d837b53361a35fde39ab291204a849f360ca646d1',
    'reference/packages/contracts/tsconfig.json': '52dcc294dde8e99f4b16969e5966d74be878e11453a9aa755a335cda15eba602',
}


def sha256(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


def checked_files() -> dict[str, bytes]:
    raw = base64.b64decode(ARCHIVE_B64, validate=True)
    if sha256(raw) != ARCHIVE_SHA256:
        raise ValueError("Embedded archive SHA-256 differs from the reviewed archive")
    files = {}
    with zipfile.ZipFile(io.BytesIO(raw)) as archive:
        infos = archive.infolist()
        if len(infos) != len(EXPECTED_FILES):
            raise ValueError("Archive member count differs from the reviewed file list")
        for info in infos:
            name = info.filename
            path = PurePosixPath(name)
            if (not name or name.startswith(("/", "\\")) or "\\" in name
                    or ":" in name.split("/")[0] or path.is_absolute()
                    or any(part in ("", ".", "..") for part in name.split("/"))
                    or info.is_dir() or stat.S_ISLNK(info.external_attr >> 16)):
                raise ValueError("Unsafe archive member path/type")
            if name not in EXPECTED_FILES or name in files:
                raise ValueError("Unexpected or duplicate archive member")
            data = archive.read(info)
            if sha256(data) != EXPECTED_FILES[name]:
                raise ValueError("Reviewed file SHA-256 mismatch: " + name)
            files[name] = data
    if set(files) != set(EXPECTED_FILES):
        raise ValueError("Reviewed file list mismatch")
    return files


def main() -> int:
    if len(sys.argv) != 2:
        print("Usage: python3 restore_reviewed_source.py ABSOLUTE_NEW_DIRECTORY", file=sys.stderr)
        return 2
    target = Path(sys.argv[1])
    if (not target.is_absolute() or target.name in ("", ".", "..")
            or (sys.platform == "win32" and (len(target.drive) != 2 or target.drive[1] != ":"))
            or (sys.platform != "win32" and target.anchor != "/")):
        print("Give one absolute path for a NEW output directory", file=sys.stderr)
        return 2
    try:
        parent = target.parent.resolve(strict=True)
        if parent != target.parent or not parent.is_dir():
            raise ValueError("Output parent must be an existing, direct directory without symlink traversal")
        if target.exists() or target.is_symlink():
            raise FileExistsError("Output directory already exists; nothing was changed")
        files = checked_files()  # Validate archive, names, types and every byte before any write.
        target.mkdir(mode=0o700, parents=False, exist_ok=False)
        root = target.resolve(strict=True)
        if root != target or root.parent != parent:
            raise ValueError("Created output resolved outside the explicit parent")
        for name in sorted(files):
            destination = root.joinpath(*PurePosixPath(name).parts)
            destination.parent.mkdir(parents=True, exist_ok=True)
            verified_parent = destination.parent.resolve(strict=True)
            if not verified_parent.is_relative_to(root):
                raise ValueError("Output path escaped the new directory")
            with destination.open("xb") as stream:  # No overwrite, including a symlink.
                stream.write(files[name])
            if sha256(destination.read_bytes()) != EXPECTED_FILES[name]:
                raise ValueError("Written file did not match reviewed bytes: " + name)
        print(f"Created {len(files)} verified source files in {root}")
        print(f"Reviewed embedded ZIP SHA-256: {ARCHIVE_SHA256}")
        print("Source only: no install, app execution, migration or deployment was performed.")
        return 0
    except (OSError, ValueError, zipfile.BadZipFile) as error:
        print(f"Stopped: {error}", file=sys.stderr)
        print("If a new directory was partly created, inspect it; this script never cleans it up or overwrites it.", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
```

## Sources & further reading

- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html) and [strict mode](https://www.typescriptlang.org/tsconfig/strict): compile-time language checks. The shared Zod schemas address runtime values that TypeScript alone cannot inspect.
- [Zod basic usage](https://zod.dev/basics): schema parsing and inferred types used by the reference contracts.
- [Vite guide](https://vite.dev/guide/): browser build and development server. The code pins the version in its lockfile.
- [Express 5 error handling](https://expressjs.com/en/5x/guide/error-handling/): server error route context; the reference's exact behavior is in the embedded source.
- [Supabase server package choice](https://supabase.com/docs/guides/auth/choosing-a-server-package), [`getUser`](https://supabase.com/docs/reference/javascript/auth-getuser), [email OTP](https://supabase.com/docs/reference/javascript/auth-signinwithotp) and [`signOut`](https://supabase.com/docs/reference/javascript/auth-signout): server identity confirmation and the browser Auth calls. Account settings and mail behavior need live checks.
- [Supabase row-level security](https://supabase.com/docs/guides/database/postgres/row-level-security) and [database functions](https://supabase.com/docs/guides/database/functions): grants, owner policies and the status RPC. The guide's version guarantee is scoped to its API/RPC path.
- [Render deploys](https://render.com/docs/deploys): first deployment, deploy history and specific-commit recovery. Check [Render pricing](https://render.com/pricing) and [Supabase pricing](https://supabase.com/pricing) for current plan terms.

## Sources

- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html) — Compile-time language context, distinct from runtime validation.
- [TypeScript strict mode](https://www.typescriptlang.org/tsconfig/strict) — Compiler checks used by the reference; no promise of HTTP or database safety.
- [Zod basic usage](https://zod.dev/basics) — Schema parse and inferred type behavior for shared contracts.
- [Vite guide](https://vite.dev/guide/) — Browser development and build context; exact dependency version pinned in source.
- [Express 5 error handling](https://expressjs.com/en/5x/guide/error-handling/) — API error handling context, while exact route behavior comes from reviewed source.
- [Supabase server package choice](https://supabase.com/docs/guides/auth/choosing-a-server-package) — Caller-scoped base client route versus alternate server package.
- [Supabase getUser](https://supabase.com/docs/reference/javascript/auth-getuser) — Server confirmation of access-token identity.
- [Supabase email OTP](https://supabase.com/docs/reference/javascript/auth-signinwithotp) — Email link request and shouldCreateUser setting; mail and enrollment untested.
- [Supabase signOut](https://supabase.com/docs/reference/javascript/auth-signout) — Browser sign-out error result and session limitations.
- [Supabase row-level security](https://supabase.com/docs/guides/database/postgres/row-level-security) — Grants and per-user table policies, separate from API version guard.
- [Supabase database functions](https://supabase.com/docs/guides/database/functions) — Invoker RPC context; actual SQL is in full delivered source.
- [Render deploys](https://render.com/docs/deploys) — First deploy, deployment record and specific-commit recovery.
- [Render pricing](https://render.com/pricing) — Current host plan and usage must be checked; no fixed cost asserted.
- [Supabase pricing](https://supabase.com/pricing) — Current Auth/database/backup plan must be checked; no fixed cost asserted.
