Skip to main content

Guide

Kirimase vs Create T3 App CLI 2026

Kirimase vs create-t3-app compared: both scaffold T3 Stack projects but Kirimase adds ongoing CRUD generation. Which CLI tool fits your Next.js workflow.

StarterPick Team

TL;DR

They're complementary, not competitors — and the community knows it. create-t3-app generates your initial Next.js + tRPC + Prisma project scaffold once. Kirimase adds ongoing code generation: run kirimase generate to scaffold Prisma models, tRPC routers, Zod validators, and UI forms throughout development. Think of create-t3-app as your project initializer and Kirimase as your development accelerator. Many teams use both: T3 to start, Kirimase to maintain velocity.

Key Takeaways

  • create-t3-app: ~270K downloads/week, one-time scaffold, the gold standard initial setup
  • Kirimase: smaller but growing, ongoing CRUD generation on top of T3 projects
  • Kirimase init: supports T3 Stack, Next.js + Drizzle, custom configs
  • Kirimase generate: creates Prisma model → tRPC router → Zod schema → UI form in one command
  • DX: Both are CLI-based, Kirimase is more opinionated about the generated patterns
  • Use together: start with create-t3-app, add Kirimase later for feature scaffolding

Create T3 App: The Standard Initializer

npm create t3-app@latest
# Interactive prompts:
#   ✔ What will your project be called? my-saas
#   ✔ Will you be using TypeScript? Yes
#   ✔ Will you be using tRPC? Yes
#   ✔ What authentication provider would you like to use? NextAuth.js
#   ✔ What database ORM would you like to use? Prisma
#   ✔ Would you like to use Tailwind CSS? Yes
#   ✔ What package manager? pnpm
#   ✔ Should we run 'pnpm install' for you? Yes
#   ✔ Initialize a new git repository? Yes

What You Get

Generated structure:
my-saas/
  ├── src/
  │   ├── app/
  │   │   ├── layout.tsx
  │   │   ├── page.tsx
  │   │   └── api/
  │   │       ├── auth/[...nextauth]/route.ts
  │   │       └── trpc/[trpc]/route.ts
  │   ├── server/
  │   │   ├── api/
  │   │   │   ├── root.ts         ← tRPC root router
  │   │   │   ├── trpc.ts         ← tRPC context setup
  │   │   │   └── routers/
  │   │   │       └── post.ts     ← Example router
  │   │   ├── auth.ts             ← NextAuth config
  │   │   └── db.ts               ← Prisma client
  │   ├── trpc/
  │   │   ├── query-client.ts     ← TanStack Query config
  │   │   ├── react.tsx           ← Client-side hooks
  │   │   └── server.ts           ← Server-side caller
  │   └── styles/globals.css
  ├── prisma/schema.prisma
  ├── .env.example
  └── next.config.js

T3's generated code is minimal and clean — it gives you the wiring, not the features.

// Generated tRPC router (src/server/api/routers/post.ts):
import { z } from 'zod';
import { createTRPCRouter, protectedProcedure, publicProcedure } from '~/server/api/trpc';

export const postRouter = createTRPCRouter({
  hello: publicProcedure
    .input(z.object({ text: z.string() }))
    .query(({ input }) => ({ greeting: `Hello ${input.text}` })),

  create: protectedProcedure
    .input(z.object({ name: z.string().min(1) }))
    .mutation(async ({ ctx, input }) => {
      return ctx.db.post.create({
        data: { name: input.name, createdBy: { connect: { id: ctx.session.user.id } } },
      });
    }),

  getLatest: protectedProcedure.query(async ({ ctx }) => {
    return ctx.db.post.findFirst({
      orderBy: { createdAt: 'desc' },
      where: { createdBy: { id: ctx.session.user.id } },
    });
  }),
});

Kirimase: Ongoing Code Generation

Kirimase wraps the T3 stack and adds kirimase generate — the ability to scaffold new models with full CRUD stack throughout development.

# Install globally:
npm install -g kirimase

# Initialize in an existing Next.js project (or start fresh):
kirimase init
# Prompts: Database? Prisma | ORM? Yes | Auth? NextAuth | Package manager? pnpm

# Add a package with guided configuration:
kirimase add
# Prompts: What to add? (shadcn, stripe, resend, clerk, lucia...)

# Generate full CRUD for a model:
kirimase generate

kirimase generate In Action

kirimase generate
# Prompts:
#   ✔ Model name: Project
#   ✔ Add field: name | String | required
#   ✔ Add field: description | String | optional
#   ✔ Add field: status | Enum (active, paused, archived) | default: active
#   ✔ Add field: userId | String | foreignKey → User
#   ✔ Done adding fields
#   ✔ Generate server actions (not tRPC)? No, use tRPC

What gets generated:

// 1. Prisma schema addition (appended to schema.prisma):
model Project {
  id          String   @id @default(cuid())
  name        String
  description String?
  status      ProjectStatus @default(active)
  userId      String
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

enum ProjectStatus {
  active
  paused
  archived
}
// 2. Zod schema (src/lib/db/schema/projects.ts):
import { z } from 'zod';

export const projectIdSchema = z.object({ id: z.string() });
export type ProjectId = z.infer<typeof projectIdSchema>;

export const insertProjectSchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  status: z.enum(['active', 'paused', 'archived']).default('active'),
});
export type NewProjectParams = z.infer<typeof insertProjectSchema>;

export const updateProjectSchema = insertProjectSchema;
export type UpdateProjectParams = z.infer<typeof updateProjectSchema>;
// 3. tRPC router (src/server/api/routers/projects.ts):
import { createTRPCRouter, protectedProcedure } from '~/server/api/trpc';
import {
  projectIdSchema,
  insertProjectSchema,
  updateProjectSchema,
} from '~/lib/db/schema/projects';

export const projectsRouter = createTRPCRouter({
  getProjects: protectedProcedure.query(async ({ ctx }) => {
    return ctx.db.project.findMany({ where: { userId: ctx.session.user.id } });
  }),

  getProjectById: protectedProcedure
    .input(projectIdSchema)
    .query(async ({ ctx, input }) => {
      return ctx.db.project.findFirst({
        where: { id: input.id, userId: ctx.session.user.id },
      });
    }),

  createProject: protectedProcedure
    .input(insertProjectSchema)
    .mutation(async ({ ctx, input }) => {
      return ctx.db.project.create({
        data: { ...input, userId: ctx.session.user.id },
      });
    }),

  updateProject: protectedProcedure
    .input(updateProjectSchema.extend({ id: z.string() }))
    .mutation(async ({ ctx, input }) => {
      const { id, ...data } = input;
      return ctx.db.project.update({ where: { id }, data });
    }),

  deleteProject: protectedProcedure
    .input(projectIdSchema)
    .mutation(async ({ ctx, input }) => {
      return ctx.db.project.delete({ where: { id: input.id } });
    }),
});
// 4. React form component (src/components/projects/ProjectForm.tsx):
'use client';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { api } from '~/trpc/react';
import { insertProjectSchema, type NewProjectParams } from '~/lib/db/schema/projects';

export function ProjectForm({ onSuccess }: { onSuccess?: () => void }) {
  const { register, handleSubmit, formState: { errors } } = useForm<NewProjectParams>({
    resolver: zodResolver(insertProjectSchema),
  });

  const createProject = api.projects.createProject.useMutation({
    onSuccess: () => {
      onSuccess?.();
    },
  });

  return (
    <form onSubmit={handleSubmit((data) => createProject.mutate(data))}>
      <div>
        <label>Name</label>
        <input {...register('name')} />
        {errors.name && <p>{errors.name.message}</p>}
      </div>
      <div>
        <label>Description</label>
        <textarea {...register('description')} />
      </div>
      <div>
        <label>Status</label>
        <select {...register('status')}>
          <option value="active">Active</option>
          <option value="paused">Paused</option>
          <option value="archived">Archived</option>
        </select>
      </div>
      <button type="submit" disabled={createProject.isPending}>
        {createProject.isPending ? 'Creating...' : 'Create Project'}
      </button>
    </form>
  );
}

One kirimase generate command = Prisma model + Zod schemas + tRPC CRUD router + React form.


Comparison

create-t3-appKirimase
PurposeInitial project scaffoldOngoing feature generation
When to useProject creationThroughout development
Generated outputFull project structurePer-model CRUD stack
FlexibilityHigh (minimal opinions)Medium (opinionated patterns)
Downloads/week~270KSmaller
Auth supportNextAuthNextAuth, Lucia, Clerk
ORM supportPrisma, DrizzlePrisma, Drizzle
MaintenanceT3 OSS teamCommunity

Decision Guide

Use create-t3-app if:
  → Starting a new T3-stack project (always use this)
  → Want the community-standard setup
  → Prefer minimal generated code you write yourself

Use Kirimase if:
  → Already have a T3/Next.js project
  → Tired of writing boilerplate CRUD manually
  → Want consistent patterns across all models
  → Building data-heavy apps (lots of models)

Use both (recommended):
  1. create-t3-app to initialize
  2. Kirimase for each new model/resource
  → Get T3's quality foundation + Kirimase's velocity

Why the Distinction Matters in Practice

The lifecycle difference between these two tools is the key insight. create-t3-app runs once. You answer a few prompts, get a project scaffold, and never run the tool again for that project. Kirimase runs dozens of times — once per model, once per resource, once per new domain entity you need to add to your application. The cumulative time saved by Kirimase compounds as your data model grows more complex.

A project with five to ten models represents a meaningful portion of development time if each model requires manually writing the Prisma schema addition, the Zod validation schemas, the tRPC router with five standard procedures, and the React form component. Kirimase generates all four artifacts from a single interactive prompt. For teams building data-heavy applications — project management tools, CRMs, dashboards, inventory systems — this is a genuine productivity multiplier.

Developer Experience Comparison

create-t3-app is intentionally minimal. The generated code is clean, readable, and immediately understandable. There's no framework-specific API to learn beyond the standard T3 stack libraries (tRPC, Prisma, NextAuth, Tailwind). This is a deliberate design choice by the T3 team — they want you to own your code, not depend on create-t3-app's conventions for ongoing development.

Kirimase's code generation is more opinionated. The generated Zod schemas, tRPC procedures, and form components follow specific patterns. This consistency is valuable on teams — everyone's code looks the same because it was generated from the same templates. The downside is that the generated patterns may not match your personal preferences or project-specific requirements. Most developers customize the generated code after creation, which is expected and supported.

The kirimase init command adds its own layer of dependencies and configuration on top of an existing Next.js project. Teams sometimes notice that the dependency graph expands noticeably after initialization, particularly if you use the kirimase add command to integrate packages like Stripe or Resend. Inspect what gets added before committing to the integration approach.

When Kirimase Generate Saves the Most Time

The kirimase generate command is most valuable in specific development scenarios. Building a new feature that needs a complete CRUD resource — a Project, Invoice, or Team model with full read/write API and UI — benefits most. The command generates a production-quality starting point that you then customize, rather than writing from scratch.

Kirimase is less helpful for complex relational queries, advanced authorization logic, or unusual UI patterns. The generator outputs standard patterns. When your requirements are standard — basic CRUD with ownership filtering — the output is immediately usable. When your requirements are non-standard, you'll spend time modifying generated code, which may be more work than writing it directly.

For prototyping and proof-of-concept work, Kirimase is excellent. You can scaffold an entire data model in an afternoon and have a working CRUD interface to validate with users before investing in custom UI and business logic.

Maintenance and Community

create-t3-app is maintained by the T3 Open Source team and has strong community momentum: 270,000+ weekly downloads, regular updates, and extensive community tutorials. Bugs are addressed quickly and the project follows Next.js version compatibility closely. The reliability of this tool as a project initializer is high.

Kirimase is a community-driven project with a smaller but dedicated contributor base. The maintenance cadence is less predictable. Before integrating Kirimase into a team workflow, verify that the generated code stays current with Next.js App Router conventions and the current versions of tRPC and Prisma. Generated code that becomes outdated creates a subtle technical debt: the scaffolding works but uses deprecated patterns.

The safest approach is to use Kirimase's generated output as a starting point and immediately detach from its conventions. Once the files are generated, they're plain TypeScript files in your project — not linked back to Kirimase in any way. You can update them freely without Kirimase dependency concerns.

Integration with the Broader T3 Ecosystem

Both tools fit naturally into the T3 ecosystem that includes Turbo, T3 Turbo (monorepo variant), and the growing library of T3-compatible shadcn/ui components. The generated code from create-t3-app provides the foundation; Kirimase's scaffolding uses the same tRPC patterns, making the two compatible by design.

Teams using the T3 Turbo monorepo setup for mobile and web apps should note that Kirimase's generator targets the standard T3 project structure, not the Turbo variant. Generated files may need path adjustments to fit the packages directory layout of a T3 Turbo project.

The T3 Stack's strengths compound when both tools are used together: create-t3-app establishes the type-safe foundation where everything from database query to React component is TypeScript-verified, and Kirimase's generators maintain that type safety in the code they produce. The generated Zod schemas, tRPC routers, and React forms are all strongly typed, which is the most important quality gate for long-term maintainability in TypeScript-first projects. Teams building CRUD-heavy applications — project management tools, internal dashboards, CRMs — extract the most value from this combination.

For comparisons between T3 and pre-built SaaS boilerplates, see the T3 Stack review and the create-t3-app vs ShipFast comparison. Teams considering a complete SaaS boilerplate instead of building on T3 should check StarterPick's comparison page for feature matrices across the major options.

Alternatives to Kirimase for Ongoing Scaffolding

For developers who like the idea of ongoing code generation but find Kirimase's opinions don't match their codebase, two alternatives are worth evaluating.

Drizzle Kit (drizzle-kit generate) is a first-party migration and schema tool for Drizzle ORM. Unlike Kirimase, it only generates database migration files — not routers or UI components. For teams that want the database scaffolding but prefer to write their own API and UI code, Drizzle Kit provides the most important scaffolding (schema migrations) without the full CRUD stack.

shadcn/ui CLI (npx shadcn add) generates individual UI components — form components, tables, dialogs — into your project. For teams that want Kirimase's UI generation benefits without the full CRUD stack, the shadcn CLI combined with Drizzle Kit covers the high-value scaffolding: database schema + UI components. You write the API layer manually.

The DIY alternative to both tools: a project-specific plop configuration with Handlebars templates for your tRPC router, Prisma model, and form component patterns. Plop is a code generation library that lets you define your own templates and prompt flows. It requires upfront work to configure but produces output exactly matching your project's conventions rather than Kirimase's opinions.

The T3 Stack with Billing: Common Additions

Both create-t3-app and Kirimase generate the application structure but exclude billing and auth by design. The standard additions to a T3 project for production SaaS:

Auth: NextAuth v5 is included in create-t3-app by default. Better Auth is an increasingly popular alternative — add it by removing NextAuth and installing better-auth, which provides built-in 2FA, passkeys, and organizations that T3's default NextAuth setup lacks.

Billing: Stripe integration requires manual setup — no CLI tool handles this cleanly. The standard pattern is a Stripe client in server/stripe.ts, a webhook handler at app/api/webhooks/stripe/route.ts, and a subscriptions table in the Prisma schema. Budget one to two days for a complete Stripe integration that handles subscriptions, upgrades, cancellations, and the customer portal.

Email: Resend with React Email templates is the community standard in T3 projects. Add resend and @react-email/components to your dependencies, configure the API key, and create your email templates in emails/. Kirimase's kirimase add resend handles this configuration automatically.

The T3 boilerplate landscape has expanded to address these gaps. Next-Forge (free, Turborepo monorepo) and several community starters now combine T3's type-safe foundation with billing and auth pre-configured. For teams that want the T3 approach but with less manual setup, these combined starters are worth evaluating before starting from create-t3-app directly.


Explore T3 Stack, Kirimase, and all CLI-generated starters at StarterPick.

Review the T3 Stack review for a detailed T3 ecosystem analysis.

Compare T3 Stack vs ShipFast vs Makerkit for the decision between building vs buying your SaaS foundation.

The SaaS Boilerplate Matrix (Free PDF)

20+ SaaS starters compared: pricing, tech stack, auth, payments, and what you actually ship with. Updated monthly. Used by 150+ founders.

Join 150+ SaaS founders. Unsubscribe in one click.