Key answer: The reliable way to build Next.js UI with an AI coding assistant is to start from a component source you own — typed, accessible, themable primitives — and have the assistant assemble and adapt them, not invent them from scratch. You keep control of the server/client boundary, the design tokens, and accessibility; the assistant handles the repetitive wiring; a human reviews every boundary decision and interaction state before it ships.
Table of contents
- Why start from components you own
- Server vs client component boundaries
- Dashboards, forms, navigation, sections
- Typed, accessible, themable
- Where a human reviews
- A concrete workflow
- Common mistakes
- FAQ
- Conclusion
Why start from components you own
An AI coding assistant is good at transformation and tedious wiring, and inconsistent at invention. If you ask it to "build a dashboard" from nothing, you get plausible-looking markup that drifts in spacing, naming, and accessibility from one screen to the next. Every regeneration produces a slightly different result, so the codebase never converges on a system.
Starting from a component source you own inverts that. You define the React components once — a Button, Card, Table, NavBar, FormField — with your tokens and your accessibility baked in. The assistant then composes those into pages, adapts props, and wires data. Its output is constrained by primitives that were already reviewed, so quality is inherited rather than re-rolled each time.
This is the difference between an assistant that generates UI and one that assembles your UI. The second is far more maintainable. This is also why AETumi ships components as source you own rather than as generated output — the assistant adapts real, reviewed primitives instead of reinventing them each session.
Server vs client component boundaries
The single decision that most affects a Next.js App Router codebase is where the server/client line falls. Server Components render on the server, ship no JavaScript for themselves, and can fetch data directly. Client Components run in the browser and are the only place hooks like useState, useEffect, and event handlers work.
A practical rule: keep components server by default, and push "use client" as far down the tree as possible — to the smallest interactive leaf. A page and its layout stay server; a dropdown, a form input, or a chart that needs state becomes a small client island.
// app/dashboard/page.tsx — Server Component (no "use client")
import { getMetrics } from "@/lib/data";
import { MetricCard } from "@/components/metric-card"; // server, presentational
import { RevenueChart } from "@/components/revenue-chart"; // client island
export default async function DashboardPage() {
const metrics = await getMetrics(); // runs on the server
return (
<section aria-labelledby="dash-h">
<h1 id="dash-h">Overview</h1>
<div className="grid">
{metrics.map((m) => (
<MetricCard key={m.id} label={m.label} value={m.value} />
))}
</div>
<RevenueChart data={metrics} /> {/* interactivity lives here */}
</section>
);
}
// components/revenue-chart.tsx
"use client";
import { useState } from "react";
export function RevenueChart({ data }: { data: Metric[] }) {
const [range, setRange] = useState<"30d" | "90d">("30d");
// ...render an interactive chart
}
An AI assistant will often reach for "use client" at the top of a file the moment it sees an event handler, dragging an entire page into the client bundle. This is exactly the boundary a human must review. Ask for it explicitly in your prompt: "keep this a Server Component; extract only the interactive part into a client child."
Dashboards, forms, navigation, sections
Most application UI reduces to a few recurring shapes. Give the assistant a clear structure for each and let it fill them from your primitives — the AETumi component set covers these shapes so the assistant has a consistent starting point for each.
- Dashboards: a server layout that fetches, presentational server cards for stats, and small client islands for anything interactive (filters, charts, live toggles). Always specify loading, empty, and error states — they are the ones that get skipped.
- Forms: use the platform. Next.js Server Actions let a form submit to a server function without hand-rolling an API route. Keep the field components client (for validation feedback) and the action server. Wire real labels,
aria-describedbyfor errors, and disabled/pending states. - Navigation: a server nav shell with a small client piece for the active-route highlight (
usePathname) and the mobile menu toggle. Keyboard operability andaria-current="page"are non-negotiable. - Marketing sections: hero, feature grid, pricing, FAQ. These are almost entirely server-rendered and benefit most from owned section components so they stay on-brand instead of looking generically AI-generated.
// A Server Action form — the action runs on the server, the field is a client leaf
// app/settings/page.tsx
import { saveProfile } from "./actions";
import { TextField } from "@/components/text-field"; // client leaf, accessible
export default function Settings() {
return (
<form action={saveProfile}>
<TextField name="displayName" label="Display name" required />
<button type="submit">Save</button>
</form>
);
}
Typed, accessible, themable
Three properties separate components that survive from components that get rewritten:
- Typed: every component has an explicit props interface. TypeScript is also the assistant's best guardrail — when props are typed, the assistant's misuse fails at compile time instead of in production.
- Accessible: real semantic elements (
button,nav,label), a visible focus ring, correct roles and ARIA only where semantics fall short, and keyboard paths for every interaction. AI output frequently producesdivs with click handlers; that is a review item every time. - Themable: colors, spacing, and radius come from CSS variables or design tokens, never hardcoded per component. This is what lets one assistant-assembled page match the next and lets you re-theme without touching component internals. AETumi's Next.js and React components are built to all three standards — typed props, semantic accessible markup, and token-driven theming — precisely so an AI assistant inherits quality instead of guessing at it.
:root {
--color-bg: #ffffff;
--color-fg: #0b0b0c;
--radius: 12px;
}
:root[data-theme="dark"] {
--color-bg: #0b0b0c;
--color-fg: #f4f4f5;
}
.card { background: var(--color-bg); color: var(--color-fg); border-radius: var(--radius); }
Where a human reviews
An AI coding assistant does not reliably produce correct or faithful UI on the first pass — it needs direction and review. Concentrate human attention where mistakes are most expensive:
- The server/client boundary — is
"use client"at the smallest possible leaf? - Data fetching — no secrets or server-only calls leaking into client components; no waterfalls that could be parallelized.
- Accessibility — keyboard reachable, focus visible, labels present, contrast adequate.
- States — loading, empty, and error actually rendered, not just the happy path.
- Tokens — no hardcoded colors or magic spacing that break theming.
Everything else — prop wiring, mapping data to cards, repetitive layout — is where the assistant saves the most time and needs the least scrutiny.
A concrete workflow
1. Establish or import your owned primitives (Button, Card, Table, FormField, NavBar) with tokens and accessibility in place. A starter like AETumi's nextjs-threejs-starter gives you a typed Next.js base to build these on. 2. Describe the screen to the assistant in terms of those primitives and the intended server/client split: "server page, fetch X, render Cards; extract the filter into a client child." 3. Let it assemble. Read the diff for the five review items above before running. 4. Fill states — ask explicitly for loading, empty, and error UI; they are the most commonly omitted. 5. Iterate on real data. Wire the actual fetch or Server Action, then have the assistant reconcile types.
For how this fits into building whole AI-assisted websites rather than single components, see how AI coding assistants build React UIs.
Common mistakes
- Marking a whole page
"use client"because one button needs a handler. - Regenerating a component instead of adapting the owned one, so the design drifts.
- Skipping empty and error states — the demo looks done, production doesn't.
- Hardcoding colors, which quietly breaks dark mode and theming.
- Trusting the assistant's accessibility output without a keyboard pass.
- Fetching in a client component what a server component could fetch directly.
FAQ
Should every interactive Next.js component be a Client Component? No — only the interactive leaf. Keep the page and layout as Server Components and push "use client" down to the smallest child that actually needs state or events. This keeps your JavaScript bundle small.
Can an AI coding assistant decide the server/client boundary for me? It can propose one, but it tends to over-mark components as client. Treat the boundary as a human review decision and state your intent in the prompt.
Why build from owned components instead of generating UI each time? Owned, typed, themable components make every assistant-assembled page inherit the same quality and design, instead of drifting with each regeneration. It is more maintainable and looks less generic. A library like AETumi gives you that owned source up front so the assistant assembles rather than improvises.
Do I still need TypeScript if the assistant writes the code? Yes — arguably more. Typed props catch the assistant's mistakes at compile time and document intent, which makes its output far safer to accept.
Conclusion
Building Next.js UI with an AI coding assistant works best as assembly, not invention: own your typed, accessible, themable components; let the assistant compose and wire them; and keep a human on the server/client boundary, accessibility, and the states that get forgotten. That division of labor gives you speed without the generic drift that comes from regenerating UI on every request. AETumi, an AI-native 3D web platform, provides production-ready Next.js and React components, 3D scenes, and MCP workflows built for exactly this pattern — a source you own and adapt with your AI assistant, buy once and own for life. Start from our React component library, see the plans at aetumi.app/pricing, and give your assistant something solid to build on.
More from the AETumi library
Real, production-ready assets — preview the motion, grab the source.

