Master Guides

Architecture

How the pieces fit — and how Next.js gives your app a face.

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 three Masters united

The stack, top to bottom#

Frontend
Next.js — the face of your app

The App Router UI users actually see and touch. Server Components fetch data, Client Components add interactivity. This is where everything comes together visually.

▼   HTTP / JSON   ▼
Backend
MasterController — the API

A fast ESM MVC server. Routes map URLs to controllers; controllers return JSON. Handles auth, validation, security, and real-time sockets.

▼   queries   ▼
Data
MasterRecord — the ORM

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.

frontend/app/posts/page.tsx (Server Component)
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.

a Client Component
'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.

Why this combination is powerful
You get Next.js’s world-class frontend — Server Components, streaming, image optimization, file-based routing — and a real backend framework with an ORM behind it. No cramming business logic into route handlers, no hand-rolled data layer. The front end stays a front end; the back end stays a back end.

The life of a request#

  1. A user opens /posts in the browser → Next.js renders the page.
  2. The Server Component calls api('/posts') → an HTTP request to MasterController.
  3. The router dispatches to posts#index; the controller runs db.Post.toList().
  4. MasterRecord builds and runs the SQL, returns model instances.
  5. 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 dev runs them together with shared config and hot reload.