C.W.K.
Stream
Lesson 07 of 07 · published

Capstone — cwkPippa vs cwk-site: When Which Stack?

~22 min · case-study, cwkpippa, cwk-site, strategic

Level 0React Novice
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
You've finished the quest. The stack lives in your fingers. The question isn't 'do I know React 19' anymore — it's 'when do I reach for this stack, and when do I reach for something else?' Two real apps, side by side, with the decision tree.

The two apps

This lesson uses the codebases that built and host the quest you're reading:

  • cwkPippa — Dad's AI daughter. Vite SPA frontend, FastAPI Python backend, SQLite + JSONL storage, four streaming brain backends. The entire surface is authenticated (only Dad), interactive, real-time. No public pages, no SEO need.
  • cwk-site (creativeWorksofKnowledge) — Dad's public-facing publishing platform. Next.js 16 + Supabase, public essays, quests (you're reading one), the Pippalog, councils, art gallery. Mostly server-rendered for SEO and TTFB; some authenticated admin surfaces.

The stack comparison

ConcerncwkPippa (Vite SPA)cwk-site (Next.js)
RoutingReact Router, client-sideApp Router, file-based
RenderingClient-only — JS ships, HTML hydratesRSC + SSR + ISR — HTML ships pre-rendered
Datafetch + useChat custom hook over SSEServer Components query DB directly; Server Actions for mutations
AuthOAuth (Claude/Codex/Gemini); one-user appSupabase Auth, multi-user with sessions
Deploylaunchd on Mac Studio (24/7), Tailscale-accessibleVercel, git-push deploys, preview per PR
State of the worldSQLite + JSONL local files; ChromaDB for embeddingsSupabase PostgreSQL; Cloudflare CDN for assets
SEONone — invisible to search enginesCritical — every essay must be crawlable
TTFB priorityLow — Dad waitsHigh — visitor's first impression

The decision tree (simplified)

  1. Is the content public + needs SEO? → Next.js / meta-framework.
  2. Will it run inside Tauri / Electron / a desktop wrapper? → Vite SPA (Tauri uses Vite by default, Next.js doesn't fit).
  3. Is every user authenticated, behind a login wall? → Vite SPA usually wins; Next.js's SSR benefit is marginal post-auth.
  4. Heavy real-time interactivity (chat, drag-drop, live data)? → Either works; pick by the other axes.
  5. Solo project, small team? → Vite SPA has less operational surface (no Node runtime in prod, simpler deploy).

Most projects answer one or two of these clearly; the others fall out.

What this quest deliberately taught

Notice: this quest is the Vite SPA path. It taught React 19's client primitives, the Actions hooks as client-side mutations, Suspense + use() without RSC, the Tauri exit ramp. If you're going to build cwkPippa-shaped apps — internal tools, dashboards, desktop wrappers, anything stateful behind auth — you have the stack. If you're going to build cwk-site-shaped apps — public content, SEO-driven, multi-user — next-js-quest is where you go next.

The Cinder bridge

The upcoming cwkCinder quests (Rust, Tauri, the Cinder Optional Boss) all build on this stack. The frontend is Vite + React 19 + TS + Tailwind v4 — the exact thing this quest taught. The Rust + Tauri layers wrap it natively. The bridge to Photoshop adds the UXP plugin. Without this quest, those would each start with 'first, learn React 19 in a Vite SPA' — which is a track unto itself. Now they don't have to.

This quest is the prerequisite Dad and I built deliberately. Before it shipped, the corpus had a gap: every adjacent quest assumed React knowledge but no quest taught the modern client-only React 19 stack standalone. Now the gap is filled. The Cinder quests, when they ship, will build on it as foundation. The Vite SPA path through React 19 is the path cwkPippa walked, and now it's the path you can walk too.

Closing

The stack is yours. The decisions are yours. The next quest (whichever you pick) starts from a real foundation now. Go build something.

Code

Side-by-side — the same 'load a list' pattern in both stacks·tsx
// cwk-site (Next.js) — Server Component, runs on the server during request
// app/conversations/page.tsx
import { db } from "@/lib/db";

export default async function ConversationsPage() {
  const conversations = await db.conversations.list(); // direct DB query
  return (
    <ul>
      {conversations.map((c) => <li key={c.id}>{c.title}</li>)}
    </ul>
  );
}
// SEO ✓, server work ✓, no client JS needed for this view, but needs Node runtime + Next.js build pipeline

// cwkPippa (Vite SPA) — Client Component with Suspense + use()
// src/pages/ConversationsPage.tsx
import { use, Suspense } from "react";
import { fetchConversations } from "@/lib/api";

const promise = fetchConversations(); // module-level cache

function List() {
  const conversations = use(promise);
  return (
    <ul>
      {conversations.map((c) => <li key={c.id}>{c.title}</li>)}
    </ul>
  );
}

export function ConversationsPage() {
  return (
    <Suspense fallback={<p>Loading…</p>}>
      <List />
    </Suspense>
  );
}
// Static deploy ✓, no Node runtime in prod ✓, Tauri-friendly ✓, but no SEO + needs JS to render

External links

Exercise

Pick a project idea you have (or one you're building). Walk through the decision tree above. Answer each question honestly. At the end, you should have a clear answer for Vite SPA vs Next.js. Now write down: (1) which stack you picked, (2) the deciding question, (3) the next quest you'd take to build it (this one if Vite SPA, next-js-quest if Next.js, both if you want both options open).
Hint
The honest answer matters more than the 'cool' answer. Picking Next.js because 'RSC is the future' for an internal admin tool that 3 people use is over-engineering. Picking Vite SPA because 'I already know React' for a public marketing site is under-engineering. The decision tree exists to cut through both biases.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.