@dinakars777/create-nexus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # 🧠 create-nexus
2
+
3
+ > **The Ultimate Agent-Native Boilerplate Generator.**
4
+
5
+ Most Next.js boilerplates are optimized for human readability.
6
+ **Project Nexus** is optimized to be perfectly indexed, mutated, and scaled by AI Coding Agents (Cursor, Claude, Devin) with *zero hallucinations*.
7
+
8
+ ## The Problem
9
+ When you ask an AI Agent to "build a feature" in a standard Next.js codebase, it hallucinates. It mixes Pages Router with App Router, it writes raw SQL instead of using your ORM, or it bypasses your API layer entirely to write Server Actions in the UI.
10
+
11
+ ## The Solution
12
+ `create-nexus` generates a fortress. It scaffolds a high-density, strictly-typed environment (Next.js, Hono, Drizzle, Zod) that includes a built-in **Context Control Plane** explicitly designed to govern AI behavior.
13
+
14
+ ### 📦 The Tech Stack
15
+ * **Frontend:** Next.js (App Router) + Tailwind CSS
16
+ * **API:** Hono RPC (End-to-End Type Safety)
17
+ * **Database:** Drizzle ORM + Postgres
18
+ * **Validation:** Strict Zod Boundaries
19
+
20
+ ### 🤖 The Agent-Native Architecture
21
+ When you run the generator, you aren't just getting React components. You get:
22
+
23
+ 1. **The `.agent/` Control Directory**: Contains global `rules.md`, an architectural `project-map.json`, and a `scratchpad.md` for the agent to "think" out loud.
24
+ 2. **The Twin-File System**: Every major directory (`src/app`, `src/db`) contains a `CONCEPTS.md`. This defines the Business Logic vs. Implementation boundaries so the agent understands the "why" and doesn't guess context.
25
+ 3. **Strict Type-Safety Walls**: Absolute zero `any` types. Every API route uses `zValidator`. If an agent hallucinates an API shape, the Typescript compiler crashes, forcing the agent to read the error and fix itself.
26
+ 4. **Verification Hooks**: Pre-configured Husky pre-commit hooks run `tsc --noEmit`. If the agent breaks the build, the Git commit natively fails, forcing it to loop until structurally sound.
27
+ 5. **MCP Stub**: An integrated Model Context Protocol server stub (`server/mcp`) allowing local agents to securely query database schemas without reading thousands of lines of code.
28
+
29
+ ## Quickstart
30
+
31
+ Instantly generate your Agent-Native workspace:
32
+
33
+ ```bash
34
+ npx @dinakars777/create-nexus
35
+ ```
36
+
37
+ Follow the interactive prompts to name your project. The CLI will handle directory scaffolding, Git initialization, and NPM dependency installations.
38
+
39
+ ## License
40
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { intro, outro, spinner, text, confirm, isCancel } from "@clack/prompts";
5
+ import { Command } from "commander";
6
+ import pc from "picocolors";
7
+
8
+ // src/generator.ts
9
+ import fs from "fs-extra";
10
+ import path from "path";
11
+
12
+ // src/templates/agent.ts
13
+ var agentRulesTemplate = `# Global Agent Rules
14
+ - **Verify Before Commit:** Always run \`pnpm check\` (or \`npm run check\`) which triggers tsc and vitest after a change. Do not commit failing code.
15
+ - **Strict Typing:** Never use \`any\`. Use Zod for all validations.
16
+ - **Twin-Files:** If you create a new directory, you MUST create a \`CONCEPTS.md\` explaining its business logic and boundaries.
17
+ - **Architecture Limits:** Do not import UI components into the API layer. Do not import Drizzle directly into the Next.js React UI layer.
18
+ - **Think First:** Before making massive destructive changes, write your plan in \`.agent/scratchpad.md\`.
19
+ `;
20
+ var agentProjectMapTemplate = `{
21
+ "name": "nexus-app",
22
+ "architecture": {
23
+ "frontend": "Next.js App Router (React Server Components)",
24
+ "api": "Hono RPC",
25
+ "database": "Drizzle ORM + SQLite",
26
+ "validation": "Zod"
27
+ },
28
+ "directories": {
29
+ "src/app": "Next.js Routing and React UI Pages",
30
+ "src/server": "Hono API backend and RCP routes",
31
+ "src/db": "Drizzle schema operations",
32
+ "server/mcp": "Model Context Protocol stubs"
33
+ }
34
+ }
35
+ `;
36
+ var agentScratchpadTemplate = `# Agent Scratchpad
37
+ *Use this file to think out loud, draft complex refactors, or save temporary snippets before applying them to the main codebase.*
38
+
39
+ ## Current Objective
40
+ ...
41
+ `;
42
+
43
+ // src/templates/twin.ts
44
+ var twinAppConceptsTemplate = `# CONCEPTS: Frontend (src/app)
45
+
46
+ ## Business Logic
47
+ This directory contains the user-facing React application. It is responsible purely for data presentation and optimistic UI updates.
48
+
49
+ ## Boundaries
50
+ - **DO NOT** perform direct database queries (Drizzle) from here.
51
+ - **DO NOT** define raw Zod schemas for the database here.
52
+ - **DO** use the generated Hono RPC client (e.g., \`hc\`) to communicate with the \`src/server\` API.
53
+ - All components should default to React Server Components unless interactive hooks (useState, useEffect) are strictly required (use \`"use client"\`).
54
+ `;
55
+ var twinServerConceptsTemplate = `# CONCEPTS: API Backend (src/server)
56
+
57
+ ## Business Logic
58
+ This directory houses the Hono API routes. This is the exclusive gateway for all data mutations and retrievals.
59
+
60
+ ## Boundaries
61
+ - **MUST** validate all incoming payloads using \`zValidator\` with Zod.
62
+ - **MUST** export the \`AppType\` router type so the Next.js frontend can consume the RPC client with end-to-end type safety.
63
+ - **DO NOT** import React or UI components into this layer.
64
+ `;
65
+ var twinDbConceptsTemplate = `# CONCEPTS: Database Layer (src/db)
66
+
67
+ ## Business Logic
68
+ This directory contains the single source of truth for the database schema using Drizzle ORM.
69
+
70
+ ## Boundaries
71
+ - **MUST** export Drizzle Select/Insert schemas (e.g., \`createInsertSchema\`) using \`drizzle-zod\`.
72
+ - This layer does not execute business logic; it strictly defines the schema shapes and relationships.
73
+ `;
74
+
75
+ // src/templates/stack.ts
76
+ var honoServerTemplate = `import { Hono } from 'hono';
77
+ import { zValidator } from '@hono/zod-validator';
78
+ import { z } from 'zod';
79
+ import { db } from '../db';
80
+ import { users } from '../db/schema';
81
+
82
+ const app = new Hono().basePath('/api');
83
+
84
+ // @ai-intent: STRICT ZOD VALIDATION REQUIRED FOR ALL ROUTES
85
+ const createUserSchema = z.object({
86
+ name: z.string().min(1),
87
+ email: z.string().email(),
88
+ });
89
+
90
+ const routes = app
91
+ .get('/users', async (c) => {
92
+ const allUsers = await db.select().from(users);
93
+ return c.json(allUsers);
94
+ })
95
+ .post('/users', zValidator('json', createUserSchema), async (c) => {
96
+ const { name, email } = c.req.valid('json');
97
+ const result = await db.insert(users).values({ name, email }).returning();
98
+ return c.json(result[0], 201);
99
+ });
100
+
101
+ export type AppType = typeof routes;
102
+ export default app;
103
+ `;
104
+ var drizzleSchemaTemplate = `import { pgTable, text, serial, timestamp } from 'drizzle-orm/pg-core';
105
+
106
+ // @ai-intent: SINGLE SOURCE OF TRUTH. Do not write raw SQL.
107
+ export const users = pgTable('users', {
108
+ id: serial('id').primaryKey(),
109
+ name: text('name').notNull(),
110
+ email: text('email').notNull().unique(),
111
+ createdAt: timestamp('created_at').defaultNow(),
112
+ });
113
+ `;
114
+ var drizzleDbTemplate = `import { drizzle } from 'drizzle-orm/postgres-js';
115
+ import postgres from 'postgres';
116
+
117
+ const queryClient = postgres(process.env.DATABASE_URL || 'postgres://localhost:5432/nexus');
118
+ export const db = drizzle(queryClient);
119
+ `;
120
+ var nextjsPageTemplate = `import { hc } from 'hono/client';
121
+ import { type AppType } from '../server';
122
+
123
+ // @ai-intent: HONO RPC CLIENT INSTANTIATION
124
+ // Agents MUST use this \`client\` to interact with the backend to preserve end-to-end type safety.
125
+ const client = hc<AppType>('http://localhost:3000');
126
+
127
+ export default async function Home() {
128
+ const res = await client.api.users.$get();
129
+ const users = await res.json();
130
+
131
+ return (
132
+ <main className="min-h-screen bg-black text-white p-24 font-sans">
133
+ <div className="max-w-xl mx-auto space-y-8">
134
+ <h1 className="text-4xl font-bold tracking-tight">Project Nexus \u{1F9E0}</h1>
135
+ <p className="text-zinc-400">
136
+ Agent-Native Boilerplate initialized. Next.js, Hono, Drizzle, and Zod perfectly aligned.
137
+ </p>
138
+
139
+ <div className="p-6 border border-zinc-800 rounded-lg bg-zinc-950">
140
+ <h2 className="text-xl font-semibold mb-4">Database Users</h2>
141
+ {users.length === 0 ? (
142
+ <p className="text-zinc-500">No users found. Try adding one via the API.</p>
143
+ ) : (
144
+ <ul className="space-y-2">
145
+ {users.map((u: any) => (
146
+ <li key={u.id} className="text-zinc-300">\u2022 {u.name} ({u.email})</li>
147
+ ))}
148
+ </ul>
149
+ )}
150
+ </div>
151
+ </div>
152
+ </main>
153
+ );
154
+ }
155
+ `;
156
+
157
+ // src/templates/mcp.ts
158
+ var mcpServerTemplate = `import { Server } from "@modelcontextprotocol/sdk/server/index.js";
159
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
160
+ import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
161
+ import { execSync } from 'child_process';
162
+ import fs from 'fs';
163
+
164
+ // @ai-intent: MCP SERVER STUB
165
+ // Agents can connect to this server via stdio to execute read-only queries against the environment.
166
+
167
+ const server = new Server(
168
+ { name: "nexus-mcp", version: "1.0.0" },
169
+ { capabilities: { tools: {} } }
170
+ );
171
+
172
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
173
+ return {
174
+ tools: [
175
+ {
176
+ name: "get_drizzle_schema",
177
+ description: "Returns the raw text of the current Drizzle database schema to maintain context without hallucinating.",
178
+ inputSchema: { type: "object", properties: {}, required: [] },
179
+ },
180
+ {
181
+ name: "check_build_health",
182
+ description: "Runs typescript compiler checks to verify if the codebase currently has any type errors.",
183
+ inputSchema: { type: "object", properties: {}, required: [] },
184
+ }
185
+ ],
186
+ };
187
+ });
188
+
189
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
190
+ if (request.params.name === "get_drizzle_schema") {
191
+ try {
192
+ const schema = fs.readFileSync('./src/db/schema.ts', 'utf-8');
193
+ return { toolResult: schema };
194
+ } catch {
195
+ return { toolResult: "Schema file not found." };
196
+ }
197
+ }
198
+
199
+ if (request.params.name === "check_build_health") {
200
+ try {
201
+ const output = execSync('npx tsc --noEmit', { encoding: 'utf-8' });
202
+ return { toolResult: output || "Build is perfectly healthy. No type errors." };
203
+ } catch (e: any) {
204
+ return { toolResult: \`Type errors detected:\\n\${e.stdout}\` };
205
+ }
206
+ }
207
+
208
+ throw new Error("Tool not found");
209
+ });
210
+
211
+ const transport = new StdioServerTransport();
212
+ server.connect(transport).catch(console.error);
213
+ `;
214
+
215
+ // src/generator.ts
216
+ async function generateBoilerplate(projectName) {
217
+ const targetDir = path.resolve(process.cwd(), projectName);
218
+ if (fs.existsSync(targetDir)) {
219
+ throw new Error(`Directory ${projectName} already exists.`);
220
+ }
221
+ await fs.ensureDir(targetDir);
222
+ const dirs = [
223
+ "src/app",
224
+ "src/server",
225
+ "src/db",
226
+ "server/mcp",
227
+ ".agent",
228
+ ".husky"
229
+ ];
230
+ for (const dir of dirs) {
231
+ await fs.ensureDir(path.join(targetDir, dir));
232
+ }
233
+ await fs.writeFile(path.join(targetDir, ".agent/rules.md"), agentRulesTemplate);
234
+ await fs.writeFile(path.join(targetDir, ".agent/project-map.json"), agentProjectMapTemplate);
235
+ await fs.writeFile(path.join(targetDir, ".agent/scratchpad.md"), agentScratchpadTemplate);
236
+ await fs.writeFile(path.join(targetDir, "src/app/CONCEPTS.md"), twinAppConceptsTemplate);
237
+ await fs.writeFile(path.join(targetDir, "src/server/CONCEPTS.md"), twinServerConceptsTemplate);
238
+ await fs.writeFile(path.join(targetDir, "src/db/CONCEPTS.md"), twinDbConceptsTemplate);
239
+ await fs.writeFile(path.join(targetDir, "server/mcp/index.ts"), mcpServerTemplate);
240
+ await fs.writeFile(path.join(targetDir, "src/server/index.ts"), honoServerTemplate);
241
+ await fs.writeFile(path.join(targetDir, "src/db/schema.ts"), drizzleSchemaTemplate);
242
+ await fs.writeFile(path.join(targetDir, "src/db/index.ts"), drizzleDbTemplate);
243
+ await fs.writeFile(path.join(targetDir, "src/app/page.tsx"), nextjsPageTemplate);
244
+ const packageJson = {
245
+ name: projectName,
246
+ version: "0.1.0",
247
+ private: true,
248
+ scripts: {
249
+ "dev": "next dev",
250
+ "build": "next build",
251
+ "start": "next start",
252
+ "lint": "next lint",
253
+ "check": "tsc --noEmit",
254
+ "db:push": "drizzle-kit push",
255
+ "prepare": "husky install"
256
+ },
257
+ dependencies: {
258
+ "next": "14.2.3",
259
+ "react": "^18",
260
+ "react-dom": "^18",
261
+ "hono": "^4.3.0",
262
+ "zod": "^3.23.0",
263
+ "@hono/zod-validator": "^0.2.1",
264
+ "drizzle-orm": "^0.30.0",
265
+ "postgres": "^3.4.4",
266
+ "@modelcontextprotocol/sdk": "^1.27.1"
267
+ },
268
+ devDependencies: {
269
+ "typescript": "^5",
270
+ "@types/node": "^20",
271
+ "@types/react": "^18",
272
+ "@types/react-dom": "^18",
273
+ "postcss": "^8",
274
+ "tailwindcss": "^3.4.1",
275
+ "drizzle-kit": "^0.21.0",
276
+ "husky": "^9.0.0",
277
+ "lint-staged": "^15.2.0"
278
+ },
279
+ "lint-staged": {
280
+ "*.ts?(x)": [
281
+ "tsc --noEmit"
282
+ ]
283
+ }
284
+ };
285
+ await fs.writeJson(path.join(targetDir, "package.json"), packageJson, { spaces: 2 });
286
+ const tsconfig = {
287
+ "compilerOptions": {
288
+ "lib": ["dom", "dom.iterable", "esnext"],
289
+ "allowJs": true,
290
+ "skipLibCheck": true,
291
+ "strict": true,
292
+ "noEmit": true,
293
+ "esModuleInterop": true,
294
+ "module": "esnext",
295
+ "moduleResolution": "bundler",
296
+ "resolveJsonModule": true,
297
+ "isolatedModules": true,
298
+ "jsx": "preserve",
299
+ "incremental": true,
300
+ "plugins": [
301
+ {
302
+ "name": "next"
303
+ }
304
+ ],
305
+ "paths": {
306
+ "@/*": ["./src/*"]
307
+ }
308
+ },
309
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
310
+ "exclude": ["node_modules"]
311
+ };
312
+ await fs.writeJson(path.join(targetDir, "tsconfig.json"), tsconfig, { spaces: 2 });
313
+ const huskyPreCommit = `#!/usr/bin/env sh
314
+ . "$(dirname -- "$0")/_/husky.sh"
315
+
316
+ npx lint-staged
317
+ npm run check
318
+ `;
319
+ await fs.writeFile(path.join(targetDir, ".husky/pre-commit"), huskyPreCommit);
320
+ }
321
+
322
+ // src/index.ts
323
+ import { execa } from "execa";
324
+ var program = new Command();
325
+ program.name("create-nexus").description("Scaffold the ultimate Agent-Native Boilerplate.").version("1.0.0");
326
+ program.action(async () => {
327
+ console.log();
328
+ intro(pc.inverse(pc.bold(" \u{1F9E0} CREATE NEXUS: Agent-Native Stack ")));
329
+ const projectName = await text({
330
+ message: "What is your project named?",
331
+ placeholder: "my-agent-app",
332
+ validate(value) {
333
+ if (!value || value.length === 0) return "Project name is required!";
334
+ if (/^[a-zA-Z0-9-]+$/.test(value) === false) return "Project name can only contain letters, numbers, and dashes.";
335
+ }
336
+ });
337
+ if (isCancel(projectName)) {
338
+ outro("Operation cancelled.");
339
+ process.exit(0);
340
+ }
341
+ const s = spinner();
342
+ s.start(`Scaffolding Agent-Native architecture into ${projectName}...`);
343
+ try {
344
+ await generateBoilerplate(projectName);
345
+ s.stop(pc.green("\u2713 Scaffold instantiated successfully."));
346
+ } catch (err) {
347
+ s.stop(pc.red("\u2716 Failed to generate project."));
348
+ console.error(pc.red(err.message));
349
+ process.exit(1);
350
+ }
351
+ console.log();
352
+ console.log(pc.bold("Included in this High-Density Stack:"));
353
+ console.log(pc.cyan(" \u2022 Next.js App Router") + " (Frontend)");
354
+ console.log(pc.cyan(" \u2022 Hono RPC") + " (Type-safe API Backend)");
355
+ console.log(pc.cyan(" \u2022 Drizzle ORM + SQLite") + " (Strict Zod Schemas)");
356
+ console.log(pc.cyan(" \u2022 The Twin-File Architecture") + " (CONCEPTS.md context layer)");
357
+ console.log(pc.cyan(" \u2022 Integrated MCP Stub") + " (server/mcp for Agent querying)");
358
+ console.log(pc.cyan(" \u2022 Husky + tsc") + " (Strict commit verification hooks)");
359
+ console.log();
360
+ const installDeps = await confirm({
361
+ message: "Would you like to install dependencies now? (npm install)",
362
+ initialValue: true
363
+ });
364
+ if (isCancel(installDeps)) {
365
+ outro("Operation cancelled.");
366
+ process.exit(0);
367
+ }
368
+ if (installDeps) {
369
+ s.start("Installing dependencies via npm...");
370
+ try {
371
+ await execa("npm", ["install"], { cwd: projectName });
372
+ s.stop(pc.green("\u2713 Dependencies installed."));
373
+ } catch {
374
+ s.stop(pc.red("\u2716 Failed to install dependencies. You can run npm install manually later."));
375
+ }
376
+ }
377
+ const initGit = await confirm({
378
+ message: "Initialize a new Git repository?",
379
+ initialValue: true
380
+ });
381
+ if (!isCancel(initGit) && initGit) {
382
+ try {
383
+ await execa("git", ["init"], { cwd: projectName });
384
+ console.log(pc.green("\u2713 Git repository initialized."));
385
+ } catch {
386
+ }
387
+ }
388
+ console.log();
389
+ console.log(pc.bgGreen(" SUCCESS! ") + ` Project ${projectName} is ready for an AI Agent to dominate.`);
390
+ console.log("Next steps:");
391
+ console.log(pc.bold(` cd ${projectName}`));
392
+ console.log(pc.bold(" npm run dev"));
393
+ outro("Good luck building!");
394
+ });
395
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@dinakars777/create-nexus",
3
+ "version": "1.0.0",
4
+ "description": "Scaffold the ultimate Agent-Native Boilerplate. Next.js, Hono, Drizzle, Zod, with built-in .agent control plane.",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "create-nexus": "dist/index.js",
9
+ "create-nexus-app": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "dev": "tsup watch",
13
+ "build": "tsup src/index.ts --format esm --clean"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "agent",
18
+ "boilerplate",
19
+ "nextjs",
20
+ "hono",
21
+ "drizzle"
22
+ ],
23
+ "author": "Dinakar Sarbada",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@clack/prompts": "^0.7.0",
27
+ "commander": "^11.1.0",
28
+ "execa": "^8.0.1",
29
+ "fs-extra": "^11.2.0",
30
+ "picocolors": "^1.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/fs-extra": "^11.0.4",
34
+ "@types/node": "^20.10.0",
35
+ "tsup": "^8.0.0",
36
+ "typescript": "^5.3.2"
37
+ }
38
+ }
@@ -0,0 +1,133 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { agentRulesTemplate, agentProjectMapTemplate, agentScratchpadTemplate } from './templates/agent';
4
+ import { twinAppConceptsTemplate, twinServerConceptsTemplate, twinDbConceptsTemplate } from './templates/twin';
5
+ import { honoServerTemplate, drizzleSchemaTemplate, drizzleDbTemplate, nextjsPageTemplate } from './templates/stack';
6
+ import { mcpServerTemplate } from './templates/mcp';
7
+
8
+ export async function generateBoilerplate(projectName: string) {
9
+ const targetDir = path.resolve(process.cwd(), projectName);
10
+
11
+ if (fs.existsSync(targetDir)) {
12
+ throw new Error(`Directory ${projectName} already exists.`);
13
+ }
14
+
15
+ // 1. Core Directory Scaffolding
16
+ await fs.ensureDir(targetDir);
17
+ const dirs = [
18
+ 'src/app',
19
+ 'src/server',
20
+ 'src/db',
21
+ 'server/mcp',
22
+ '.agent',
23
+ '.husky'
24
+ ];
25
+
26
+ for (const dir of dirs) {
27
+ await fs.ensureDir(path.join(targetDir, dir));
28
+ }
29
+
30
+ // 2. The Agent Control Directory
31
+ await fs.writeFile(path.join(targetDir, '.agent/rules.md'), agentRulesTemplate);
32
+ await fs.writeFile(path.join(targetDir, '.agent/project-map.json'), agentProjectMapTemplate);
33
+ await fs.writeFile(path.join(targetDir, '.agent/scratchpad.md'), agentScratchpadTemplate);
34
+
35
+ // 3. The Twin-File System (CONCEPTS.md)
36
+ await fs.writeFile(path.join(targetDir, 'src/app/CONCEPTS.md'), twinAppConceptsTemplate);
37
+ await fs.writeFile(path.join(targetDir, 'src/server/CONCEPTS.md'), twinServerConceptsTemplate);
38
+ await fs.writeFile(path.join(targetDir, 'src/db/CONCEPTS.md'), twinDbConceptsTemplate);
39
+
40
+ // 4. MCP Server Stub
41
+ await fs.writeFile(path.join(targetDir, 'server/mcp/index.ts'), mcpServerTemplate);
42
+
43
+ // 5. Stack Templates
44
+ await fs.writeFile(path.join(targetDir, 'src/server/index.ts'), honoServerTemplate);
45
+ await fs.writeFile(path.join(targetDir, 'src/db/schema.ts'), drizzleSchemaTemplate);
46
+ await fs.writeFile(path.join(targetDir, 'src/db/index.ts'), drizzleDbTemplate);
47
+ await fs.writeFile(path.join(targetDir, 'src/app/page.tsx'), nextjsPageTemplate);
48
+
49
+ // 6. Base Package Config & Verification Hooks (Husky)
50
+ const packageJson = {
51
+ name: projectName,
52
+ version: "0.1.0",
53
+ private: true,
54
+ scripts: {
55
+ "dev": "next dev",
56
+ "build": "next build",
57
+ "start": "next start",
58
+ "lint": "next lint",
59
+ "check": "tsc --noEmit",
60
+ "db:push": "drizzle-kit push",
61
+ "prepare": "husky install"
62
+ },
63
+ dependencies: {
64
+ "next": "14.2.3",
65
+ "react": "^18",
66
+ "react-dom": "^18",
67
+ "hono": "^4.3.0",
68
+ "zod": "^3.23.0",
69
+ "@hono/zod-validator": "^0.2.1",
70
+ "drizzle-orm": "^0.30.0",
71
+ "postgres": "^3.4.4",
72
+ "@modelcontextprotocol/sdk": "^1.27.1"
73
+ },
74
+ devDependencies: {
75
+ "typescript": "^5",
76
+ "@types/node": "^20",
77
+ "@types/react": "^18",
78
+ "@types/react-dom": "^18",
79
+ "postcss": "^8",
80
+ "tailwindcss": "^3.4.1",
81
+ "drizzle-kit": "^0.21.0",
82
+ "husky": "^9.0.0",
83
+ "lint-staged": "^15.2.0"
84
+ },
85
+ "lint-staged": {
86
+ "*.ts?(x)": [
87
+ "tsc --noEmit"
88
+ ]
89
+ }
90
+ };
91
+
92
+ await fs.writeJson(path.join(targetDir, 'package.json'), packageJson, { spaces: 2 });
93
+
94
+ // TSConfig
95
+ const tsconfig = {
96
+ "compilerOptions": {
97
+ "lib": ["dom", "dom.iterable", "esnext"],
98
+ "allowJs": true,
99
+ "skipLibCheck": true,
100
+ "strict": true,
101
+ "noEmit": true,
102
+ "esModuleInterop": true,
103
+ "module": "esnext",
104
+ "moduleResolution": "bundler",
105
+ "resolveJsonModule": true,
106
+ "isolatedModules": true,
107
+ "jsx": "preserve",
108
+ "incremental": true,
109
+ "plugins": [
110
+ {
111
+ "name": "next"
112
+ }
113
+ ],
114
+ "paths": {
115
+ "@/*": ["./src/*"]
116
+ }
117
+ },
118
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
119
+ "exclude": ["node_modules"]
120
+ };
121
+ await fs.writeJson(path.join(targetDir, 'tsconfig.json'), tsconfig, { spaces: 2 });
122
+
123
+ // Husky Pre-commit hook
124
+ const huskyPreCommit = `#!/usr/bin/env sh
125
+ . "$(dirname -- "$0")/_/husky.sh"
126
+
127
+ npx lint-staged
128
+ npm run check
129
+ `;
130
+ await fs.writeFile(path.join(targetDir, '.husky/pre-commit'), huskyPreCommit);
131
+ // Ensure the hook is executable (not natively supported by fs.writeFile easily cross-platform, but good enough for a generated boilerplate before install)
132
+
133
+ }
package/src/index.ts ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import { intro, outro, spinner, text, confirm, isCancel } from '@clack/prompts';
3
+ import { Command } from 'commander';
4
+ import pc from 'picocolors';
5
+ import { generateBoilerplate } from './generator';
6
+ import { execa } from 'execa';
7
+
8
+ const program = new Command();
9
+
10
+ program
11
+ .name('create-nexus')
12
+ .description('Scaffold the ultimate Agent-Native Boilerplate.')
13
+ .version('1.0.0');
14
+
15
+ program.action(async () => {
16
+ console.log();
17
+ intro(pc.inverse(pc.bold(' 🧠 CREATE NEXUS: Agent-Native Stack ')));
18
+
19
+ const projectName = await text({
20
+ message: 'What is your project named?',
21
+ placeholder: 'my-agent-app',
22
+ validate(value) {
23
+ if (!value || value.length === 0) return 'Project name is required!';
24
+ if (/^[a-zA-Z0-9-]+$/.test(value) === false) return 'Project name can only contain letters, numbers, and dashes.';
25
+ },
26
+ });
27
+
28
+ if (isCancel(projectName)) {
29
+ outro('Operation cancelled.');
30
+ process.exit(0);
31
+ }
32
+
33
+ const s = spinner();
34
+ s.start(`Scaffolding Agent-Native architecture into ${projectName}...`);
35
+
36
+ try {
37
+ await generateBoilerplate(projectName as string);
38
+ s.stop(pc.green('✓ Scaffold instantiated successfully.'));
39
+ } catch (err: any) {
40
+ s.stop(pc.red('✖ Failed to generate project.'));
41
+ console.error(pc.red(err.message));
42
+ process.exit(1);
43
+ }
44
+
45
+ console.log();
46
+ console.log(pc.bold('Included in this High-Density Stack:'));
47
+ console.log(pc.cyan(' • Next.js App Router') + ' (Frontend)');
48
+ console.log(pc.cyan(' • Hono RPC') + ' (Type-safe API Backend)');
49
+ console.log(pc.cyan(' • Drizzle ORM + SQLite') + ' (Strict Zod Schemas)');
50
+ console.log(pc.cyan(' • The Twin-File Architecture') + ' (CONCEPTS.md context layer)');
51
+ console.log(pc.cyan(' • Integrated MCP Stub') + ' (server/mcp for Agent querying)');
52
+ console.log(pc.cyan(' • Husky + tsc') + ' (Strict commit verification hooks)');
53
+ console.log();
54
+
55
+ const installDeps = await confirm({
56
+ message: 'Would you like to install dependencies now? (npm install)',
57
+ initialValue: true,
58
+ });
59
+
60
+ if (isCancel(installDeps)) {
61
+ outro('Operation cancelled.');
62
+ process.exit(0);
63
+ }
64
+
65
+ if (installDeps) {
66
+ s.start('Installing dependencies via npm...');
67
+ try {
68
+ await execa('npm', ['install'], { cwd: projectName as string });
69
+ s.stop(pc.green('✓ Dependencies installed.'));
70
+ } catch {
71
+ s.stop(pc.red('✖ Failed to install dependencies. You can run npm install manually later.'));
72
+ }
73
+ }
74
+
75
+ const initGit = await confirm({
76
+ message: 'Initialize a new Git repository?',
77
+ initialValue: true,
78
+ });
79
+
80
+ if (!isCancel(initGit) && initGit) {
81
+ try {
82
+ await execa('git', ['init'], { cwd: projectName as string });
83
+ console.log(pc.green('✓ Git repository initialized.'));
84
+ } catch {}
85
+ }
86
+
87
+ console.log();
88
+ console.log(pc.bgGreen(' SUCCESS! ') + ` Project ${projectName} is ready for an AI Agent to dominate.`);
89
+ console.log('Next steps:');
90
+ console.log(pc.bold(` cd ${projectName}`));
91
+ console.log(pc.bold(' npm run dev'));
92
+
93
+ outro('Good luck building!');
94
+ });
95
+
96
+ program.parse(process.argv);
@@ -0,0 +1,31 @@
1
+ export const agentRulesTemplate = `# Global Agent Rules
2
+ - **Verify Before Commit:** Always run \`pnpm check\` (or \`npm run check\`) which triggers tsc and vitest after a change. Do not commit failing code.
3
+ - **Strict Typing:** Never use \`any\`. Use Zod for all validations.
4
+ - **Twin-Files:** If you create a new directory, you MUST create a \`CONCEPTS.md\` explaining its business logic and boundaries.
5
+ - **Architecture Limits:** Do not import UI components into the API layer. Do not import Drizzle directly into the Next.js React UI layer.
6
+ - **Think First:** Before making massive destructive changes, write your plan in \`.agent/scratchpad.md\`.
7
+ `;
8
+
9
+ export const agentProjectMapTemplate = `{
10
+ "name": "nexus-app",
11
+ "architecture": {
12
+ "frontend": "Next.js App Router (React Server Components)",
13
+ "api": "Hono RPC",
14
+ "database": "Drizzle ORM + SQLite",
15
+ "validation": "Zod"
16
+ },
17
+ "directories": {
18
+ "src/app": "Next.js Routing and React UI Pages",
19
+ "src/server": "Hono API backend and RCP routes",
20
+ "src/db": "Drizzle schema operations",
21
+ "server/mcp": "Model Context Protocol stubs"
22
+ }
23
+ }
24
+ `;
25
+
26
+ export const agentScratchpadTemplate = `# Agent Scratchpad
27
+ *Use this file to think out loud, draft complex refactors, or save temporary snippets before applying them to the main codebase.*
28
+
29
+ ## Current Objective
30
+ ...
31
+ `;
@@ -0,0 +1,56 @@
1
+ export const mcpServerTemplate = `import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
4
+ import { execSync } from 'child_process';
5
+ import fs from 'fs';
6
+
7
+ // @ai-intent: MCP SERVER STUB
8
+ // Agents can connect to this server via stdio to execute read-only queries against the environment.
9
+
10
+ const server = new Server(
11
+ { name: "nexus-mcp", version: "1.0.0" },
12
+ { capabilities: { tools: {} } }
13
+ );
14
+
15
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
16
+ return {
17
+ tools: [
18
+ {
19
+ name: "get_drizzle_schema",
20
+ description: "Returns the raw text of the current Drizzle database schema to maintain context without hallucinating.",
21
+ inputSchema: { type: "object", properties: {}, required: [] },
22
+ },
23
+ {
24
+ name: "check_build_health",
25
+ description: "Runs typescript compiler checks to verify if the codebase currently has any type errors.",
26
+ inputSchema: { type: "object", properties: {}, required: [] },
27
+ }
28
+ ],
29
+ };
30
+ });
31
+
32
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
33
+ if (request.params.name === "get_drizzle_schema") {
34
+ try {
35
+ const schema = fs.readFileSync('./src/db/schema.ts', 'utf-8');
36
+ return { toolResult: schema };
37
+ } catch {
38
+ return { toolResult: "Schema file not found." };
39
+ }
40
+ }
41
+
42
+ if (request.params.name === "check_build_health") {
43
+ try {
44
+ const output = execSync('npx tsc --noEmit', { encoding: 'utf-8' });
45
+ return { toolResult: output || "Build is perfectly healthy. No type errors." };
46
+ } catch (e: any) {
47
+ return { toolResult: \`Type errors detected:\\n\${e.stdout}\` };
48
+ }
49
+ }
50
+
51
+ throw new Error("Tool not found");
52
+ });
53
+
54
+ const transport = new StdioServerTransport();
55
+ server.connect(transport).catch(console.error);
56
+ `;
@@ -0,0 +1,83 @@
1
+ export const honoServerTemplate = `import { Hono } from 'hono';
2
+ import { zValidator } from '@hono/zod-validator';
3
+ import { z } from 'zod';
4
+ import { db } from '../db';
5
+ import { users } from '../db/schema';
6
+
7
+ const app = new Hono().basePath('/api');
8
+
9
+ // @ai-intent: STRICT ZOD VALIDATION REQUIRED FOR ALL ROUTES
10
+ const createUserSchema = z.object({
11
+ name: z.string().min(1),
12
+ email: z.string().email(),
13
+ });
14
+
15
+ const routes = app
16
+ .get('/users', async (c) => {
17
+ const allUsers = await db.select().from(users);
18
+ return c.json(allUsers);
19
+ })
20
+ .post('/users', zValidator('json', createUserSchema), async (c) => {
21
+ const { name, email } = c.req.valid('json');
22
+ const result = await db.insert(users).values({ name, email }).returning();
23
+ return c.json(result[0], 201);
24
+ });
25
+
26
+ export type AppType = typeof routes;
27
+ export default app;
28
+ `;
29
+
30
+ export const drizzleSchemaTemplate = `import { pgTable, text, serial, timestamp } from 'drizzle-orm/pg-core';
31
+
32
+ // @ai-intent: SINGLE SOURCE OF TRUTH. Do not write raw SQL.
33
+ export const users = pgTable('users', {
34
+ id: serial('id').primaryKey(),
35
+ name: text('name').notNull(),
36
+ email: text('email').notNull().unique(),
37
+ createdAt: timestamp('created_at').defaultNow(),
38
+ });
39
+ `;
40
+
41
+ export const drizzleDbTemplate = `import { drizzle } from 'drizzle-orm/postgres-js';
42
+ import postgres from 'postgres';
43
+
44
+ const queryClient = postgres(process.env.DATABASE_URL || 'postgres://localhost:5432/nexus');
45
+ export const db = drizzle(queryClient);
46
+ `;
47
+
48
+ export const nextjsPageTemplate = `import { hc } from 'hono/client';
49
+ import { type AppType } from '../server';
50
+
51
+ // @ai-intent: HONO RPC CLIENT INSTANTIATION
52
+ // Agents MUST use this \`client\` to interact with the backend to preserve end-to-end type safety.
53
+ const client = hc<AppType>('http://localhost:3000');
54
+
55
+ export default async function Home() {
56
+ const res = await client.api.users.$get();
57
+ const users = await res.json();
58
+
59
+ return (
60
+ <main className="min-h-screen bg-black text-white p-24 font-sans">
61
+ <div className="max-w-xl mx-auto space-y-8">
62
+ <h1 className="text-4xl font-bold tracking-tight">Project Nexus 🧠</h1>
63
+ <p className="text-zinc-400">
64
+ Agent-Native Boilerplate initialized. Next.js, Hono, Drizzle, and Zod perfectly aligned.
65
+ </p>
66
+
67
+ <div className="p-6 border border-zinc-800 rounded-lg bg-zinc-950">
68
+ <h2 className="text-xl font-semibold mb-4">Database Users</h2>
69
+ {users.length === 0 ? (
70
+ <p className="text-zinc-500">No users found. Try adding one via the API.</p>
71
+ ) : (
72
+ <ul className="space-y-2">
73
+ {users.map((u: any) => (
74
+ <li key={u.id} className="text-zinc-300">• {u.name} ({u.email})</li>
75
+ ))}
76
+ </ul>
77
+ )}
78
+ </div>
79
+ </div>
80
+ </main>
81
+ );
82
+ }
83
+ `;
@@ -0,0 +1,32 @@
1
+ export const twinAppConceptsTemplate = `# CONCEPTS: Frontend (src/app)
2
+
3
+ ## Business Logic
4
+ This directory contains the user-facing React application. It is responsible purely for data presentation and optimistic UI updates.
5
+
6
+ ## Boundaries
7
+ - **DO NOT** perform direct database queries (Drizzle) from here.
8
+ - **DO NOT** define raw Zod schemas for the database here.
9
+ - **DO** use the generated Hono RPC client (e.g., \`hc\`) to communicate with the \`src/server\` API.
10
+ - All components should default to React Server Components unless interactive hooks (useState, useEffect) are strictly required (use \`"use client"\`).
11
+ `;
12
+
13
+ export const twinServerConceptsTemplate = `# CONCEPTS: API Backend (src/server)
14
+
15
+ ## Business Logic
16
+ This directory houses the Hono API routes. This is the exclusive gateway for all data mutations and retrievals.
17
+
18
+ ## Boundaries
19
+ - **MUST** validate all incoming payloads using \`zValidator\` with Zod.
20
+ - **MUST** export the \`AppType\` router type so the Next.js frontend can consume the RPC client with end-to-end type safety.
21
+ - **DO NOT** import React or UI components into this layer.
22
+ `;
23
+
24
+ export const twinDbConceptsTemplate = `# CONCEPTS: Database Layer (src/db)
25
+
26
+ ## Business Logic
27
+ This directory contains the single source of truth for the database schema using Drizzle ORM.
28
+
29
+ ## Boundaries
30
+ - **MUST** export Drizzle Select/Insert schemas (e.g., \`createInsertSchema\`) using \`drizzle-zod\`.
31
+ - This layer does not execute business logic; it strictly defines the schema shapes and relationships.
32
+ `;
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "dist",
11
+ "rootDir": "src"
12
+ },
13
+ "include": ["src/**/*"]
14
+ }