Log in
Progress0 / 30 pages0%
V.
Chapter 5 · Day 6–7 · 5 min read

Full Stack Engineering

Full Stack Engineering

Day 6–7 · The whole loop

A forward deployed engineer ships features end-to-end. You will design a schema in the morning, write a backend route at lunch, build the React component in the afternoon, and ship it from a customer's WiFi by evening. There is no "front-end team" to throw it over to.

This chapter is the spine of the bootcamp - the part you'll come back to. We're going to keep it opinionated: one stack, taught well, that you can become productive in by end of Day 7.


Sub-chapter deep-dives

This primer is the spine; two sub-chapters split the stack into its halves. Do both - a forward deployed engineer owns the whole slice:

#Sub-chapterWhat it covers
1FrontendThe browser, React, Next.js App Router, Core Web Vitals, the design-quality bar
2BackendHTTP deeply, REST design, auth, validation, resilience, observability

Outline

  1. The web request lifecycle - browser → DNS → CDN → server → DB → back
  2. HTTP, properly - methods, status codes, headers, cookies, CORS
  3. REST and beyond - designing resourceful APIs; when GraphQL/RPC make sense
  4. Backend: Node + TypeScript (and where Python fits)
  5. Frontend: React + Next.js App Router
  6. State management - server state vs UI state; React Query vs Zustand vs context
  7. Styling - Tailwind, design tokens, accessibility
  8. Auth - sessions, JWTs, OAuth, why "auth is hard" is true
  9. Deployment - Docker, Vercel, fly.io, EC2 - picking right
  10. The full slice - building a feature from schema to UI

101 Primer

What actually happens when a user clicks

text
[Browser]
  │  1. DNS resolves welzin.ai → IP
  │  2. TLS handshake
  │  3. GET / HTTP/2
  ▼
[CDN / Vercel edge]  ← may serve cached HTML/JS
  │  4. Forwards to origin if dynamic
  ▼
[Next.js server]
  │  5. Runs your React Server Component
  │  6. Queries Postgres for data
  │  7. Streams HTML back
  ▼
[Browser]
  │  8. Parses HTML, requests JS bundles
  │  9. Hydrates React on the client
  │ 10. Subsequent navigations are client-side

Understanding this pipeline tells you where to fix slow pages: CDN cache miss? DB query slow? Bundle too big? Hydration blocked?

HTTP, the part interviewers ignore

You will encounter all of these in your first month:

StatusMeans
200 OKgreat
201 Createduse this when POST creates something
204 No Contentsuccess, nothing to return
301/302redirect (permanent / temporary)
304 Not Modifiedclient cache is fine, don't re-send
400 Bad Requestclient's fault, malformed
401 Unauthorizednot logged in
403 Forbiddenlogged in but not allowed
404 Not Founddoesn't exist (or you don't get to know)
409 Conflictconcurrent write, e.g. version mismatch
422 Unprocessable Entityvalid syntax, invalid semantics
429 Too Many Requestsrate-limited
500 / 502 / 503 / 504server problem

Return the right code. 200 { "error": "..." } is an anti-pattern.

REST in one screen

A resource is a noun. The verb is the HTTP method.

text
GET    /api/users             → list users
GET    /api/users/42          → fetch user 42
POST   /api/users             → create a user (body: JSON)
PATCH  /api/users/42          → partial update
PUT    /api/users/42          → replace (rarely what you want)
DELETE /api/users/42          → delete
  • Use plural nouns.
  • Use sub-resources for relationships: GET /api/users/42/orders.
  • Pagination via ?page=2&limit=20 or cursor: ?after=<opaque>.
  • Never put verbs in the URL (/api/getUser).

Backend: Node + TypeScript with Hono or Express

Minimal Hono server:

ts
import { Hono } from 'hono'
import { z } from 'zod'

const app = new Hono()

const CreateUser = z.object({
  email: z.string().email(),
  name: z.string().min(1),
})

app.get('/api/users/:id', async (c) => {
  const id = Number(c.req.param('id'))
  const user = await db.user.findUnique({ where: { id } })
  return user ? c.json(user) : c.json({ error: 'not found' }, 404)
})

app.post('/api/users', async (c) => {
  const body = CreateUser.parse(await c.req.json())
  const user = await db.user.create({ data: body })
  return c.json(user, 201)
})

export default app

Three habits to build:

  1. Validate every input with Zod (or equivalent). Trust nothing from the wire.
  2. Type your DB layer. Prisma, Drizzle, or sqlx. Strings of SQL with manual any returns are how you create incidents.
  3. Errors are first-class. A consistent error shape ({ error: { code, message, details? } }) makes the frontend's life ten times easier.

Python is fine too

For ML-adjacent work, prefer Python with FastAPI. Same Zod-shaped validation via Pydantic. Same opinions.

python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class CreateUser(BaseModel):
    email: str
    name: str

@app.post("/api/users", status_code=201)
def create_user(body: CreateUser):
    return db.users.create(**body.model_dump())

Frontend: React + Next.js App Router

The default Welzin frontend stack:

  • Next.js 15+ App Router for routing and SSR.
  • TypeScript everywhere. any is a code smell.
  • Server Components for data fetching; Client Components when you need state or browser APIs.
  • React Query (TanStack Query) for client-side server state.
  • Zustand for genuinely local UI state that crosses components.
  • Tailwind v4 for styling. No styled-components, no CSS-in-JS, no separate stylesheets per component.

A typical component:

tsx
'use client'

import { useQuery } from '@tanstack/react-query'

export function UserCard({ id }: { id: number }) {
  const { data, isLoading, error } = useQuery({
    queryKey: ['user', id],
    queryFn: () => fetch(`/api/users/${id}`).then(r => r.json()),
  })

  if (isLoading) return <Skeleton />
  if (error) return <ErrorState onRetry={() => location.reload()} />

  return (
    <article className="rounded-lg border p-4">
      <h3 className="text-lg font-medium">{data.name}</h3>
      <p className="text-sm text-zinc-500">{data.email}</p>
    </article>
  )
}

State management, demystified

There are two kinds of state:

  1. Server state - what's on the server. Cached, refetched, possibly stale. Use React Query.
  2. UI state - modals open/closed, form drafts, theme. Lives in components or Zustand.

Treating server data as UI state (sticking it in useState, manually syncing) is the cause of 70% of frontend bugs. Use a server-state library; don't roll it yourself.

Auth - the short, honest version

  • Session-based auth (cookie holding a session ID, session in DB/Redis) - boring, robust, the right default for first-party web apps.
  • JWTs - useful for stateless API auth across services. Annoying to revoke. Don't store them in localStorage if the page is exposed to your own user input (XSS = full account compromise).
  • OAuth / SSO - use a library (NextAuth, Auth.js, Clerk, WorkOS). Do not write OAuth from scratch.
  • Passwords: hash with argon2id or bcrypt. Never store plaintext. Never email a password.

If a customer asks for SSO/SAML, that's WorkOS or similar. The cost is justified.

Deployment, picking right

App shapeUse
Marketing site, dashboard, anything Next.jsVercel
Long-running Node/Python servicefly.io or Render
Stateful workload, custom kernelEC2 + Cockpit (see DevOps chapter)
Background jobsa dedicated worker + queue (BullMQ, Celery, SQS)

Premature Kubernetes is the most expensive mistake a small team can make. Stay on a PaaS until you have a named reason to leave.

The full slice - what we'll build on Day 7

By end of Day 7 you'll have built and deployed:

A "Customer Notes" app. List + detail page. Auth via email magic link. Postgres-backed. One LLM-powered feature (auto-summarise a note). Deployed to Vercel with a live URL.

That single project exercises every concept in this chapter.


Hands-on Checkpoints

  • Read every HTTP status code in the table above without looking it up.
  • Build a Hono (or FastAPI) server with GET, POST, PATCH, DELETE for a notes resource. Validate inputs.
  • Wire it to Postgres via Prisma (or SQLAlchemy).
  • Build a Next.js client that lists notes, opens detail, edits inline. Use React Query.
  • Add auth (NextAuth or Clerk, your call).
  • Deploy to Vercel with a Postgres on Neon or Supabase.
  • Share the live URL in the team channel.

Further reading

Welzin opinion: Pick boring, well-documented tools and master them. A team of five engineers shipping in Next.js + Postgres + Prisma + Tailwind will beat a team of fifteen each using their favourite stack. Boredom is a feature.

Sub-chapters

2 parts
  1. 1.
    Sub-chapter 1
    Frontend
    The browser, React, Next.js App Router, Core Web Vitals, design quality.
    Open sub-chapter →
  2. 2.
    Sub-chapter 2
    Backend
    HTTP deeply, REST design, auth, validation, resilience, observability.
    Open sub-chapter →

Knowledge check

Pass 80% to unlock
0/1 answered
Which HTTP method conventionally creates a new resource in a REST API?