2. Browser, server, and code map
Learn where code runs, how a page gets its first data, and why a useful interface still needs server checks.
Start with the request
-
The browser requests a route such as
/reviews/[reviewKey]. Next.js selects the page file. - The server resolves the signed-in actor. It checks scope and loads authorized initial data.
- The server returns the page and data. React attaches interaction to the rendered page. This step is called hydration.
-
Client components manage tabs, inputs, drafts, and save status. Later requests use HTTP
handlers under
src/app/api. - The server validates every command and derives the actor again. It does not trust an actor chosen by the browser.
Useful coding terms
| Term | Meaning in Iris |
|---|---|
| TypeScript type | A development-time contract. It catches many wrong shapes, but does not validate an incoming HTTP body. |
| Zod schema | A runtime check of an incoming shape and allowed values. It does not by itself grant permission. |
| React component | A function that describes UI from data and state. Hooks such as useState keep interaction state. |
| Server component | Runs on the server and can obtain initial data without a browser API round trip. |
| Client component | A module marked "use client" that supports browser events and hooks. Initial rendering can still happen on the server. |
| HTTP API | A request/response boundary. GET reads data. POST sends actions in this demo. |
| Store | Code that reads or writes persistent data. A low-level store method is not automatically authorized. |
| Pure function | Produces an output from inputs without database or network work. Calculation and workflow functions are easier to test this way. |
| Migration | A tracked database structure change. It must be deployed in a compatible order with the app. |
Read a small function
A variable names a value. An object groups named values. An array holds a sequence of values. A function takes inputs and returns a result. A module is a file that exports functions or types for another file to import. Follow imports when you trace a feature.
function errorCents(caoCents: number, qcCents: number): number {
return caoCents - qcCents;
}
const result = errorCents(0, 48_800); // -48_800 cents, or -$488
This teaching example shows the error sign convention. The parameter types say both inputs must be numbers during development. The return type says the result is a number. It does not calculate eligibility or check access. The real program does those tasks in separate functions. Keep each responsibility visible when you read generated code.
JSON is a text format for objects, arrays, and simple values. API responses and stored review facts use it. SQL is the language used to query the relational database. Drizzle helps the code construct those queries. A transaction commits a group of database writes together or rolls them back together if one fails.
Map each concern to its files
| Concern | Entry point | What to look for |
|---|---|---|
| Route and initial load | review page | getActor, authorized load, initial prop to workspace. |
| Browser editing | ReviewProvider | Draft state, queued commands, save status, navigation coordination. |
| Transport | review GET/POST | Zod body, actor lookup, server time, saveCommands call. |
| Rules | execute | Access guard and fact/evidence/workflow handler dispatch. |
| Program-specific behavior | calculation and validation | Bound algorithm, policy values, blockers, findings. |
| Database | review store | Append snapshot, update index, append events in one transaction. |
| Shared UI | components notes | Shell, header, navigation and UI controls. |
| App layout and tools | package.json and configuration notes | Pinned/declared versions, scripts, build and database commands. |
Why these technologies were useful
| Choice | Benefit in the demo | Trade-off and production choice |
|---|---|---|
| Next.js + React | One project provides routes, initial server data, UI and APIs. | Framework and browser/server boundaries need care. Keep only if the delivery team and host support it. |
| TypeScript + Zod | Typed commands plus runtime request validation. | Types do not prove policy correctness. Keep contracts and independent tests. |
| Tailwind + Radix-based controls | Fast layout work and reusable dialogs, tabs and inputs. | Dense forms still need manual keyboard and assistive-technology tests. |
| Clerk | Working sign-in and account controls without writing an identity provider. | Production needs agency identity, provisioning and offboarding. Clerk is a candidate, not a settled procurement decision. |
| PostgreSQL + Drizzle | Transactions, uniqueness constraints and explicit queries. | JSON snapshots and projections require size, retention and rebuild controls. |
| Bun + Playwright + Oxlint/Oxfmt | One script set for tests, browser journeys, lint and format. | A new team must verify tool support in its agency build environment. |
| Neon/Vercel-related demo choices | Managed database/storage adapters and hosting-related integration. | Approved region, contracts, network requirements and support may require different hosting. |
These are inferred benefits from the implementation, not a claim that an approved architecture decision record exists for every dependency. Exact current versions are in package.json and bun.lock. Keep the lockfile in reviews. Do not present a dependency count as a maintenance estimate.
Follow one screen without reading every file
- Open the route page and identify which store provides initial data.
- Open the client feature and find the event handler for the action.
- Find its command type in command-schema.ts.
- Follow the API handler, domain handler, and store write.
- Find the tests beside the rule, then the relevant browser journey.
- Explain why each boundary exists. Use the data flow page for a larger map.
Exercise and answer key
A user changes the POST body to claim program_manager. Does hiding the manager buttons protect the system? Where does Iris decide the actor?
Answer
Button visibility only helps the interface. The review route calls getActor from the server session and assigns that actor to the submitted commands. Runtime schemas reject unsupported request shapes. Commands check capabilities, review scope, and state. The server must enforce all of those checks even when the UI looks correct.