Architecture
A Master app is a decoupled full-stack monorepo. The browser talks to a Next.js frontend; the frontend talks to a MasterController API; the API talks to your database through the MasterRecord ORM. The Master CLI scaffolds all of it and runs the whole stack with one command.

The stack, top to bottom#
The App Router UI users actually see and touch. Server Components fetch data, Client Components add interactivity. This is where everything comes together visually.
A fast ESM MVC server. Routes map URLs to controllers; controllers return JSON. Handles auth, validation, security, and real-time sockets.
Code-first models and an expressive query language over SQLite, MySQL, or PostgreSQL. Migrations keep the schema in step with your models.
Next.js: how the front end ties it all together#
In a Master app, Next.js is the entire front end — not a sprinkle of client widgets, but the real, full App Router framework. It is the one place your users meet your application, and it pulls the whole stack into a single, coherent experience.
Server Components fetch from your API#
Most pages are React Server Components. They run on the server, call your MasterController API directly (no CORS, no client round-trip), and stream finished HTML to the browser — fast first paint, SEO-friendly, no loading spinners for the initial view.
import { api } from '../lib/api';
export default async function PostsPage() {
// Runs on the server — talks straight to MasterController.
const { data } = await api<{ data: Post[] }>('/posts');
return <ul>{data.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;
}Client Components add interactivity#
Anything interactive — forms, live updates, optimistic UI — is a 'use client' component that calls the same API from the browser. One typed helper, app/lib/api.ts, is the single doorway between the front end and the back end.
'use client';
import { api } from '../lib/api';
async function createPost(title: string) {
return api('/posts', { method: 'POST', body: JSON.stringify({ title }) });
}One helper, one contract#
Because every call flows through api(), the boundary between frontend and backend is explicit and typed. Change the API base URL once (via NEXT_PUBLIC_API_URL) and the whole front end follows — local, staging, or production.
The life of a request#
- A user opens
/postsin the browser → Next.js renders the page. - The Server Component calls
api('/posts')→ an HTTP request to MasterController. - The router dispatches to
posts#index; the controller runsdb.Post.toList(). - MasterRecord builds and runs the SQL, returns model instances.
- The controller replies with
this.returnJson(...); Next.js renders the HTML and streams it back.
Why decoupled?#
- Independent scaling & deployment — host the Next.js front end on the edge and the API on a Node host; scale each to its own load.
- Clean separation of concerns — UI code never touches SQL; API code never renders HTML.
- Reusable API — the same MasterController API can serve a mobile app or third party, not just your website.
- One dev experience — despite being two services,
master devruns them together with shared config and hot reload.