What is your app named?
- my-applowercase, digits, . _ -
Becomes both the folder and the name in package.json, so it is checked for the characters those allow - and refuses a directory that already has files in it.
pass the name as an argumentOne command. Newest Next.js, colour generated from your brand HEX, motion tokens, and docs your agent reads. No Tailwind.
npx @larsen-utvikling/create-next-app my-appScaffolds Next.js 16.3.0 - resolved when you run it, never pinned
$npx @larsen-utvikling/create-next-app
Done. cd my-app && npm run dev
Why
Not hard work. Just the same work, slightly worse each time, because it was being re-derived from memory.
The flow
Press enter through all of them for a considered default, or pass flags and skip the terminal entirely.
Becomes both the folder and the name in package.json, so it is checked for the characters those allow - and refuses a directory that already has files in it.
pass the name as an argumentSay no and you get a considered black-and-white theme with a blue accent. Say yes and three follow-up questions shape the whole palette.
--hex <color> · omit it for the default themeOne color in. A 12-step accent scale, a 12-step gray scale, semantic colors and both modes out.
--hex 4DA0FFDecides which token names exist - and the generated docs and starter CSS are rewritten to match.
--preset shadcn | radix | css-variablesHSL values keep alpha composition available. Any other format and the docs switch to the color-mix idiom instead.
--format hsl-values | hex | rgb | hsl | oklab | oklchPassed straight through to create-next-app, so you get its official configuration for whichever you pick.
--linter eslint | biome | noneInstalls into .agents/skills/ and symlinks each agent's own directory, so Claude Code, Codex, Cursor and Copilot all see them.
--skills recommended | all | a,comma,list · --no-skillsRuns the install and rewrites the generated README so every command shown is the one you actually type.
--pm npm | pnpm | yarn | bunCommits everything after the overlay, so your first commit is the finished project rather than a bare template.
--no-gitA missing package manager never fails the scaffold - you get the finished app and the command to finish it yourself.
--no-installColour
The generator that runs during install runs here too, imported from the published package - so what you make is byte-for-byte what npx writes.
--background--foreground--primary--accent-9--muted--border--background--foreground--primary--accent-9--muted--bordernpx @larsen-utvikling/create-next-app my-app --hex 4DA0FF/**
* theme.css - color tokens
*
* Generated by @larsen-utvikling/create-next-app (rampkit engine).
* Seed: #4DA0FF | preset: shadcn | format: hsl-values | scheme: analogous
*
* Dark mode follows the OS automatically. Set data-theme="light" or
* data-theme="dark" on <html> to override manually - no JS shipped.
* Regenerate any time by re-running the scaffolder, or edit values freely.
*/
:root {
--background: 0 0% 95%;
--foreground: 210 6% 13%;
--foreground-subtle: 214 3% 44%;
--primary: 212 100% 65%;
--primary-foreground: 215 100% 22%;
--secondary: 214 54% 90%;
--secondary-foreground: 215 100% 22%;
--muted: 210 3% 88%;
--muted-foreground: 210 6% 13%;
--accent: 214 54% 90%;
--accent-foreground: 215 100% 22%;
--destructive: 10 75% 48%;
--destructive-foreground: 0 0% 100%;
--border: 210 4% 73%;
--input: 210 4% 73%;
--ring: 212 100% 65%;
--analogous: 242 78% 65%;
--analogous-foreground: 0 0% 100%;
--complementary: 35 100% 43%;
--complementary-foreground: 210 6% 13%;
/* Accent Scale - Light */
--accent-1: 210 12% 94%;
--accent-2: 212 33% 92%;
--accent-3: 214 54% 90%;
--accent-4: 212 82% 87%;
--accent-5: 213 95% 84%;
--accent-6: 213 95% 78%;
--accent-7: 213 90% 72%;
--accent-8: 212 90% 61%;
--accent-9: 212 100% 65%;
--accent-10: 212 87% 60%;
--accent-11: 210 100% 35%;
--accent-12: 215 100% 22%;
/* Gray Scale - Light */
--gray-1: 0 0% 93%;
--gray-2: 210 5% 92%;
--gray-3: 210 3% 88%;
--gray-4: 220 4% 85%;
--gray-5: 210 4% 81%;
--gray-6: 204 4% 78%;
--gray-7: 210 4% 73%;
--gray-8: 210 5% 66%;
--gray-9: 206 3% 48%;
--gray-10: 214 3% 44%;
--gray-11: 216 3% 33%;
--gray-12: 210 6% 13%;
/* Semantic Colors - Light */
--success: 145 75% 52%;
--success-foreground: 139 47% 18%;
--success-muted: 133 40% 86%;
--success-muted-foreground: 139 47% 18%;
--success-border: 137 43% 58%;
--danger: 10 75% 48%;
--danger-foreground: 0 0% 100%;
--danger-muted: 10 40% 89%;
--danger-muted-foreground: 10 56% 23%;
--danger-border: 11 59% 70%;
--warning: 35 75% 50%;
--warning-foreground: 0 0% 0%;
--warning-muted: 31 91% 86%;
--warning-muted-foreground: 33 69% 19%;
--warning-border: 32 73% 60%;
--info: 250 75% 51%;
--info-foreground: 220 10% 94%;
--info-muted: 231 47% 91%;
--info-muted-foreground: 242 54% 29%;
--info-border: 232 89% 79%;
}
@media (prefers-color-scheme: dark) {
:root {
--background: 0 0% 6%;
--foreground: 210 6% 93%;
--foreground-subtle: 210 2% 49%;
--primary: 212 100% 65%;
--primary-foreground: 212 54% 7%;
--secondary: 212 66% 16%;
--secondary-foreground: 212 100% 90%;
--muted: 210 3% 13%;
--muted-foreground: 210 6% 93%;
--accent: 212 66% 16%;
--accent-foreground: 212 100% 90%;
--destructive: 10 75% 48%;
--destructive-foreground: 0 0% 100%;
--border: 210 3% 28%;
--input: 210 3% 28%;
--ring: 212 100% 65%;
--analogous: 242 78% 65%;
--analogous-foreground: 0 0% 100%;
--complementary: 32 78% 65%;
--complementary-foreground: 26 24% 6%;
/* Accent Scale - Dark */
--accent-1: 212 54% 7%;
--accent-2: 213 42% 10%;
--accent-3: 212 66% 16%;
--accent-4: 210 94% 19%;
--accent-5: 211 81% 25%;
--accent-6: 211 67% 31%;
--accent-7: 212 60% 38%;
--accent-8: 212 60% 46%;
--accent-9: 212 100% 65%;
--accent-10: 212 87% 60%;
--accent-11: 212 100% 73%;
--accent-12: 212 100% 90%;
/* Gray Scale - Dark */
--gray-1: 210 6% 6%;
--gray-2: 210 4% 10%;
--gray-3: 210 3% 13%;
--gray-4: 200 4% 16%;
--gray-5: 210 2% 19%;
--gray-6: 210 3% 23%;
--gray-7: 210 3% 28%;
--gray-8: 210 3% 38%;
--gray-9: 210 3% 43%;
--gray-10: 210 2% 49%;
--gray-11: 210 3% 71%;
--gray-12: 210 6% 93%;
/* Semantic Colors - Dark */
--success: 145 75% 52%;
--success-foreground: 137 24% 6%;
--success-muted: 136 41% 13%;
--success-muted-foreground: 135 74% 82%;
--success-border: 139 48% 28%;
--danger: 10 75% 48%;
--danger-foreground: 0 0% 100%;
--danger-muted: 10 56% 14%;
--danger-muted-foreground: 11 86% 89%;
--danger-border: 10 51% 35%;
--warning: 35 75% 50%;
--warning-foreground: 26 23% 6%;
--warning-muted: 31 43% 12%;
--warning-muted-foreground: 31 84% 88%;
--warning-border: 33 52% 28%;
--info: 250 75% 51%;
--info-foreground: 228 100% 92%;
--info-muted: 239 49% 22%;
--info-muted-foreground: 228 100% 92%;
--info-border: 239 45% 47%;
}
}
[data-theme="light"] {
--background: 0 0% 95%;
--foreground: 210 6% 13%;
--foreground-subtle: 214 3% 44%;
--primary: 212 100% 65%;
--primary-foreground: 215 100% 22%;
--secondary: 214 54% 90%;
--secondary-foreground: 215 100% 22%;
--muted: 210 3% 88%;
--muted-foreground: 210 6% 13%;
--accent: 214 54% 90%;
--accent-foreground: 215 100% 22%;
--destructive: 10 75% 48%;
--destructive-foreground: 0 0% 100%;
--border: 210 4% 73%;
--input: 210 4% 73%;
--ring: 212 100% 65%;
--analogous: 242 78% 65%;
--analogous-foreground: 0 0% 100%;
--complementary: 35 100% 43%;
--complementary-foreground: 210 6% 13%;
/* Accent Scale - Light */
--accent-1: 210 12% 94%;
--accent-2: 212 33% 92%;
--accent-3: 214 54% 90%;
--accent-4: 212 82% 87%;
--accent-5: 213 95% 84%;
--accent-6: 213 95% 78%;
--accent-7: 213 90% 72%;
--accent-8: 212 90% 61%;
--accent-9: 212 100% 65%;
--accent-10: 212 87% 60%;
--accent-11: 210 100% 35%;
--accent-12: 215 100% 22%;
/* Gray Scale - Light */
--gray-1: 0 0% 93%;
--gray-2: 210 5% 92%;
--gray-3: 210 3% 88%;
--gray-4: 220 4% 85%;
--gray-5: 210 4% 81%;
--gray-6: 204 4% 78%;
--gray-7: 210 4% 73%;
--gray-8: 210 5% 66%;
--gray-9: 206 3% 48%;
--gray-10: 214 3% 44%;
--gray-11: 216 3% 33%;
--gray-12: 210 6% 13%;
/* Semantic Colors - Light */
--success: 145 75% 52%;
--success-foreground: 139 47% 18%;
--success-muted: 133 40% 86%;
--success-muted-foreground: 139 47% 18%;
--success-border: 137 43% 58%;
--danger: 10 75% 48%;
--danger-foreground: 0 0% 100%;
--danger-muted: 10 40% 89%;
--danger-muted-foreground: 10 56% 23%;
--danger-border: 11 59% 70%;
--warning: 35 75% 50%;
--warning-foreground: 0 0% 0%;
--warning-muted: 31 91% 86%;
--warning-muted-foreground: 33 69% 19%;
--warning-border: 32 73% 60%;
--info: 250 75% 51%;
--info-foreground: 220 10% 94%;
--info-muted: 231 47% 91%;
--info-muted-foreground: 242 54% 29%;
--info-border: 232 89% 79%;
}
[data-theme="dark"] {
--background: 0 0% 6%;
--foreground: 210 6% 93%;
--foreground-subtle: 210 2% 49%;
--primary: 212 100% 65%;
--primary-foreground: 212 54% 7%;
--secondary: 212 66% 16%;
--secondary-foreground: 212 100% 90%;
--muted: 210 3% 13%;
--muted-foreground: 210 6% 93%;
--accent: 212 66% 16%;
--accent-foreground: 212 100% 90%;
--destructive: 10 75% 48%;
--destructive-foreground: 0 0% 100%;
--border: 210 3% 28%;
--input: 210 3% 28%;
--ring: 212 100% 65%;
--analogous: 242 78% 65%;
--analogous-foreground: 0 0% 100%;
--complementary: 32 78% 65%;
--complementary-foreground: 26 24% 6%;
/* Accent Scale - Dark */
--accent-1: 212 54% 7%;
--accent-2: 213 42% 10%;
--accent-3: 212 66% 16%;
--accent-4: 210 94% 19%;
--accent-5: 211 81% 25%;
--accent-6: 211 67% 31%;
--accent-7: 212 60% 38%;
--accent-8: 212 60% 46%;
--accent-9: 212 100% 65%;
--accent-10: 212 87% 60%;
--accent-11: 212 100% 73%;
--accent-12: 212 100% 90%;
/* Gray Scale - Dark */
--gray-1: 210 6% 6%;
--gray-2: 210 4% 10%;
--gray-3: 210 3% 13%;
--gray-4: 200 4% 16%;
--gray-5: 210 2% 19%;
--gray-6: 210 3% 23%;
--gray-7: 210 3% 28%;
--gray-8: 210 3% 38%;
--gray-9: 210 3% 43%;
--gray-10: 210 2% 49%;
--gray-11: 210 3% 71%;
--gray-12: 210 6% 93%;
/* Semantic Colors - Dark */
--success: 145 75% 52%;
--success-foreground: 137 24% 6%;
--success-muted: 136 41% 13%;
--success-muted-foreground: 135 74% 82%;
--success-border: 139 48% 28%;
--danger: 10 75% 48%;
--danger-foreground: 0 0% 100%;
--danger-muted: 10 56% 14%;
--danger-muted-foreground: 11 86% 89%;
--danger-border: 10 51% 35%;
--warning: 35 75% 50%;
--warning-foreground: 26 23% 6%;
--warning-muted: 31 43% 12%;
--warning-muted-foreground: 31 84% 88%;
--warning-border: 33 52% 28%;
--info: 250 75% 51%;
--info-foreground: 228 100% 92%;
--info-muted: 239 49% 22%;
--info-muted-foreground: 228 100% 92%;
--info-border: 239 45% 47%;
}
/* Document defaults - written for shadcn x hsl-values */
body {
background: hsl(var(--background));
color: hsl(var(--foreground));
}
::selection {
background: hsl(var(--accent-3));
color: hsl(var(--foreground));
}
hr {
border-top-color: hsl(var(--border));
}
Dark mode
Follows the OS, with an attribute for a manual override. No provider, no flash, no hydration cost.
<html data-theme="light">The design system
Small enough to hold in your head, complete enough that you are not inventing spacing values on day three.
--space-14--space-28--space-312--space-416--space-524--space-632--space-748--space-864Heading 1.1
Body copy at 1.5, so a paragraph that wraps to three lines still has room to breathe.
Label 0.05em
Motion
Most starters ship no motion layer, so every project invents its own curves. These are the values larsenutvikling.no already runs.
--duration-press--duration-fast--duration-ui--duration-slow--duration-enterAgent docs
An agent that does not know your conventions invents them, differently every session. These ship with the project.
AGENTS.mdThe project rules every coding agent readsCLAUDE.mdA one-line pointerDESIGN.mdThe token referenceNEXTJS.mdNext.js's own agent guide, preservedREADME.mdGetting started, with a post-scaffold checklistAGENTS.md
Never Tailwind, the token idiom for your chosen palette, the motion rules, and the writing conventions.
Agent skills
Optional, and off by default when unattended. One install covers Claude Code, Codex, Cursor, Copilot and Gemini CLI.
motion-craftDurations, curves, reduced motioninterface-craftLayout, hierarchy, spacing, typeinterface-reviewReview a screen against the rulesui-primitive-pickerThe right primitive for a patternmotion-vocabularyName an effect you can describeliquid-interfaceGlass and refraction effectsprototype-labThrowaway interaction prototypesreverse-engineer-motionRebuild motion from a videoanimated-logo-cycleAnimated brand marks→ .agents/skills/
Unattended
Without a terminal the CLI fails immediately and names the flag that answers the question, instead of hanging on a prompt nobody can see.
npx @larsen-utvikling/create-next-app my-app --defaultsnpx @larsen-utvikling/create-next-app my-app \
--hex 22C55E --preset shadcn \
--pm pnpm --linter biome \
--skills recommended-d, --defaults | Skip every prompt and take the defaults |
|---|---|
--hex <color> | Palette seed, with or without the #. Implies a custom palette |
--preset <name> | shadcn | radix | css-variables |
--format <name> | hex | rgb | hsl | hsl-values | oklab | oklch |
--scheme <name> | analogous | monochromatic | complementary | triadic |
--linter <name> | eslint | biome | none |
--skills <list> | recommended | all | comma-separated skill names |
--no-skills | Skip the skills install |
--pm <name> | npm | pnpm | yarn | bun |
--no-git | Skip git init |
--no-install | Skip the dependency install |
--cna-version <spec> | Pin create-next-app instead of taking the newest |
-v, --version | Print the version |
-h, --help | Show help |
On disk
Nothing to clean up first. The demo page is replaced, the unused assets are gone, and git is initialised with the finished project.
my-app/
├── AGENTS.md project rules for agents
├── CLAUDE.md → @AGENTS.md
├── DESIGN.md token reference
├── NEXTJS.md Next.js agent guide, preserved
├── README.md getting started + checklist
├── .agents/skills/ installed Larsen Skills
├── public/
└── src/
├── app/
│ ├── layout.tsx
│ ├── globals.css one import line
│ ├── page.tsx welcome page, yours to replace
│ └── page.css
└── lib/design-system/
├── index.css
├── core.css spacing · widths · radii · type · z
├── theme.css color, light + dark
├── motion.css durations · curves · reduced motion
└── base.css resetSkills live in .agents/skills/ - see the collection.