create-kofi-stack 1.2.18 → 1.2.20

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.
Files changed (2) hide show
  1. package/dist/index.js +105 -628
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -80,16 +80,6 @@ async function promptMarketingSite(defaultValue) {
80
80
  }
81
81
  return marketing;
82
82
  }
83
- async function promptIncludeDocs(defaultValue) {
84
- const includeDocs = await p.confirm({
85
- message: "Include documentation site? (Fumadocs)",
86
- initialValue: defaultValue ?? true
87
- });
88
- if (p.isCancel(includeDocs)) {
89
- throw new Error("Operation cancelled");
90
- }
91
- return includeDocs;
92
- }
93
83
 
94
84
  // src/prompts/shadcn.ts
95
85
  import * as p2 from "@clack/prompts";
@@ -471,7 +461,6 @@ function parseOptions(options) {
471
461
  monorepo: options.monorepo,
472
462
  single: options.single,
473
463
  marketing: options.marketing,
474
- docs: options.docs,
475
464
  componentLibrary: options.componentLibrary,
476
465
  style: options.style,
477
466
  baseColor: options.baseColor,
@@ -505,18 +494,12 @@ async function runPrompts(projectName, rawOptions) {
505
494
  structure = await promptProjectStructure();
506
495
  }
507
496
  let marketingSite = "none";
508
- let includeDocs = false;
509
497
  if (structure === "monorepo") {
510
498
  if (options.marketing) {
511
499
  marketingSite = options.marketing;
512
500
  } else {
513
501
  marketingSite = await promptMarketingSite();
514
502
  }
515
- if (options.docs !== void 0) {
516
- includeDocs = options.docs;
517
- } else {
518
- includeDocs = await promptIncludeDocs();
519
- }
520
503
  }
521
504
  const shadcn = await promptShadcnConfig({
522
505
  componentLibrary: options.componentLibrary,
@@ -569,7 +552,6 @@ async function runPrompts(projectName, rawOptions) {
569
552
  name,
570
553
  structure,
571
554
  marketingSite,
572
- includeDocs,
573
555
  shadcn,
574
556
  designSystem,
575
557
  auth,
@@ -614,9 +596,6 @@ function showConfigSummary(config) {
614
596
  if (config.marketingSite !== "none") {
615
597
  apps.push(`marketing (${config.marketingSite})`);
616
598
  }
617
- if (config.includeDocs) {
618
- apps.push("docs");
619
- }
620
599
  }
621
600
  const authProviders = ["Email/Password", "Google", ...config.auth.providers];
622
601
  const extras = [];
@@ -660,9 +639,6 @@ async function showConfirmation(config) {
660
639
  if (config.marketingSite !== "none") {
661
640
  apps.push(`marketing (${config.marketingSite})`);
662
641
  }
663
- if (config.includeDocs) {
664
- apps.push("docs");
665
- }
666
642
  }
667
643
  const authProviders = ["Email/Password", "Google", ...config.auth.providers];
668
644
  const extras = [];
@@ -709,7 +685,7 @@ ${extras.length > 0 ? `${pc.bold("Extras:")} ${extras.join(", ")}` : ""}`,
709
685
  }
710
686
 
711
687
  // src/generators/index.ts
712
- import path19 from "path";
688
+ import path18 from "path";
713
689
  import * as p7 from "@clack/prompts";
714
690
  import pc3 from "picocolors";
715
691
  import ora from "ora";
@@ -1061,17 +1037,36 @@ export const {
1061
1037
  } = authClient
1062
1038
  `;
1063
1039
  await writeFile(path3.join(appDir, "src/lib/auth.ts"), authClientContent);
1064
- const convexContent = `import { ConvexProvider, ConvexReactClient } from 'convex/react'
1040
+ const convexContent = `'use client'
1041
+
1042
+ import { ConvexProvider, ConvexReactClient } from 'convex/react'
1065
1043
  import { env } from '@/env'
1066
1044
 
1067
1045
  const convexUrl = env.NEXT_PUBLIC_CONVEX_URL
1068
- if (!convexUrl) {
1069
- throw new Error(
1070
- 'NEXT_PUBLIC_CONVEX_URL is not set. Run "npx convex dev" to set up Convex.'
1071
- )
1072
- }
1073
1046
 
1074
- export const convex = new ConvexReactClient(convexUrl)
1047
+ // Create client only if URL is available
1048
+ export const convex = convexUrl ? new ConvexReactClient(convexUrl) : null
1049
+
1050
+ // Wrapper provider that handles missing Convex configuration
1051
+ export function ConvexClientProvider({ children }: { children: React.ReactNode }) {
1052
+ if (!convex) {
1053
+ return (
1054
+ <div className="min-h-screen flex items-center justify-center bg-background">
1055
+ <div className="text-center p-8 max-w-md">
1056
+ <h1 className="text-2xl font-bold mb-4">Convex Not Configured</h1>
1057
+ <p className="text-muted-foreground mb-4">
1058
+ Run <code className="bg-muted px-2 py-1 rounded">npx convex dev</code> in your terminal to set up Convex.
1059
+ </p>
1060
+ <p className="text-sm text-muted-foreground">
1061
+ This will create your Convex project and add the required environment variables.
1062
+ </p>
1063
+ </div>
1064
+ </div>
1065
+ )
1066
+ }
1067
+
1068
+ return <ConvexProvider client={convex}>{children}</ConvexProvider>
1069
+ }
1075
1070
 
1076
1071
  export { ConvexProvider }
1077
1072
  `;
@@ -1198,15 +1193,14 @@ export const env = createEnv({
1198
1193
  async function generateComponentFiles(config, appDir) {
1199
1194
  let providersContent = `'use client'
1200
1195
 
1201
- import { ConvexProvider } from '@/lib/convex'
1202
- import { convex } from '@/lib/convex'`;
1196
+ import { ConvexClientProvider } from '@/lib/convex'`;
1203
1197
  if (config.integrations.analytics === "posthog") {
1204
1198
  providersContent += `
1205
1199
  import posthog from 'posthog-js'
1206
1200
  import { PostHogProvider } from 'posthog-js/react'
1207
1201
  import { env } from '@/env'
1208
1202
 
1209
- if (typeof window !== 'undefined') {
1203
+ if (typeof window !== 'undefined' && env.NEXT_PUBLIC_POSTHOG_KEY) {
1210
1204
  posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, {
1211
1205
  api_host: env.NEXT_PUBLIC_POSTHOG_HOST,
1212
1206
  person_profiles: 'identified_only',
@@ -1222,9 +1216,9 @@ export function Providers({ children }: { children: React.ReactNode }) {
1222
1216
  <PostHogProvider client={posthog}>`;
1223
1217
  }
1224
1218
  providersContent += `
1225
- <ConvexProvider client={convex}>
1219
+ <ConvexClientProvider>
1226
1220
  {children}
1227
- </ConvexProvider>`;
1221
+ </ConvexClientProvider>`;
1228
1222
  if (config.integrations.analytics === "posthog") {
1229
1223
  providersContent += `
1230
1224
  </PostHogProvider>`;
@@ -2059,18 +2053,19 @@ import { ConvexHttpClient } from 'convex/browser'
2059
2053
  import { env } from '@/env'
2060
2054
 
2061
2055
  const convexUrl = env.NEXT_PUBLIC_CONVEX_URL
2062
- if (!convexUrl) {
2063
- throw new Error(
2064
- 'NEXT_PUBLIC_CONVEX_URL is not set. Run "npx convex dev" to set up Convex.'
2065
- )
2066
- }
2067
2056
 
2068
- const convex = new ConvexHttpClient(convexUrl)
2057
+ // Auth is only functional when Convex is configured
2058
+ const convex = convexUrl ? new ConvexHttpClient(convexUrl) : null
2059
+
2060
+ function createAuth() {
2061
+ if (!convex) {
2062
+ throw new Error('NEXT_PUBLIC_CONVEX_URL is not set. Run "npx convex dev" to set up Convex.')
2063
+ }
2069
2064
 
2070
- export const auth = betterAuth({
2071
- database: convexAdapter(convex),
2072
- secret: env.BETTER_AUTH_SECRET || '',
2073
- baseURL: env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
2065
+ return betterAuth({
2066
+ database: convexAdapter(convex),
2067
+ secret: env.BETTER_AUTH_SECRET || '',
2068
+ baseURL: env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
2074
2069
  emailAndPassword: {
2075
2070
  enabled: true,
2076
2071
  sendResetPassword: async ({ user, url }) => {
@@ -2100,7 +2095,11 @@ export const auth = betterAuth({
2100
2095
  ],`;
2101
2096
  }
2102
2097
  content += `
2103
- })
2098
+ })
2099
+ }
2100
+
2101
+ // Lazy initialization - only create auth when needed
2102
+ export const auth = convex ? createAuth() : null
2104
2103
  `;
2105
2104
  await writeFile(path7.join(appDir, "src/lib/auth-server.ts"), content);
2106
2105
  }
@@ -2769,19 +2768,18 @@ async function generateRateLimiting(config, appDir) {
2769
2768
  }
2770
2769
  }
2771
2770
  async function generateArcjet(appDir) {
2772
- const content = `import arcjet, { shield, rateLimit, detectBot } from '@arcjet/next'
2771
+ const content = `import arcjet, { shield, fixedWindow, detectBot } from '@arcjet/next'
2773
2772
  import { env } from '@/env'
2774
2773
 
2775
2774
  export const aj = arcjet({
2776
- key: env.ARCJET_KEY,
2777
- characteristics: ['ip.src'],
2775
+ key: env.ARCJET_KEY!,
2778
2776
  rules: [
2779
2777
  // Shield protects against common attacks
2780
2778
  shield({ mode: 'LIVE' }),
2781
- // Rate limit API requests
2782
- rateLimit({
2779
+ // Rate limit API requests - 100 requests per minute
2780
+ fixedWindow({
2783
2781
  mode: 'LIVE',
2784
- interval: '1m',
2782
+ window: '1m',
2785
2783
  max: 100,
2786
2784
  }),
2787
2785
  // Bot detection
@@ -4270,517 +4268,8 @@ S3_ENDPOINT="https://[PROJECT].supabase.co/storage/v1/s3"
4270
4268
  await writeFile(path15.join(marketingDir, ".env.local"), envContent);
4271
4269
  }
4272
4270
 
4273
- // src/generators/fumadocs.ts
4274
- import path16 from "path";
4275
- async function generateFumadocs(config, docsDir) {
4276
- await ensureDir(path16.join(docsDir, "content/docs"));
4277
- await ensureDir(path16.join(docsDir, "src/app/docs/[[...slug]]"));
4278
- await ensureDir(path16.join(docsDir, "src/lib"));
4279
- await generateFumadocsPackageJson(docsDir);
4280
- await generateFumadocsNextConfig(docsDir);
4281
- await generateFumadocsTsConfig(docsDir);
4282
- await generateFumadocsSource(docsDir);
4283
- await generateFumadocsAppFiles(config, docsDir);
4284
- await generateFumadocsContent(config, docsDir);
4285
- }
4286
- async function generateFumadocsPackageJson(docsDir) {
4287
- const packageJson2 = {
4288
- name: "@repo/docs",
4289
- version: "0.1.0",
4290
- private: true,
4291
- scripts: {
4292
- dev: "next dev --turbopack -p 3002",
4293
- build: "next build",
4294
- start: "next start",
4295
- lint: "biome check .",
4296
- "lint:fix": "biome check --write .",
4297
- typecheck: "tsc --noEmit"
4298
- },
4299
- dependencies: {
4300
- next: "^16.0.0",
4301
- react: "^19.0.0",
4302
- "react-dom": "^19.0.0",
4303
- "fumadocs-core": "^16.0.0",
4304
- "fumadocs-mdx": "^14.0.0",
4305
- "fumadocs-ui": "^16.0.0",
4306
- "@repo/ui": "workspace:*"
4307
- },
4308
- devDependencies: {
4309
- "@repo/config-typescript": "workspace:*",
4310
- "@types/node": "^20.0.0",
4311
- "@types/react": "^19.0.0",
4312
- "@types/react-dom": "^19.0.0",
4313
- "@types/mdx": "^2.0.0",
4314
- tailwindcss: "^4.0.0",
4315
- "@tailwindcss/postcss": "^4.0.0",
4316
- postcss: "^8.4.0",
4317
- typescript: "^5.0.0"
4318
- }
4319
- };
4320
- await writeJSON(path16.join(docsDir, "package.json"), packageJson2);
4321
- }
4322
- async function generateFumadocsNextConfig(docsDir) {
4323
- const content = `import { createMDX } from 'fumadocs-mdx/next'
4324
- import type { NextConfig } from 'next'
4325
-
4326
- const withMDX = createMDX()
4327
-
4328
- const config: NextConfig = {
4329
- reactStrictMode: true,
4330
- transpilePackages: ['@repo/ui'],
4331
- }
4332
-
4333
- export default withMDX(config)
4334
- `;
4335
- await writeFile(path16.join(docsDir, "next.config.ts"), content);
4336
- }
4337
- async function generateFumadocsTsConfig(docsDir) {
4338
- const tsConfig = {
4339
- compilerOptions: {
4340
- target: "ES2020",
4341
- lib: ["dom", "dom.iterable", "esnext"],
4342
- allowJs: true,
4343
- skipLibCheck: true,
4344
- strict: true,
4345
- noEmit: true,
4346
- esModuleInterop: true,
4347
- module: "esnext",
4348
- moduleResolution: "bundler",
4349
- resolveJsonModule: true,
4350
- isolatedModules: true,
4351
- jsx: "preserve",
4352
- incremental: true,
4353
- plugins: [{ name: "next" }],
4354
- paths: {
4355
- "@/*": ["./src/*"],
4356
- "fumadocs-mdx:collections/*": ["./.source/*"]
4357
- }
4358
- },
4359
- include: [
4360
- "next-env.d.ts",
4361
- "**/*.ts",
4362
- "**/*.tsx",
4363
- "**/*.mdx",
4364
- ".next/types/**/*.ts",
4365
- ".source/**/*.ts"
4366
- ],
4367
- exclude: ["node_modules"]
4368
- };
4369
- await writeJSON(path16.join(docsDir, "tsconfig.json"), tsConfig);
4370
- }
4371
- async function generateFumadocsSource(docsDir) {
4372
- const content = `import { docs } from 'fumadocs-mdx:collections/server'
4373
- import { loader } from 'fumadocs-core/source'
4374
-
4375
- export const source = loader({
4376
- baseUrl: '/docs',
4377
- source: docs.toFumadocsSource(),
4378
- })
4379
- `;
4380
- await writeFile(path16.join(docsDir, "src/lib/source.ts"), content);
4381
- }
4382
- async function generateFumadocsAppFiles(config, docsDir) {
4383
- const layoutContent = `import { RootProvider } from 'fumadocs-ui/provider/next'
4384
- import { Inter } from 'next/font/google'
4385
- import type { Metadata } from 'next'
4386
- import type { ReactNode } from 'react'
4387
- import './global.css'
4388
-
4389
- const inter = Inter({
4390
- subsets: ['latin'],
4391
- })
4392
-
4393
- export const metadata: Metadata = {
4394
- title: {
4395
- template: '%s | ${config.name} Docs',
4396
- default: '${config.name} Documentation',
4397
- },
4398
- description: 'Documentation for ${config.name}',
4399
- }
4400
-
4401
- export default function RootLayout({ children }: { children: ReactNode }) {
4402
- return (
4403
- <html lang="en" className={inter.className} suppressHydrationWarning>
4404
- <body className="flex flex-col min-h-screen">
4405
- <RootProvider>{children}</RootProvider>
4406
- </body>
4407
- </html>
4408
- )
4409
- }
4410
- `;
4411
- await writeFile(path16.join(docsDir, "src/app/layout.tsx"), layoutContent);
4412
- const docsLayoutContent = `import { DocsLayout } from 'fumadocs-ui/layouts/docs'
4413
- import type { ReactNode } from 'react'
4414
- import { source } from '@/lib/source'
4415
-
4416
- export default function Layout({ children }: { children: ReactNode }) {
4417
- return (
4418
- <DocsLayout
4419
- tree={source.pageTree}
4420
- nav={{
4421
- title: '${config.name} Docs',
4422
- }}
4423
- >
4424
- {children}
4425
- </DocsLayout>
4426
- )
4427
- }
4428
- `;
4429
- await writeFile(
4430
- path16.join(docsDir, "src/app/docs/layout.tsx"),
4431
- docsLayoutContent
4432
- );
4433
- const docsPageContent = `import { source } from '@/lib/source'
4434
- import {
4435
- DocsPage,
4436
- DocsBody,
4437
- DocsDescription,
4438
- DocsTitle,
4439
- } from 'fumadocs-ui/page'
4440
- import { notFound } from 'next/navigation'
4441
- import defaultMdxComponents from 'fumadocs-ui/mdx'
4442
-
4443
- export default async function Page(props: {
4444
- params: Promise<{ slug?: string[] }>
4445
- }) {
4446
- const params = await props.params
4447
- const page = source.getPage(params.slug)
4448
- if (!page) notFound()
4449
-
4450
- const MDX = page.data.body
4451
-
4452
- return (
4453
- <DocsPage toc={page.data.toc} full={page.data.full}>
4454
- <DocsTitle>{page.data.title}</DocsTitle>
4455
- <DocsDescription>{page.data.description}</DocsDescription>
4456
- <DocsBody>
4457
- <MDX components={{ ...defaultMdxComponents }} />
4458
- </DocsBody>
4459
- </DocsPage>
4460
- )
4461
- }
4462
-
4463
- export async function generateStaticParams() {
4464
- return source.generateParams()
4465
- }
4466
-
4467
- export async function generateMetadata(props: {
4468
- params: Promise<{ slug?: string[] }>
4469
- }) {
4470
- const params = await props.params
4471
- const page = source.getPage(params.slug)
4472
- if (!page) notFound()
4473
-
4474
- return {
4475
- title: page.data.title,
4476
- description: page.data.description,
4477
- }
4478
- }
4479
- `;
4480
- await writeFile(
4481
- path16.join(docsDir, "src/app/docs/[[...slug]]/page.tsx"),
4482
- docsPageContent
4483
- );
4484
- const homePageContent = `import { redirect } from 'next/navigation'
4485
-
4486
- export default function HomePage() {
4487
- redirect('/docs')
4488
- }
4489
- `;
4490
- await writeFile(path16.join(docsDir, "src/app/page.tsx"), homePageContent);
4491
- const globalCssContent = `@import 'tailwindcss';
4492
- @import 'fumadocs-ui/css/neutral.css';
4493
- @import 'fumadocs-ui/css/preset.css';
4494
-
4495
- @source '../node_modules/fumadocs-ui/dist/**/*.js';
4496
- `;
4497
- await writeFile(path16.join(docsDir, "src/app/global.css"), globalCssContent);
4498
- const sourceConfigContent = `import { defineDocs, defineConfig } from 'fumadocs-mdx/config'
4499
-
4500
- export const { docs, meta } = defineDocs({
4501
- dir: 'content/docs',
4502
- })
4503
-
4504
- export default defineConfig()
4505
- `;
4506
- await writeFile(path16.join(docsDir, "source.config.ts"), sourceConfigContent);
4507
- const postcssContent = `export default {
4508
- plugins: {
4509
- '@tailwindcss/postcss': {},
4510
- },
4511
- }
4512
- `;
4513
- await writeFile(path16.join(docsDir, "postcss.config.mjs"), postcssContent);
4514
- }
4515
- async function generateFumadocsContent(config, docsDir) {
4516
- const metaJson = {
4517
- title: "Documentation",
4518
- pages: ["index", "getting-started", "---", "guides", "api"]
4519
- };
4520
- await writeJSON(path16.join(docsDir, "content/docs/meta.json"), metaJson);
4521
- const indexContent = `---
4522
- title: Introduction
4523
- description: Welcome to ${config.name} documentation
4524
- ---
4525
-
4526
- # Welcome to ${config.name}
4527
-
4528
- This is the documentation for ${config.name}, built with [Fumadocs](https://fumadocs.vercel.app).
4529
-
4530
- ## Features
4531
-
4532
- - Built with Next.js 15 and React 19
4533
- - Convex for real-time database
4534
- - Better-Auth for authentication
4535
- - shadcn/ui components
4536
- - Tailwind CSS v4
4537
-
4538
- ## Getting Started
4539
-
4540
- Check out the [Getting Started](/docs/getting-started) guide to begin.
4541
- `;
4542
- await writeFile(
4543
- path16.join(docsDir, "content/docs/index.mdx"),
4544
- indexContent
4545
- );
4546
- const gettingStartedContent = `---
4547
- title: Getting Started
4548
- description: Get started with ${config.name}
4549
- ---
4550
-
4551
- # Getting Started
4552
-
4553
- This guide will help you get ${config.name} up and running.
4554
-
4555
- ## Prerequisites
4556
-
4557
- - Node.js 18 or higher
4558
- - pnpm package manager
4559
-
4560
- ## Installation
4561
-
4562
- 1. Clone the repository
4563
- 2. Install dependencies:
4564
-
4565
- \`\`\`bash
4566
- pnpm install
4567
- \`\`\`
4568
-
4569
- 3. Copy environment variables:
4570
-
4571
- \`\`\`bash
4572
- cp .env.example .env.local
4573
- \`\`\`
4574
-
4575
- 4. Set up Convex:
4576
-
4577
- \`\`\`bash
4578
- pnpm convex dev
4579
- \`\`\`
4580
-
4581
- 5. Start the development server:
4582
-
4583
- \`\`\`bash
4584
- pnpm dev
4585
- \`\`\`
4586
-
4587
- ## Next Steps
4588
-
4589
- - [Configure authentication](/docs/guides/authentication)
4590
- - [Set up your database schema](/docs/guides/database)
4591
- - [Customize the UI](/docs/guides/customization)
4592
- `;
4593
- await writeFile(
4594
- path16.join(docsDir, "content/docs/getting-started.mdx"),
4595
- gettingStartedContent
4596
- );
4597
- await ensureDir(path16.join(docsDir, "content/docs/guides"));
4598
- const guidesMetaJson = {
4599
- title: "Guides",
4600
- pages: ["authentication", "database", "customization"]
4601
- };
4602
- await writeJSON(
4603
- path16.join(docsDir, "content/docs/guides/meta.json"),
4604
- guidesMetaJson
4605
- );
4606
- const authGuideContent = `---
4607
- title: Authentication
4608
- description: Learn how to configure authentication in ${config.name}
4609
- ---
4610
-
4611
- # Authentication
4612
-
4613
- ${config.name} uses Better-Auth with Convex for authentication.
4614
-
4615
- ## Supported Providers
4616
-
4617
- - Email/Password (always enabled)
4618
- - Google OAuth (always enabled)
4619
- ${config.auth.providers.map((p8) => `- ${p8.charAt(0).toUpperCase() + p8.slice(1)}`).join("\n")}
4620
-
4621
- ## Configuration
4622
-
4623
- Authentication is configured in \`convex/auth.ts\`.
4624
-
4625
- \`\`\`typescript
4626
- export const { auth, createAuth } = new BetterAuth<DataModel>(components.betterAuth, {
4627
- emailAndPassword: {
4628
- enabled: true,
4629
- },
4630
- socialProviders: {
4631
- google: {
4632
- clientId: process.env.GOOGLE_CLIENT_ID!,
4633
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
4634
- },
4635
- },
4636
- })
4637
- \`\`\`
4638
-
4639
- ## Using Authentication
4640
-
4641
- Use the auth client in your components:
4642
-
4643
- \`\`\`typescript
4644
- import { signIn, signOut, useSession } from '@/lib/auth'
4645
-
4646
- // Sign in
4647
- await signIn.email({ email, password })
4648
-
4649
- // Sign out
4650
- await signOut()
4651
-
4652
- // Get session
4653
- const { data: session } = useSession()
4654
- \`\`\`
4655
- `;
4656
- await writeFile(
4657
- path16.join(docsDir, "content/docs/guides/authentication.mdx"),
4658
- authGuideContent
4659
- );
4660
- const databaseGuideContent = `---
4661
- title: Database
4662
- description: Working with Convex database
4663
- ---
4664
-
4665
- # Database
4666
-
4667
- ${config.name} uses Convex as its database.
4668
-
4669
- ## Schema
4670
-
4671
- The database schema is defined in \`convex/schema.ts\`.
4672
-
4673
- ## Queries
4674
-
4675
- Create queries to read data:
4676
-
4677
- \`\`\`typescript
4678
- import { query } from './_generated/server'
4679
-
4680
- export const getUsers = query({
4681
- handler: async (ctx) => {
4682
- return await ctx.db.query('users').collect()
4683
- },
4684
- })
4685
- \`\`\`
4686
-
4687
- ## Mutations
4688
-
4689
- Create mutations to write data:
4690
-
4691
- \`\`\`typescript
4692
- import { mutation } from './_generated/server'
4693
- import { v } from 'convex/values'
4694
-
4695
- export const createUser = mutation({
4696
- args: {
4697
- name: v.string(),
4698
- email: v.string(),
4699
- },
4700
- handler: async (ctx, args) => {
4701
- return await ctx.db.insert('users', args)
4702
- },
4703
- })
4704
- \`\`\`
4705
- `;
4706
- await writeFile(
4707
- path16.join(docsDir, "content/docs/guides/database.mdx"),
4708
- databaseGuideContent
4709
- );
4710
- const customizationGuideContent = `---
4711
- title: Customization
4712
- description: Customize the look and feel of ${config.name}
4713
- ---
4714
-
4715
- # Customization
4716
-
4717
- ## Theme
4718
-
4719
- The theme is configured in \`src/app/globals.css\` using Tailwind CSS v4.
4720
-
4721
- ### Colors
4722
-
4723
- Update the theme colors in the CSS:
4724
-
4725
- \`\`\`css
4726
- @theme {
4727
- --color-primary: oklch(0.6 0.2 250);
4728
- --color-primary-foreground: oklch(0.98 0 0);
4729
- }
4730
- \`\`\`
4731
-
4732
- ### Dark Mode
4733
-
4734
- Dark mode is supported out of the box. Define dark mode styles with:
4735
-
4736
- \`\`\`css
4737
- .dark {
4738
- --color-background: oklch(0.145 0 0);
4739
- }
4740
- \`\`\`
4741
-
4742
- ## Components
4743
-
4744
- UI components are in \`src/components/ui\`. Customize or add new components as needed.
4745
- `;
4746
- await writeFile(
4747
- path16.join(docsDir, "content/docs/guides/customization.mdx"),
4748
- customizationGuideContent
4749
- );
4750
- await ensureDir(path16.join(docsDir, "content/docs/api"));
4751
- const apiMetaJson = {
4752
- title: "API Reference",
4753
- pages: ["overview"]
4754
- };
4755
- await writeJSON(
4756
- path16.join(docsDir, "content/docs/api/meta.json"),
4757
- apiMetaJson
4758
- );
4759
- const apiOverviewContent = `---
4760
- title: API Overview
4761
- description: API reference for ${config.name}
4762
- ---
4763
-
4764
- # API Reference
4765
-
4766
- This section contains the API reference for ${config.name}.
4767
-
4768
- ## Authentication API
4769
-
4770
- See the [Better-Auth documentation](https://www.better-auth.com) for detailed API reference.
4771
-
4772
- ## Database API
4773
-
4774
- See the [Convex documentation](https://docs.convex.dev) for database API reference.
4775
- `;
4776
- await writeFile(
4777
- path16.join(docsDir, "content/docs/api/overview.mdx"),
4778
- apiOverviewContent
4779
- );
4780
- }
4781
-
4782
4271
  // src/generators/design-system.ts
4783
- import path17 from "path";
4272
+ import path16 from "path";
4784
4273
  var fontImports = {
4785
4274
  inter: {
4786
4275
  import: "import { Inter } from 'next/font/google'",
@@ -4848,17 +4337,17 @@ var spacingMultipliers = {
4848
4337
  relaxed: 1.125
4849
4338
  };
4850
4339
  async function generateDesignSystemApp(config, targetDir) {
4851
- const appDir = path17.join(targetDir, "apps/design-system");
4852
- await ensureDir(path17.join(appDir, "src/app"));
4853
- await ensureDir(path17.join(appDir, "src/app/colors"));
4854
- await ensureDir(path17.join(appDir, "src/app/typography"));
4855
- await ensureDir(path17.join(appDir, "src/app/spacing"));
4856
- await ensureDir(path17.join(appDir, "src/app/brand"));
4857
- await ensureDir(path17.join(appDir, "src/app/blocks"));
4858
- await ensureDir(path17.join(appDir, "src/app/components"));
4859
- await ensureDir(path17.join(appDir, "src/app/components/[slug]"));
4860
- await ensureDir(path17.join(appDir, "src/lib"));
4861
- await ensureDir(path17.join(appDir, "public/brand"));
4340
+ const appDir = path16.join(targetDir, "apps/design-system");
4341
+ await ensureDir(path16.join(appDir, "src/app"));
4342
+ await ensureDir(path16.join(appDir, "src/app/colors"));
4343
+ await ensureDir(path16.join(appDir, "src/app/typography"));
4344
+ await ensureDir(path16.join(appDir, "src/app/spacing"));
4345
+ await ensureDir(path16.join(appDir, "src/app/brand"));
4346
+ await ensureDir(path16.join(appDir, "src/app/blocks"));
4347
+ await ensureDir(path16.join(appDir, "src/app/components"));
4348
+ await ensureDir(path16.join(appDir, "src/app/components/[slug]"));
4349
+ await ensureDir(path16.join(appDir, "src/lib"));
4350
+ await ensureDir(path16.join(appDir, "public/brand"));
4862
4351
  await generatePackageJson2(config, appDir);
4863
4352
  await generateTsConfig2(appDir);
4864
4353
  await generateNextConfig2(appDir);
@@ -4911,7 +4400,7 @@ async function generatePackageJson2(config, appDir) {
4911
4400
  typescript: "^5.0.0"
4912
4401
  }
4913
4402
  };
4914
- await writeJSON(path17.join(appDir, "package.json"), packageJson2);
4403
+ await writeJSON(path16.join(appDir, "package.json"), packageJson2);
4915
4404
  }
4916
4405
  async function generateTsConfig2(appDir) {
4917
4406
  const tsConfig = {
@@ -4939,7 +4428,7 @@ async function generateTsConfig2(appDir) {
4939
4428
  include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
4940
4429
  exclude: ["node_modules"]
4941
4430
  };
4942
- await writeJSON(path17.join(appDir, "tsconfig.json"), tsConfig);
4431
+ await writeJSON(path16.join(appDir, "tsconfig.json"), tsConfig);
4943
4432
  }
4944
4433
  async function generateNextConfig2(appDir) {
4945
4434
  const content = `import type { NextConfig } from 'next'
@@ -4950,7 +4439,7 @@ const nextConfig: NextConfig = {
4950
4439
 
4951
4440
  export default nextConfig
4952
4441
  `;
4953
- await writeFile(path17.join(appDir, "next.config.ts"), content);
4442
+ await writeFile(path16.join(appDir, "next.config.ts"), content);
4954
4443
  }
4955
4444
  async function generatePostCssConfig2(appDir) {
4956
4445
  const content = `export default {
@@ -4959,7 +4448,7 @@ async function generatePostCssConfig2(appDir) {
4959
4448
  },
4960
4449
  }
4961
4450
  `;
4962
- await writeFile(path17.join(appDir, "postcss.config.mjs"), content);
4451
+ await writeFile(path16.join(appDir, "postcss.config.mjs"), content);
4963
4452
  }
4964
4453
  async function generateGlobalsCss2(config, appDir) {
4965
4454
  const { designSystem } = config;
@@ -5219,7 +4708,7 @@ h1, h2, h3, h4, h5, h6 {
5219
4708
  }
5220
4709
  }
5221
4710
  `;
5222
- await writeFile(path17.join(appDir, "src/app/globals.css"), content);
4711
+ await writeFile(path16.join(appDir, "src/app/globals.css"), content);
5223
4712
  }
5224
4713
  async function generateLayoutTsx(config, appDir) {
5225
4714
  const { designSystem } = config;
@@ -5418,7 +4907,7 @@ function ThemeToggle() {
5418
4907
  )
5419
4908
  }
5420
4909
  `;
5421
- await writeFile(path17.join(appDir, "src/app/layout.tsx"), content);
4910
+ await writeFile(path16.join(appDir, "src/app/layout.tsx"), content);
5422
4911
  }
5423
4912
  async function generateHomePage(config, appDir) {
5424
4913
  const content = `export default function DesignSystemHome() {
@@ -5584,7 +5073,7 @@ function Principle({
5584
5073
  )
5585
5074
  }
5586
5075
  `;
5587
- await writeFile(path17.join(appDir, "src/app/page.tsx"), content);
5076
+ await writeFile(path16.join(appDir, "src/app/page.tsx"), content);
5588
5077
  }
5589
5078
  async function generateColorsPage(config, appDir) {
5590
5079
  const content = `export default function ColorsPage() {
@@ -5753,7 +5242,7 @@ function ColorCard({
5753
5242
  )
5754
5243
  }
5755
5244
  `;
5756
- await writeFile(path17.join(appDir, "src/app/colors/page.tsx"), content);
5245
+ await writeFile(path16.join(appDir, "src/app/colors/page.tsx"), content);
5757
5246
  }
5758
5247
  async function generateTypographyPage(config, appDir) {
5759
5248
  const { designSystem } = config;
@@ -5910,7 +5399,7 @@ function WeightCard({ weight, name }: { weight: string; name: string }) {
5910
5399
  )
5911
5400
  }
5912
5401
  `;
5913
- await writeFile(path17.join(appDir, "src/app/typography/page.tsx"), content);
5402
+ await writeFile(path16.join(appDir, "src/app/typography/page.tsx"), content);
5914
5403
  }
5915
5404
  async function generateSpacingPage(config, appDir) {
5916
5405
  const { designSystem } = config;
@@ -6043,7 +5532,7 @@ function PatternCard({
6043
5532
  )
6044
5533
  }
6045
5534
  `;
6046
- await writeFile(path17.join(appDir, "src/app/spacing/page.tsx"), content);
5535
+ await writeFile(path16.join(appDir, "src/app/spacing/page.tsx"), content);
6047
5536
  }
6048
5537
  async function generateBrandPage(config, appDir) {
6049
5538
  const content = `export default function BrandPage() {
@@ -6181,7 +5670,7 @@ function DownloadCard({
6181
5670
  )
6182
5671
  }
6183
5672
  `;
6184
- await writeFile(path17.join(appDir, "src/app/brand/page.tsx"), content);
5673
+ await writeFile(path16.join(appDir, "src/app/brand/page.tsx"), content);
6185
5674
  }
6186
5675
  async function generateBlocksPage(appDir) {
6187
5676
  const content = `export default function BlocksPage() {
@@ -6243,7 +5732,7 @@ function BlockCard({ title, description }: { title: string; description: string
6243
5732
  )
6244
5733
  }
6245
5734
  `;
6246
- await writeFile(path17.join(appDir, "src/app/blocks/page.tsx"), content);
5735
+ await writeFile(path16.join(appDir, "src/app/blocks/page.tsx"), content);
6247
5736
  }
6248
5737
  async function generateComponentsPage(appDir) {
6249
5738
  const content = `export default function ComponentsPage() {
@@ -6323,7 +5812,7 @@ function CategoryCard({
6323
5812
  )
6324
5813
  }
6325
5814
  `;
6326
- await writeFile(path17.join(appDir, "src/app/components/page.tsx"), content);
5815
+ await writeFile(path16.join(appDir, "src/app/components/page.tsx"), content);
6327
5816
  }
6328
5817
  async function generateComponentSlugPage(appDir) {
6329
5818
  const content = `import { notFound } from 'next/navigation'
@@ -6427,7 +5916,7 @@ export function generateStaticParams() {
6427
5916
  return components.map((slug) => ({ slug }))
6428
5917
  }
6429
5918
  `;
6430
- await writeFile(path17.join(appDir, "src/app/components/[slug]/page.tsx"), content);
5919
+ await writeFile(path16.join(appDir, "src/app/components/[slug]/page.tsx"), content);
6431
5920
  }
6432
5921
  async function generateUtils(appDir) {
6433
5922
  const content = `import { clsx, type ClassValue } from 'clsx'
@@ -6437,7 +5926,7 @@ export function cn(...inputs: ClassValue[]) {
6437
5926
  return twMerge(clsx(inputs))
6438
5927
  }
6439
5928
  `;
6440
- await writeFile(path17.join(appDir, "src/lib/utils.ts"), content);
5929
+ await writeFile(path16.join(appDir, "src/lib/utils.ts"), content);
6441
5930
  }
6442
5931
 
6443
5932
  // src/setup/env-wizard.ts
@@ -6445,7 +5934,7 @@ import * as p6 from "@clack/prompts";
6445
5934
  import pc2 from "picocolors";
6446
5935
  import { exec } from "child_process";
6447
5936
  import { promisify } from "util";
6448
- import path18 from "path";
5937
+ import path17 from "path";
6449
5938
  var execAsync = promisify(exec);
6450
5939
  async function runEnvSetupWizard(config) {
6451
5940
  console.log();
@@ -6526,7 +6015,7 @@ This will open your browser to create a new project on Convex.
6526
6015
  ${pc2.dim("Note: Make sure you have a Convex account at https://convex.dev")}
6527
6016
  `);
6528
6017
  try {
6529
- const convexDir = config.structure === "monorepo" ? path18.join(config.targetDir, "packages/backend") : config.targetDir;
6018
+ const convexDir = config.structure === "monorepo" ? path17.join(config.targetDir, "packages/backend") : config.targetDir;
6530
6019
  const { spawn } = await import("child_process");
6531
6020
  p6.log.info(`Installing dependencies in ${pc2.dim(convexDir)}...`);
6532
6021
  const installSuccess = await new Promise((resolve) => {
@@ -6802,7 +6291,7 @@ async function writeEnvFiles(config, envValues) {
6802
6291
  return;
6803
6292
  }
6804
6293
  p6.log.step("Writing environment files...");
6805
- const webEnvPath = config.structure === "monorepo" ? path18.join(config.targetDir, "apps/web/.env.local") : path18.join(config.targetDir, ".env.local");
6294
+ const webEnvPath = config.structure === "monorepo" ? path17.join(config.targetDir, "apps/web/.env.local") : path17.join(config.targetDir, ".env.local");
6806
6295
  if (await pathExists(webEnvPath)) {
6807
6296
  let content = await readFile(webEnvPath);
6808
6297
  for (const [key, value] of Object.entries(envValues)) {
@@ -6821,7 +6310,7 @@ ${key}="${value}"`;
6821
6310
  p6.log.success(`Updated ${config.structure === "monorepo" ? "apps/web/.env.local" : ".env.local"}`);
6822
6311
  }
6823
6312
  if (config.marketingSite === "payload" && config.structure === "monorepo") {
6824
- const marketingEnvPath = path18.join(config.targetDir, "apps/marketing/.env.local");
6313
+ const marketingEnvPath = path17.join(config.targetDir, "apps/marketing/.env.local");
6825
6314
  if (await pathExists(marketingEnvPath)) {
6826
6315
  let content = await readFile(marketingEnvPath);
6827
6316
  const payloadEnvKeys = ["PAYLOAD_SECRET", "DATABASE_URL", "S3_ENDPOINT", "S3_REGION", "S3_BUCKET", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY", "CRON_SECRET", "PREVIEW_SECRET"];
@@ -6882,7 +6371,7 @@ async function generateSingleProject(config, spinner) {
6882
6371
  await generateShadcn(config, targetDir);
6883
6372
  spinner.succeed("shadcn/ui configured");
6884
6373
  spinner.start("Setting up Convex...");
6885
- await generateConvex(config, path19.join(targetDir, "convex"));
6374
+ await generateConvex(config, path18.join(targetDir, "convex"));
6886
6375
  spinner.succeed("Convex configured");
6887
6376
  spinner.start("Configuring Better-Auth...");
6888
6377
  await generateBetterAuth(config, targetDir);
@@ -6925,7 +6414,7 @@ async function generateMonorepoProject(config, spinner) {
6925
6414
  spinner.start("Creating shared UI package...");
6926
6415
  await generateUIPackage(config, targetDir);
6927
6416
  spinner.succeed("Shared UI package created");
6928
- const webDir = path19.join(targetDir, "apps/web");
6417
+ const webDir = path18.join(targetDir, "apps/web");
6929
6418
  spinner.start("Generating web application...");
6930
6419
  await generateBaseNextjs(config, webDir);
6931
6420
  await generateTailwind(config, webDir);
@@ -6935,10 +6424,10 @@ async function generateMonorepoProject(config, spinner) {
6935
6424
  await generateEmail(config, webDir);
6936
6425
  await updateWebTsConfig(webDir);
6937
6426
  spinner.succeed("Web application generated");
6938
- const backendDir = path19.join(targetDir, "packages/backend");
6427
+ const backendDir = path18.join(targetDir, "packages/backend");
6939
6428
  spinner.start("Setting up Convex backend...");
6940
6429
  await ensureDir(backendDir);
6941
- await generateConvex(config, path19.join(backendDir, "convex"));
6430
+ await generateConvex(config, path18.join(backendDir, "convex"));
6942
6431
  spinner.succeed("Convex backend configured");
6943
6432
  if (config.integrations.analytics !== "none") {
6944
6433
  spinner.start(`Setting up ${config.integrations.analytics} analytics...`);
@@ -6961,7 +6450,7 @@ async function generateMonorepoProject(config, spinner) {
6961
6450
  spinner.succeed(`${config.integrations.monitoring} monitoring configured`);
6962
6451
  }
6963
6452
  if (config.marketingSite !== "none") {
6964
- const marketingDir = path19.join(targetDir, "apps/marketing");
6453
+ const marketingDir = path18.join(targetDir, "apps/marketing");
6965
6454
  spinner.start(`Generating ${config.marketingSite} marketing site...`);
6966
6455
  if (config.marketingSite === "payload") {
6967
6456
  await generatePayload(config, marketingDir);
@@ -6970,12 +6459,6 @@ async function generateMonorepoProject(config, spinner) {
6970
6459
  }
6971
6460
  spinner.succeed(`${config.marketingSite} marketing site generated`);
6972
6461
  }
6973
- if (config.includeDocs) {
6974
- const docsDir = path19.join(targetDir, "apps/docs");
6975
- spinner.start("Generating Fumadocs documentation site...");
6976
- await generateFumadocs(config, docsDir);
6977
- spinner.succeed("Fumadocs documentation site generated");
6978
- }
6979
6462
  spinner.start("Generating design system app...");
6980
6463
  await generateDesignSystemApp(config, targetDir);
6981
6464
  spinner.succeed("Design system app generated");
@@ -6992,7 +6475,7 @@ async function runPostGenerationSteps(config, spinner) {
6992
6475
  }
6993
6476
  spinner.start("Installing shadcn/ui components...");
6994
6477
  try {
6995
- const shadcnDir = config.structure === "monorepo" ? path19.join(targetDir, "packages/ui") : targetDir;
6478
+ const shadcnDir = config.structure === "monorepo" ? path18.join(targetDir, "packages/ui") : targetDir;
6996
6479
  await runShadcnAdd(shadcnDir);
6997
6480
  spinner.succeed("shadcn/ui components installed");
6998
6481
  } catch (error) {
@@ -7052,7 +6535,7 @@ async function generateBiomeConfig(targetDir) {
7052
6535
  }
7053
6536
  };
7054
6537
  await writeFile(
7055
- path19.join(targetDir, "biome.json"),
6538
+ path18.join(targetDir, "biome.json"),
7056
6539
  JSON.stringify(biomeJson, null, 2)
7057
6540
  );
7058
6541
  }
@@ -7103,13 +6586,13 @@ yarn-error.log*
7103
6586
  *.pem
7104
6587
  .cache
7105
6588
  `;
7106
- await writeFile(path19.join(targetDir, ".gitignore"), gitignoreContent);
6589
+ await writeFile(path18.join(targetDir, ".gitignore"), gitignoreContent);
7107
6590
  }
7108
6591
  async function generateHuskyHooks(targetDir) {
7109
6592
  const preCommitContent = `pnpm lint-staged
7110
6593
  `;
7111
- await ensureDir(path19.join(targetDir, ".husky"));
7112
- await writeFile(path19.join(targetDir, ".husky/pre-commit"), preCommitContent);
6594
+ await ensureDir(path18.join(targetDir, ".husky"));
6595
+ await writeFile(path18.join(targetDir, ".husky/pre-commit"), preCommitContent);
7113
6596
  }
7114
6597
  async function updateWebTsConfig(webDir) {
7115
6598
  const tsConfig = {
@@ -7136,14 +6619,14 @@ async function updateWebTsConfig(webDir) {
7136
6619
  exclude: ["node_modules"]
7137
6620
  };
7138
6621
  await writeFile(
7139
- path19.join(webDir, "tsconfig.json"),
6622
+ path18.join(webDir, "tsconfig.json"),
7140
6623
  JSON.stringify(tsConfig, null, 2)
7141
6624
  );
7142
6625
  }
7143
6626
  async function generateNextjsMarketing(config, marketingDir) {
7144
- await ensureDir(path19.join(marketingDir, "src/app"));
7145
- await ensureDir(path19.join(marketingDir, "src/components"));
7146
- await ensureDir(path19.join(marketingDir, "public"));
6627
+ await ensureDir(path18.join(marketingDir, "src/app"));
6628
+ await ensureDir(path18.join(marketingDir, "src/components"));
6629
+ await ensureDir(path18.join(marketingDir, "public"));
7147
6630
  const packageJson2 = {
7148
6631
  name: "@repo/marketing",
7149
6632
  version: "0.1.0",
@@ -7174,7 +6657,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7174
6657
  }
7175
6658
  };
7176
6659
  await writeFile(
7177
- path19.join(marketingDir, "package.json"),
6660
+ path18.join(marketingDir, "package.json"),
7178
6661
  JSON.stringify(packageJson2, null, 2)
7179
6662
  );
7180
6663
  const homePageContent = `export default function HomePage() {
@@ -7197,7 +6680,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7197
6680
  }
7198
6681
  `;
7199
6682
  await writeFile(
7200
- path19.join(marketingDir, "src/app/page.tsx"),
6683
+ path18.join(marketingDir, "src/app/page.tsx"),
7201
6684
  homePageContent
7202
6685
  );
7203
6686
  const layoutContent = `import type { Metadata } from 'next'
@@ -7221,7 +6704,7 @@ export default function RootLayout({
7221
6704
  }
7222
6705
  `;
7223
6706
  await writeFile(
7224
- path19.join(marketingDir, "src/app/layout.tsx"),
6707
+ path18.join(marketingDir, "src/app/layout.tsx"),
7225
6708
  layoutContent
7226
6709
  );
7227
6710
  const globalsCss = `@import "tailwindcss";
@@ -7233,7 +6716,7 @@ export default function RootLayout({
7233
6716
  }
7234
6717
  `;
7235
6718
  await writeFile(
7236
- path19.join(marketingDir, "src/app/globals.css"),
6719
+ path18.join(marketingDir, "src/app/globals.css"),
7237
6720
  globalsCss
7238
6721
  );
7239
6722
  const tsConfig = {
@@ -7260,7 +6743,7 @@ export default function RootLayout({
7260
6743
  exclude: ["node_modules"]
7261
6744
  };
7262
6745
  await writeFile(
7263
- path19.join(marketingDir, "tsconfig.json"),
6746
+ path18.join(marketingDir, "tsconfig.json"),
7264
6747
  JSON.stringify(tsConfig, null, 2)
7265
6748
  );
7266
6749
  const nextConfig = `import type { NextConfig } from 'next'
@@ -7271,14 +6754,14 @@ const nextConfig: NextConfig = {
7271
6754
 
7272
6755
  export default nextConfig
7273
6756
  `;
7274
- await writeFile(path19.join(marketingDir, "next.config.ts"), nextConfig);
6757
+ await writeFile(path18.join(marketingDir, "next.config.ts"), nextConfig);
7275
6758
  const postcssConfig = `export default {
7276
6759
  plugins: {
7277
6760
  '@tailwindcss/postcss': {},
7278
6761
  },
7279
6762
  }
7280
6763
  `;
7281
- await writeFile(path19.join(marketingDir, "postcss.config.mjs"), postcssConfig);
6764
+ await writeFile(path18.join(marketingDir, "postcss.config.mjs"), postcssConfig);
7282
6765
  }
7283
6766
  function displaySuccessMessage(config) {
7284
6767
  const apps = ["web"];
@@ -7286,9 +6769,6 @@ function displaySuccessMessage(config) {
7286
6769
  if (config.marketingSite !== "none") {
7287
6770
  apps.push("marketing");
7288
6771
  }
7289
- if (config.includeDocs) {
7290
- apps.push("docs");
7291
- }
7292
6772
  apps.push("design-system");
7293
6773
  }
7294
6774
  console.log();
@@ -7321,9 +6801,6 @@ function displaySuccessMessage(config) {
7321
6801
  if (config.marketingSite === "payload") {
7322
6802
  console.log(` ${pc3.dim("-")} Payload CMS: ${pc3.cyan("https://payloadcms.com/docs")}`);
7323
6803
  }
7324
- if (config.includeDocs) {
7325
- console.log(` ${pc3.dim("-")} Fumadocs: ${pc3.cyan("https://fumadocs.vercel.app")}`);
7326
- }
7327
6804
  console.log();
7328
6805
  }
7329
6806
 
@@ -7351,7 +6828,7 @@ program.name("create-kofi-stack").description(
7351
6828
  ).version(packageJson.version).argument("[project-name]", "Name of the project").option("--monorepo", "Use monorepo structure with Turborepo").option("--single", "Use single app structure").option(
7352
6829
  "--marketing <type>",
7353
6830
  "Marketing site type: payload, nextjs, none"
7354
- ).option("--docs", "Include documentation site (Fumadocs)").option("--no-docs", "Exclude documentation site").option(
6831
+ ).option(
7355
6832
  "--component-library <library>",
7356
6833
  "Component library: base (Base UI), radix (Radix UI)"
7357
6834
  ).option(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kofi-stack",
3
- "version": "1.2.18",
3
+ "version": "1.2.20",
4
4
  "description": "Scaffold opinionated full-stack projects with Next.js, Convex, Better-Auth, and more",
5
5
  "type": "module",
6
6
  "bin": {