create-kofi-stack 1.2.18 → 1.2.19

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 +59 -605
  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";
@@ -2769,19 +2745,18 @@ async function generateRateLimiting(config, appDir) {
2769
2745
  }
2770
2746
  }
2771
2747
  async function generateArcjet(appDir) {
2772
- const content = `import arcjet, { shield, rateLimit, detectBot } from '@arcjet/next'
2748
+ const content = `import arcjet, { shield, fixedWindow, detectBot } from '@arcjet/next'
2773
2749
  import { env } from '@/env'
2774
2750
 
2775
2751
  export const aj = arcjet({
2776
- key: env.ARCJET_KEY,
2777
- characteristics: ['ip.src'],
2752
+ key: env.ARCJET_KEY!,
2778
2753
  rules: [
2779
2754
  // Shield protects against common attacks
2780
2755
  shield({ mode: 'LIVE' }),
2781
- // Rate limit API requests
2782
- rateLimit({
2756
+ // Rate limit API requests - 100 requests per minute
2757
+ fixedWindow({
2783
2758
  mode: 'LIVE',
2784
- interval: '1m',
2759
+ window: '1m',
2785
2760
  max: 100,
2786
2761
  }),
2787
2762
  // Bot detection
@@ -4270,517 +4245,8 @@ S3_ENDPOINT="https://[PROJECT].supabase.co/storage/v1/s3"
4270
4245
  await writeFile(path15.join(marketingDir, ".env.local"), envContent);
4271
4246
  }
4272
4247
 
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
4248
  // src/generators/design-system.ts
4783
- import path17 from "path";
4249
+ import path16 from "path";
4784
4250
  var fontImports = {
4785
4251
  inter: {
4786
4252
  import: "import { Inter } from 'next/font/google'",
@@ -4848,17 +4314,17 @@ var spacingMultipliers = {
4848
4314
  relaxed: 1.125
4849
4315
  };
4850
4316
  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"));
4317
+ const appDir = path16.join(targetDir, "apps/design-system");
4318
+ await ensureDir(path16.join(appDir, "src/app"));
4319
+ await ensureDir(path16.join(appDir, "src/app/colors"));
4320
+ await ensureDir(path16.join(appDir, "src/app/typography"));
4321
+ await ensureDir(path16.join(appDir, "src/app/spacing"));
4322
+ await ensureDir(path16.join(appDir, "src/app/brand"));
4323
+ await ensureDir(path16.join(appDir, "src/app/blocks"));
4324
+ await ensureDir(path16.join(appDir, "src/app/components"));
4325
+ await ensureDir(path16.join(appDir, "src/app/components/[slug]"));
4326
+ await ensureDir(path16.join(appDir, "src/lib"));
4327
+ await ensureDir(path16.join(appDir, "public/brand"));
4862
4328
  await generatePackageJson2(config, appDir);
4863
4329
  await generateTsConfig2(appDir);
4864
4330
  await generateNextConfig2(appDir);
@@ -4911,7 +4377,7 @@ async function generatePackageJson2(config, appDir) {
4911
4377
  typescript: "^5.0.0"
4912
4378
  }
4913
4379
  };
4914
- await writeJSON(path17.join(appDir, "package.json"), packageJson2);
4380
+ await writeJSON(path16.join(appDir, "package.json"), packageJson2);
4915
4381
  }
4916
4382
  async function generateTsConfig2(appDir) {
4917
4383
  const tsConfig = {
@@ -4939,7 +4405,7 @@ async function generateTsConfig2(appDir) {
4939
4405
  include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
4940
4406
  exclude: ["node_modules"]
4941
4407
  };
4942
- await writeJSON(path17.join(appDir, "tsconfig.json"), tsConfig);
4408
+ await writeJSON(path16.join(appDir, "tsconfig.json"), tsConfig);
4943
4409
  }
4944
4410
  async function generateNextConfig2(appDir) {
4945
4411
  const content = `import type { NextConfig } from 'next'
@@ -4950,7 +4416,7 @@ const nextConfig: NextConfig = {
4950
4416
 
4951
4417
  export default nextConfig
4952
4418
  `;
4953
- await writeFile(path17.join(appDir, "next.config.ts"), content);
4419
+ await writeFile(path16.join(appDir, "next.config.ts"), content);
4954
4420
  }
4955
4421
  async function generatePostCssConfig2(appDir) {
4956
4422
  const content = `export default {
@@ -4959,7 +4425,7 @@ async function generatePostCssConfig2(appDir) {
4959
4425
  },
4960
4426
  }
4961
4427
  `;
4962
- await writeFile(path17.join(appDir, "postcss.config.mjs"), content);
4428
+ await writeFile(path16.join(appDir, "postcss.config.mjs"), content);
4963
4429
  }
4964
4430
  async function generateGlobalsCss2(config, appDir) {
4965
4431
  const { designSystem } = config;
@@ -5219,7 +4685,7 @@ h1, h2, h3, h4, h5, h6 {
5219
4685
  }
5220
4686
  }
5221
4687
  `;
5222
- await writeFile(path17.join(appDir, "src/app/globals.css"), content);
4688
+ await writeFile(path16.join(appDir, "src/app/globals.css"), content);
5223
4689
  }
5224
4690
  async function generateLayoutTsx(config, appDir) {
5225
4691
  const { designSystem } = config;
@@ -5418,7 +4884,7 @@ function ThemeToggle() {
5418
4884
  )
5419
4885
  }
5420
4886
  `;
5421
- await writeFile(path17.join(appDir, "src/app/layout.tsx"), content);
4887
+ await writeFile(path16.join(appDir, "src/app/layout.tsx"), content);
5422
4888
  }
5423
4889
  async function generateHomePage(config, appDir) {
5424
4890
  const content = `export default function DesignSystemHome() {
@@ -5584,7 +5050,7 @@ function Principle({
5584
5050
  )
5585
5051
  }
5586
5052
  `;
5587
- await writeFile(path17.join(appDir, "src/app/page.tsx"), content);
5053
+ await writeFile(path16.join(appDir, "src/app/page.tsx"), content);
5588
5054
  }
5589
5055
  async function generateColorsPage(config, appDir) {
5590
5056
  const content = `export default function ColorsPage() {
@@ -5753,7 +5219,7 @@ function ColorCard({
5753
5219
  )
5754
5220
  }
5755
5221
  `;
5756
- await writeFile(path17.join(appDir, "src/app/colors/page.tsx"), content);
5222
+ await writeFile(path16.join(appDir, "src/app/colors/page.tsx"), content);
5757
5223
  }
5758
5224
  async function generateTypographyPage(config, appDir) {
5759
5225
  const { designSystem } = config;
@@ -5910,7 +5376,7 @@ function WeightCard({ weight, name }: { weight: string; name: string }) {
5910
5376
  )
5911
5377
  }
5912
5378
  `;
5913
- await writeFile(path17.join(appDir, "src/app/typography/page.tsx"), content);
5379
+ await writeFile(path16.join(appDir, "src/app/typography/page.tsx"), content);
5914
5380
  }
5915
5381
  async function generateSpacingPage(config, appDir) {
5916
5382
  const { designSystem } = config;
@@ -6043,7 +5509,7 @@ function PatternCard({
6043
5509
  )
6044
5510
  }
6045
5511
  `;
6046
- await writeFile(path17.join(appDir, "src/app/spacing/page.tsx"), content);
5512
+ await writeFile(path16.join(appDir, "src/app/spacing/page.tsx"), content);
6047
5513
  }
6048
5514
  async function generateBrandPage(config, appDir) {
6049
5515
  const content = `export default function BrandPage() {
@@ -6181,7 +5647,7 @@ function DownloadCard({
6181
5647
  )
6182
5648
  }
6183
5649
  `;
6184
- await writeFile(path17.join(appDir, "src/app/brand/page.tsx"), content);
5650
+ await writeFile(path16.join(appDir, "src/app/brand/page.tsx"), content);
6185
5651
  }
6186
5652
  async function generateBlocksPage(appDir) {
6187
5653
  const content = `export default function BlocksPage() {
@@ -6243,7 +5709,7 @@ function BlockCard({ title, description }: { title: string; description: string
6243
5709
  )
6244
5710
  }
6245
5711
  `;
6246
- await writeFile(path17.join(appDir, "src/app/blocks/page.tsx"), content);
5712
+ await writeFile(path16.join(appDir, "src/app/blocks/page.tsx"), content);
6247
5713
  }
6248
5714
  async function generateComponentsPage(appDir) {
6249
5715
  const content = `export default function ComponentsPage() {
@@ -6323,7 +5789,7 @@ function CategoryCard({
6323
5789
  )
6324
5790
  }
6325
5791
  `;
6326
- await writeFile(path17.join(appDir, "src/app/components/page.tsx"), content);
5792
+ await writeFile(path16.join(appDir, "src/app/components/page.tsx"), content);
6327
5793
  }
6328
5794
  async function generateComponentSlugPage(appDir) {
6329
5795
  const content = `import { notFound } from 'next/navigation'
@@ -6427,7 +5893,7 @@ export function generateStaticParams() {
6427
5893
  return components.map((slug) => ({ slug }))
6428
5894
  }
6429
5895
  `;
6430
- await writeFile(path17.join(appDir, "src/app/components/[slug]/page.tsx"), content);
5896
+ await writeFile(path16.join(appDir, "src/app/components/[slug]/page.tsx"), content);
6431
5897
  }
6432
5898
  async function generateUtils(appDir) {
6433
5899
  const content = `import { clsx, type ClassValue } from 'clsx'
@@ -6437,7 +5903,7 @@ export function cn(...inputs: ClassValue[]) {
6437
5903
  return twMerge(clsx(inputs))
6438
5904
  }
6439
5905
  `;
6440
- await writeFile(path17.join(appDir, "src/lib/utils.ts"), content);
5906
+ await writeFile(path16.join(appDir, "src/lib/utils.ts"), content);
6441
5907
  }
6442
5908
 
6443
5909
  // src/setup/env-wizard.ts
@@ -6445,7 +5911,7 @@ import * as p6 from "@clack/prompts";
6445
5911
  import pc2 from "picocolors";
6446
5912
  import { exec } from "child_process";
6447
5913
  import { promisify } from "util";
6448
- import path18 from "path";
5914
+ import path17 from "path";
6449
5915
  var execAsync = promisify(exec);
6450
5916
  async function runEnvSetupWizard(config) {
6451
5917
  console.log();
@@ -6526,7 +5992,7 @@ This will open your browser to create a new project on Convex.
6526
5992
  ${pc2.dim("Note: Make sure you have a Convex account at https://convex.dev")}
6527
5993
  `);
6528
5994
  try {
6529
- const convexDir = config.structure === "monorepo" ? path18.join(config.targetDir, "packages/backend") : config.targetDir;
5995
+ const convexDir = config.structure === "monorepo" ? path17.join(config.targetDir, "packages/backend") : config.targetDir;
6530
5996
  const { spawn } = await import("child_process");
6531
5997
  p6.log.info(`Installing dependencies in ${pc2.dim(convexDir)}...`);
6532
5998
  const installSuccess = await new Promise((resolve) => {
@@ -6802,7 +6268,7 @@ async function writeEnvFiles(config, envValues) {
6802
6268
  return;
6803
6269
  }
6804
6270
  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");
6271
+ const webEnvPath = config.structure === "monorepo" ? path17.join(config.targetDir, "apps/web/.env.local") : path17.join(config.targetDir, ".env.local");
6806
6272
  if (await pathExists(webEnvPath)) {
6807
6273
  let content = await readFile(webEnvPath);
6808
6274
  for (const [key, value] of Object.entries(envValues)) {
@@ -6821,7 +6287,7 @@ ${key}="${value}"`;
6821
6287
  p6.log.success(`Updated ${config.structure === "monorepo" ? "apps/web/.env.local" : ".env.local"}`);
6822
6288
  }
6823
6289
  if (config.marketingSite === "payload" && config.structure === "monorepo") {
6824
- const marketingEnvPath = path18.join(config.targetDir, "apps/marketing/.env.local");
6290
+ const marketingEnvPath = path17.join(config.targetDir, "apps/marketing/.env.local");
6825
6291
  if (await pathExists(marketingEnvPath)) {
6826
6292
  let content = await readFile(marketingEnvPath);
6827
6293
  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 +6348,7 @@ async function generateSingleProject(config, spinner) {
6882
6348
  await generateShadcn(config, targetDir);
6883
6349
  spinner.succeed("shadcn/ui configured");
6884
6350
  spinner.start("Setting up Convex...");
6885
- await generateConvex(config, path19.join(targetDir, "convex"));
6351
+ await generateConvex(config, path18.join(targetDir, "convex"));
6886
6352
  spinner.succeed("Convex configured");
6887
6353
  spinner.start("Configuring Better-Auth...");
6888
6354
  await generateBetterAuth(config, targetDir);
@@ -6925,7 +6391,7 @@ async function generateMonorepoProject(config, spinner) {
6925
6391
  spinner.start("Creating shared UI package...");
6926
6392
  await generateUIPackage(config, targetDir);
6927
6393
  spinner.succeed("Shared UI package created");
6928
- const webDir = path19.join(targetDir, "apps/web");
6394
+ const webDir = path18.join(targetDir, "apps/web");
6929
6395
  spinner.start("Generating web application...");
6930
6396
  await generateBaseNextjs(config, webDir);
6931
6397
  await generateTailwind(config, webDir);
@@ -6935,10 +6401,10 @@ async function generateMonorepoProject(config, spinner) {
6935
6401
  await generateEmail(config, webDir);
6936
6402
  await updateWebTsConfig(webDir);
6937
6403
  spinner.succeed("Web application generated");
6938
- const backendDir = path19.join(targetDir, "packages/backend");
6404
+ const backendDir = path18.join(targetDir, "packages/backend");
6939
6405
  spinner.start("Setting up Convex backend...");
6940
6406
  await ensureDir(backendDir);
6941
- await generateConvex(config, path19.join(backendDir, "convex"));
6407
+ await generateConvex(config, path18.join(backendDir, "convex"));
6942
6408
  spinner.succeed("Convex backend configured");
6943
6409
  if (config.integrations.analytics !== "none") {
6944
6410
  spinner.start(`Setting up ${config.integrations.analytics} analytics...`);
@@ -6961,7 +6427,7 @@ async function generateMonorepoProject(config, spinner) {
6961
6427
  spinner.succeed(`${config.integrations.monitoring} monitoring configured`);
6962
6428
  }
6963
6429
  if (config.marketingSite !== "none") {
6964
- const marketingDir = path19.join(targetDir, "apps/marketing");
6430
+ const marketingDir = path18.join(targetDir, "apps/marketing");
6965
6431
  spinner.start(`Generating ${config.marketingSite} marketing site...`);
6966
6432
  if (config.marketingSite === "payload") {
6967
6433
  await generatePayload(config, marketingDir);
@@ -6970,12 +6436,6 @@ async function generateMonorepoProject(config, spinner) {
6970
6436
  }
6971
6437
  spinner.succeed(`${config.marketingSite} marketing site generated`);
6972
6438
  }
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
6439
  spinner.start("Generating design system app...");
6980
6440
  await generateDesignSystemApp(config, targetDir);
6981
6441
  spinner.succeed("Design system app generated");
@@ -6992,7 +6452,7 @@ async function runPostGenerationSteps(config, spinner) {
6992
6452
  }
6993
6453
  spinner.start("Installing shadcn/ui components...");
6994
6454
  try {
6995
- const shadcnDir = config.structure === "monorepo" ? path19.join(targetDir, "packages/ui") : targetDir;
6455
+ const shadcnDir = config.structure === "monorepo" ? path18.join(targetDir, "packages/ui") : targetDir;
6996
6456
  await runShadcnAdd(shadcnDir);
6997
6457
  spinner.succeed("shadcn/ui components installed");
6998
6458
  } catch (error) {
@@ -7052,7 +6512,7 @@ async function generateBiomeConfig(targetDir) {
7052
6512
  }
7053
6513
  };
7054
6514
  await writeFile(
7055
- path19.join(targetDir, "biome.json"),
6515
+ path18.join(targetDir, "biome.json"),
7056
6516
  JSON.stringify(biomeJson, null, 2)
7057
6517
  );
7058
6518
  }
@@ -7103,13 +6563,13 @@ yarn-error.log*
7103
6563
  *.pem
7104
6564
  .cache
7105
6565
  `;
7106
- await writeFile(path19.join(targetDir, ".gitignore"), gitignoreContent);
6566
+ await writeFile(path18.join(targetDir, ".gitignore"), gitignoreContent);
7107
6567
  }
7108
6568
  async function generateHuskyHooks(targetDir) {
7109
6569
  const preCommitContent = `pnpm lint-staged
7110
6570
  `;
7111
- await ensureDir(path19.join(targetDir, ".husky"));
7112
- await writeFile(path19.join(targetDir, ".husky/pre-commit"), preCommitContent);
6571
+ await ensureDir(path18.join(targetDir, ".husky"));
6572
+ await writeFile(path18.join(targetDir, ".husky/pre-commit"), preCommitContent);
7113
6573
  }
7114
6574
  async function updateWebTsConfig(webDir) {
7115
6575
  const tsConfig = {
@@ -7136,14 +6596,14 @@ async function updateWebTsConfig(webDir) {
7136
6596
  exclude: ["node_modules"]
7137
6597
  };
7138
6598
  await writeFile(
7139
- path19.join(webDir, "tsconfig.json"),
6599
+ path18.join(webDir, "tsconfig.json"),
7140
6600
  JSON.stringify(tsConfig, null, 2)
7141
6601
  );
7142
6602
  }
7143
6603
  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"));
6604
+ await ensureDir(path18.join(marketingDir, "src/app"));
6605
+ await ensureDir(path18.join(marketingDir, "src/components"));
6606
+ await ensureDir(path18.join(marketingDir, "public"));
7147
6607
  const packageJson2 = {
7148
6608
  name: "@repo/marketing",
7149
6609
  version: "0.1.0",
@@ -7174,7 +6634,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7174
6634
  }
7175
6635
  };
7176
6636
  await writeFile(
7177
- path19.join(marketingDir, "package.json"),
6637
+ path18.join(marketingDir, "package.json"),
7178
6638
  JSON.stringify(packageJson2, null, 2)
7179
6639
  );
7180
6640
  const homePageContent = `export default function HomePage() {
@@ -7197,7 +6657,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7197
6657
  }
7198
6658
  `;
7199
6659
  await writeFile(
7200
- path19.join(marketingDir, "src/app/page.tsx"),
6660
+ path18.join(marketingDir, "src/app/page.tsx"),
7201
6661
  homePageContent
7202
6662
  );
7203
6663
  const layoutContent = `import type { Metadata } from 'next'
@@ -7221,7 +6681,7 @@ export default function RootLayout({
7221
6681
  }
7222
6682
  `;
7223
6683
  await writeFile(
7224
- path19.join(marketingDir, "src/app/layout.tsx"),
6684
+ path18.join(marketingDir, "src/app/layout.tsx"),
7225
6685
  layoutContent
7226
6686
  );
7227
6687
  const globalsCss = `@import "tailwindcss";
@@ -7233,7 +6693,7 @@ export default function RootLayout({
7233
6693
  }
7234
6694
  `;
7235
6695
  await writeFile(
7236
- path19.join(marketingDir, "src/app/globals.css"),
6696
+ path18.join(marketingDir, "src/app/globals.css"),
7237
6697
  globalsCss
7238
6698
  );
7239
6699
  const tsConfig = {
@@ -7260,7 +6720,7 @@ export default function RootLayout({
7260
6720
  exclude: ["node_modules"]
7261
6721
  };
7262
6722
  await writeFile(
7263
- path19.join(marketingDir, "tsconfig.json"),
6723
+ path18.join(marketingDir, "tsconfig.json"),
7264
6724
  JSON.stringify(tsConfig, null, 2)
7265
6725
  );
7266
6726
  const nextConfig = `import type { NextConfig } from 'next'
@@ -7271,14 +6731,14 @@ const nextConfig: NextConfig = {
7271
6731
 
7272
6732
  export default nextConfig
7273
6733
  `;
7274
- await writeFile(path19.join(marketingDir, "next.config.ts"), nextConfig);
6734
+ await writeFile(path18.join(marketingDir, "next.config.ts"), nextConfig);
7275
6735
  const postcssConfig = `export default {
7276
6736
  plugins: {
7277
6737
  '@tailwindcss/postcss': {},
7278
6738
  },
7279
6739
  }
7280
6740
  `;
7281
- await writeFile(path19.join(marketingDir, "postcss.config.mjs"), postcssConfig);
6741
+ await writeFile(path18.join(marketingDir, "postcss.config.mjs"), postcssConfig);
7282
6742
  }
7283
6743
  function displaySuccessMessage(config) {
7284
6744
  const apps = ["web"];
@@ -7286,9 +6746,6 @@ function displaySuccessMessage(config) {
7286
6746
  if (config.marketingSite !== "none") {
7287
6747
  apps.push("marketing");
7288
6748
  }
7289
- if (config.includeDocs) {
7290
- apps.push("docs");
7291
- }
7292
6749
  apps.push("design-system");
7293
6750
  }
7294
6751
  console.log();
@@ -7321,9 +6778,6 @@ function displaySuccessMessage(config) {
7321
6778
  if (config.marketingSite === "payload") {
7322
6779
  console.log(` ${pc3.dim("-")} Payload CMS: ${pc3.cyan("https://payloadcms.com/docs")}`);
7323
6780
  }
7324
- if (config.includeDocs) {
7325
- console.log(` ${pc3.dim("-")} Fumadocs: ${pc3.cyan("https://fumadocs.vercel.app")}`);
7326
- }
7327
6781
  console.log();
7328
6782
  }
7329
6783
 
@@ -7351,7 +6805,7 @@ program.name("create-kofi-stack").description(
7351
6805
  ).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
6806
  "--marketing <type>",
7353
6807
  "Marketing site type: payload, nextjs, none"
7354
- ).option("--docs", "Include documentation site (Fumadocs)").option("--no-docs", "Exclude documentation site").option(
6808
+ ).option(
7355
6809
  "--component-library <library>",
7356
6810
  "Component library: base (Base UI), radix (Radix UI)"
7357
6811
  ).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.19",
4
4
  "description": "Scaffold opinionated full-stack projects with Next.js, Convex, Better-Auth, and more",
5
5
  "type": "module",
6
6
  "bin": {