Every AI SaaS project starts with the same two days of nothing-interesting: auth, a users
table, an encrypted place to store provider API keys, a Prisma schema. Then you finally get to
the part you actually wanted to build.
I've been working on a CLI (@chimerai/cli) that scaffolds exactly that prefix. This post is
about what it actually writes to disk — not what a landing page would claim — because that's
the only thing that matters when you decide whether to adopt a generator.
The one command
npx @chimerai/cli create my-ai-app
Interactive feature selector. Defaults are auth + RBAC + admin dashboard + analytics; AI
features are opt-in. Flags worth knowing:
chimerai create my-ai-app --yes # no prompts, defaults
chimerai create my-ai-app --sqlite # no Docker needed, DATABASE_URL=file:./dev.db
chimerai create my-ai-app --yes --install # + npm install
--sqlite is the one I'd start with if you just want to look at the code. Without it you get
a docker-compose.yml for PostgreSQL 16 + Redis 7.
What's in the output
my-ai-app/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ ├── api/auth/ # NextAuth routes (if auth selected)
│ └── admin/ # admin pages (if selected)
├── components/ui/ # shadcn/ui components
├── lib/
│ ├── prisma.ts # PrismaClient singleton
│ ├── auth.ts # auth config
│ └── encryption.ts # API key encryption
├── prisma/schema.prisma # only models for selected features
├── .env
├── docker-compose.yml
└── package.json
The generated Prisma schema is additive per feature, which is the part I check first in any
scaffolding tool — if it gives me six models when I asked for two, I stop trusting it:
| Selected | Models added |
|---|---|
| Auth |
User, Account, Session, VerificationToken
|
| RBAC |
Role, Permission
|
| Providers | ModelProvider |
| Prompts | PromptTemplate |
| Analytics | ApiUsage |
Feature dependencies are resolved by the CLI rather than left to you: admin-dashboard
requires RBAC, model-providers requires auth (the encryption key lives in the auth config),
chat-ui requires model-providers, rag requires model-providers.
Stack, stated plainly
- Next.js 14/15 App Router, API routes serve as the backend — no separate Node service
- TypeScript everywhere except the AI service, which is Python (FastAPI + LiteLLM)
- Prisma on PostgreSQL, NextAuth for credentials + OAuth
- Tailwind + shadcn/ui
The split is deliberate: the LLM orchestration layer is Python because that's where the
ecosystem lives (LangChain, FAISS, spaCy), and everything type-safe and user-facing stays
TypeScript. The Next.js side proxies to AI_SERVICE_URL (default http://localhost:8002).
The bit I'd point at as "not boilerplate"
Provider management with encrypted keys, which is the thing everyone re-implements badly:
const response = await fetch('/api/providers', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'OpenAI GPT-4',
provider: 'openai', // | 'anthropic' | 'ollama' | 'custom'
apiKey: 'sk-...',
isActive: true,
}),
});
Keys are stored AES-256 encrypted at rest using ENCRYPTION_KEY from .env, never in the
database in plaintext. provider: 'custom' takes any OpenAI-compatible baseURL, which is how
you wire up a self-hosted vLLM or an OpenRouter-style gateway without the core knowing about it.
You can also add providers through the admin UI and test the connection before using it — small
thing, saves an annoying debugging loop.
RBAC uses resource:action permission strings, checked in API routes:
import { requirePermission } from '@/lib/auth/require-permission';
export async function GET(req: NextRequest) {
const permissionError = await requirePermission('posts:read');
if (permissionError) return permissionError;
// ...
}
admin:* is a wildcard. Roles carry permission lists; there's a seeded admin
(admin@example.com / admin123 — remove it, obviously).
Honest limitations
-
Packages aren't on npm yet.
@chimerai/model-providers,@chimerai/admin-uietc. exist in the monorepo.chimerai createtherefore generates standalone projects with the selected features inlined as code templates — you get readable code you own, not a dependency you can't inspect. For the full monorepo with shared packages you'd clone the repo instead. -
chimerai addrequires Next.js 15+ (generated route handlers use the asyncparamsAPI). The CLI detects the version and warns below 15. Standalonecreateoutput runs on port 3001 by default to avoid colliding with another dev server. - The feature set is opinionated toward the SaaS shape (auth, providers, prompts, chat, RAG,
admin). If your app doesn't need that shape, a plain
create-next-appplus a library like LangChain is a perfectly reasonable starting point — pick the generator that matches the problem.
Adding to an existing project instead
You don't have to start from a generated project:
cd my-nextjs-app
npx chimerai add auth
npx chimerai add model-providers
npx chimerai add chat-ui
pnpm install
npx prisma db push && npx prisma db seed
pnpm dev
The CLI finds the project root by walking up for a .chimerai marker, then falls back to a
registry in ~/.chimerai/projects.json, then --dir. In a monorepo, point --dir at the
Next.js app (apps/frontend), not the workspace root — the root has no app/ and no prisma/.
chimerai doctor runs health checks on env vars, DB connectivity, and installed components,
which is mostly there because I forgot to set ENCRYPTION_KEY often enough to be embarrassing.
Next in this series
- Streaming chat: SSE from FastAPI through a Next.js proxy route
- RAG with
chimerai add rag— FAISS index, chunking, and the/api/rag/queryround trip - Prompt templates in the DB instead of in git, and what breaks when you do that
Repo: github.com/armbur19-collab/chimerai-kickstart · site: chimerai.dev
Top comments (0)