create-kofi-stack 1.2.3 → 1.2.4

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 -597
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -66,11 +66,6 @@ async function promptMarketingSite(defaultValue) {
66
66
  label: "Next.js",
67
67
  hint: "Simple static/SSG site"
68
68
  },
69
- {
70
- value: "astro",
71
- label: "Astro",
72
- hint: "Lightweight, content-focused"
73
- },
74
69
  {
75
70
  value: "none",
76
71
  label: "None",
@@ -713,7 +708,7 @@ ${extras.length > 0 ? `${pc.bold("Extras:")} ${extras.join(", ")}` : ""}`,
713
708
  }
714
709
 
715
710
  // src/generators/index.ts
716
- import path20 from "path";
711
+ import path19 from "path";
717
712
  import * as p7 from "@clack/prompts";
718
713
  import pc3 from "picocolors";
719
714
  import ora from "ora";
@@ -811,11 +806,11 @@ async function generatePackageJson(config, appDir) {
811
806
  next: "^16.0.0",
812
807
  react: "^19.0.0",
813
808
  "react-dom": "^19.0.0",
814
- "@convex-dev/better-auth": "^0.10.9",
815
- "better-auth": "^1.4.0",
809
+ "@convex-dev/better-auth": "^0.10.10",
810
+ "better-auth": "1.4.9",
816
811
  convex: "^1.25.0",
817
- "@t3-oss/env-nextjs": "^0.11.0",
818
- zod: "^3.25.0",
812
+ "@t3-oss/env-nextjs": "^0.13.0",
813
+ zod: "^4.0.0",
819
814
  "date-fns": "^4.0.0",
820
815
  clsx: "^2.1.0",
821
816
  "tailwind-merge": "^2.5.0",
@@ -1996,7 +1991,7 @@ async function generateConvexPackageJson(convexDir) {
1996
1991
  types: "./convex/index.ts",
1997
1992
  dependencies: {
1998
1993
  convex: "^1.25.0",
1999
- "@convex-dev/better-auth": "^0.10.9"
1994
+ "@convex-dev/better-auth": "^0.10.10"
2000
1995
  },
2001
1996
  devDependencies: {
2002
1997
  typescript: "^5.0.0"
@@ -3257,10 +3252,10 @@ async function generatePayloadPackageJson(marketingDir) {
3257
3252
  "db:seed": "tsx src/seed.ts"
3258
3253
  },
3259
3254
  dependencies: {
3260
- next: "^16.0.0",
3255
+ next: "^15.4.10",
3261
3256
  react: "^19.0.0",
3262
3257
  "react-dom": "^19.0.0",
3263
- payload: "^3.0.0",
3258
+ payload: "^3.70.0",
3264
3259
  "@payloadcms/db-postgres": "^3.0.0",
3265
3260
  "@payloadcms/next": "^3.0.0",
3266
3261
  "@payloadcms/richtext-lexical": "^3.0.0",
@@ -4643,539 +4638,8 @@ See the [Convex documentation](https://docs.convex.dev) for database API referen
4643
4638
  );
4644
4639
  }
4645
4640
 
4646
- // src/generators/astro.ts
4647
- import path17 from "path";
4648
- async function generateAstro(config, marketingDir) {
4649
- await ensureDir(path17.join(marketingDir, "src/components"));
4650
- await ensureDir(path17.join(marketingDir, "src/layouts"));
4651
- await ensureDir(path17.join(marketingDir, "src/pages"));
4652
- await ensureDir(path17.join(marketingDir, "src/content/blog"));
4653
- await ensureDir(path17.join(marketingDir, "src/styles"));
4654
- await ensureDir(path17.join(marketingDir, "public"));
4655
- await generateAstroPackageJson(marketingDir);
4656
- await generateAstroConfig(marketingDir);
4657
- await generateAstroTsConfig(marketingDir);
4658
- await generateAstroLayouts(config, marketingDir);
4659
- await generateAstroPages(config, marketingDir);
4660
- await generateAstroComponents(config, marketingDir);
4661
- await generateAstroStyles(marketingDir);
4662
- await generateAstroContent(config, marketingDir);
4663
- }
4664
- async function generateAstroPackageJson(marketingDir) {
4665
- const packageJson = {
4666
- name: "@repo/marketing",
4667
- version: "0.1.0",
4668
- private: true,
4669
- type: "module",
4670
- scripts: {
4671
- dev: "astro dev --port 3001",
4672
- build: "astro build",
4673
- preview: "astro preview",
4674
- lint: "biome check .",
4675
- "lint:fix": "biome check --write .",
4676
- typecheck: "astro check && tsc --noEmit"
4677
- },
4678
- dependencies: {
4679
- astro: "^5.0.0",
4680
- "@astrojs/mdx": "^4.0.0",
4681
- "@astrojs/sitemap": "^3.0.0",
4682
- "@astrojs/tailwind": "^6.0.0",
4683
- "@astrojs/react": "^4.0.0",
4684
- react: "^19.0.0",
4685
- "react-dom": "^19.0.0"
4686
- },
4687
- devDependencies: {
4688
- "@repo/config-typescript": "workspace:*",
4689
- "@types/react": "^19.0.0",
4690
- "@types/react-dom": "^19.0.0",
4691
- tailwindcss: "^4.0.0",
4692
- typescript: "^5.0.0"
4693
- }
4694
- };
4695
- await writeJSON(path17.join(marketingDir, "package.json"), packageJson);
4696
- }
4697
- async function generateAstroConfig(marketingDir) {
4698
- const content = `import { defineConfig } from 'astro/config'
4699
- import mdx from '@astrojs/mdx'
4700
- import sitemap from '@astrojs/sitemap'
4701
- import tailwind from '@astrojs/tailwind'
4702
- import react from '@astrojs/react'
4703
-
4704
- export default defineConfig({
4705
- site: 'https://example.com',
4706
- integrations: [
4707
- mdx(),
4708
- sitemap(),
4709
- tailwind(),
4710
- react(),
4711
- ],
4712
- markdown: {
4713
- shikiConfig: {
4714
- theme: 'github-dark',
4715
- wrap: true,
4716
- },
4717
- },
4718
- })
4719
- `;
4720
- await writeFile(path17.join(marketingDir, "astro.config.mjs"), content);
4721
- }
4722
- async function generateAstroTsConfig(marketingDir) {
4723
- const tsConfig = {
4724
- extends: "astro/tsconfigs/strict",
4725
- compilerOptions: {
4726
- jsx: "react-jsx",
4727
- jsxImportSource: "react",
4728
- paths: {
4729
- "@/*": ["./src/*"]
4730
- }
4731
- }
4732
- };
4733
- await writeJSON(path17.join(marketingDir, "tsconfig.json"), tsConfig);
4734
- }
4735
- async function generateAstroLayouts(config, marketingDir) {
4736
- const baseLayoutContent = `---
4737
- interface Props {
4738
- title: string
4739
- description?: string
4740
- }
4741
-
4742
- const { title, description = '${config.name} - Built with create-kofi-stack' } = Astro.props
4743
- ---
4744
-
4745
- <!doctype html>
4746
- <html lang="en">
4747
- <head>
4748
- <meta charset="UTF-8" />
4749
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
4750
- <meta name="description" content={description} />
4751
- <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
4752
- <title>{title}</title>
4753
- </head>
4754
- <body class="min-h-screen bg-background text-foreground">
4755
- <slot />
4756
- </body>
4757
- </html>
4758
-
4759
- <style is:global>
4760
- @import '../styles/global.css';
4761
- </style>
4762
- `;
4763
- await writeFile(
4764
- path17.join(marketingDir, "src/layouts/BaseLayout.astro"),
4765
- baseLayoutContent
4766
- );
4767
- const blogLayoutContent = `---
4768
- import BaseLayout from './BaseLayout.astro'
4769
- import { format } from 'date-fns'
4770
-
4771
- interface Props {
4772
- frontmatter: {
4773
- title: string
4774
- description: string
4775
- pubDate: Date
4776
- author?: string
4777
- }
4778
- }
4779
-
4780
- const { frontmatter } = Astro.props
4781
- ---
4782
-
4783
- <BaseLayout title={frontmatter.title} description={frontmatter.description}>
4784
- <article class="container mx-auto px-4 py-16 max-w-3xl">
4785
- <header class="mb-8">
4786
- <h1 class="text-4xl font-bold mb-4">{frontmatter.title}</h1>
4787
- <div class="text-muted-foreground">
4788
- <time datetime={frontmatter.pubDate.toISOString()}>
4789
- {format(frontmatter.pubDate, 'MMMM d, yyyy')}
4790
- </time>
4791
- {frontmatter.author && <span> \xB7 {frontmatter.author}</span>}
4792
- </div>
4793
- </header>
4794
- <div class="prose prose-lg dark:prose-invert max-w-none">
4795
- <slot />
4796
- </div>
4797
- </article>
4798
- </BaseLayout>
4799
- `;
4800
- await writeFile(
4801
- path17.join(marketingDir, "src/layouts/BlogLayout.astro"),
4802
- blogLayoutContent
4803
- );
4804
- }
4805
- async function generateAstroPages(config, marketingDir) {
4806
- const homePageContent = `---
4807
- import BaseLayout from '../layouts/BaseLayout.astro'
4808
- import Hero from '../components/Hero.astro'
4809
- import Features from '../components/Features.astro'
4810
- import CTA from '../components/CTA.astro'
4811
- ---
4812
-
4813
- <BaseLayout title="${config.name} - Home">
4814
- <main>
4815
- <Hero />
4816
- <Features />
4817
- <CTA />
4818
- </main>
4819
- </BaseLayout>
4820
- `;
4821
- await writeFile(
4822
- path17.join(marketingDir, "src/pages/index.astro"),
4823
- homePageContent
4824
- );
4825
- const blogIndexContent = `---
4826
- import BaseLayout from '../layouts/BaseLayout.astro'
4827
- import { getCollection } from 'astro:content'
4828
- import { format } from 'date-fns'
4829
-
4830
- const posts = (await getCollection('blog')).sort(
4831
- (a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
4832
- )
4833
- ---
4834
-
4835
- <BaseLayout title="Blog - ${config.name}">
4836
- <main class="container mx-auto px-4 py-16">
4837
- <h1 class="text-4xl font-bold mb-8">Blog</h1>
4838
- <div class="grid gap-8">
4839
- {
4840
- posts.map((post) => (
4841
- <article class="border rounded-lg p-6 hover:shadow-md transition-shadow">
4842
- <a href={\`/blog/\${post.slug}\`}>
4843
- <h2 class="text-2xl font-semibold mb-2">{post.data.title}</h2>
4844
- <p class="text-muted-foreground mb-4">{post.data.description}</p>
4845
- <time class="text-sm text-muted-foreground">
4846
- {format(post.data.pubDate, 'MMMM d, yyyy')}
4847
- </time>
4848
- </a>
4849
- </article>
4850
- ))
4851
- }
4852
- </div>
4853
- </main>
4854
- </BaseLayout>
4855
- `;
4856
- await writeFile(
4857
- path17.join(marketingDir, "src/pages/blog/index.astro"),
4858
- blogIndexContent
4859
- );
4860
- await ensureDir(path17.join(marketingDir, "src/pages/blog"));
4861
- const blogPostContent = `---
4862
- import { getCollection } from 'astro:content'
4863
- import BlogLayout from '../../layouts/BlogLayout.astro'
4864
-
4865
- export async function getStaticPaths() {
4866
- const posts = await getCollection('blog')
4867
- return posts.map((post) => ({
4868
- params: { slug: post.slug },
4869
- props: post,
4870
- }))
4871
- }
4872
-
4873
- const post = Astro.props
4874
- const { Content } = await post.render()
4875
- ---
4876
-
4877
- <BlogLayout frontmatter={post.data}>
4878
- <Content />
4879
- </BlogLayout>
4880
- `;
4881
- await writeFile(
4882
- path17.join(marketingDir, "src/pages/blog/[slug].astro"),
4883
- blogPostContent
4884
- );
4885
- const notFoundContent = `---
4886
- import BaseLayout from '../layouts/BaseLayout.astro'
4887
- ---
4888
-
4889
- <BaseLayout title="404 - Page Not Found">
4890
- <main class="container mx-auto px-4 py-16 text-center">
4891
- <h1 class="text-6xl font-bold mb-4">404</h1>
4892
- <p class="text-xl text-muted-foreground mb-8">Page not found</p>
4893
- <a href="/" class="inline-block px-6 py-3 bg-primary text-primary-foreground rounded-lg">
4894
- Go Home
4895
- </a>
4896
- </main>
4897
- </BaseLayout>
4898
- `;
4899
- await writeFile(
4900
- path17.join(marketingDir, "src/pages/404.astro"),
4901
- notFoundContent
4902
- );
4903
- }
4904
- async function generateAstroComponents(config, marketingDir) {
4905
- const heroContent = `---
4906
-
4907
- ---
4908
-
4909
- <section class="py-20 lg:py-32">
4910
- <div class="container mx-auto px-4 text-center">
4911
- <h1 class="text-5xl lg:text-7xl font-bold mb-6">
4912
- Welcome to <span class="text-primary">${config.name}</span>
4913
- </h1>
4914
- <p class="text-xl lg:text-2xl text-muted-foreground mb-8 max-w-2xl mx-auto">
4915
- Build your next SaaS application with our modern, full-stack starter template.
4916
- </p>
4917
- <div class="flex flex-col sm:flex-row gap-4 justify-center">
4918
- <a
4919
- href="/docs"
4920
- class="px-8 py-3 bg-primary text-primary-foreground rounded-lg font-semibold hover:opacity-90 transition-opacity"
4921
- >
4922
- Get Started
4923
- </a>
4924
- <a
4925
- href="https://github.com"
4926
- class="px-8 py-3 border rounded-lg font-semibold hover:bg-accent transition-colors"
4927
- >
4928
- View on GitHub
4929
- </a>
4930
- </div>
4931
- </div>
4932
- </section>
4933
- `;
4934
- await writeFile(
4935
- path17.join(marketingDir, "src/components/Hero.astro"),
4936
- heroContent
4937
- );
4938
- const featuresContent = `---
4939
- const features = [
4940
- {
4941
- title: 'Next.js 15',
4942
- description: 'Built on the latest Next.js with App Router and React 19.',
4943
- },
4944
- {
4945
- title: 'Convex Database',
4946
- description: 'Real-time database with automatic syncing and TypeScript support.',
4947
- },
4948
- {
4949
- title: 'Better-Auth',
4950
- description: 'Flexible authentication with email, OAuth, and more.',
4951
- },
4952
- {
4953
- title: 'shadcn/ui',
4954
- description: 'Beautiful, accessible components built with Radix UI and Tailwind.',
4955
- },
4956
- {
4957
- title: 'Tailwind CSS v4',
4958
- description: 'CSS-first configuration with modern theming capabilities.',
4959
- },
4960
- {
4961
- title: 'TypeScript',
4962
- description: 'Full type safety from database to frontend.',
4963
- },
4964
- ]
4965
- ---
4966
-
4967
- <section class="py-20 bg-muted/50">
4968
- <div class="container mx-auto px-4">
4969
- <h2 class="text-3xl lg:text-4xl font-bold text-center mb-12">Features</h2>
4970
- <div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
4971
- {
4972
- features.map((feature) => (
4973
- <div class="p-6 bg-background rounded-lg border">
4974
- <h3 class="text-xl font-semibold mb-2">{feature.title}</h3>
4975
- <p class="text-muted-foreground">{feature.description}</p>
4976
- </div>
4977
- ))
4978
- }
4979
- </div>
4980
- </div>
4981
- </section>
4982
- `;
4983
- await writeFile(
4984
- path17.join(marketingDir, "src/components/Features.astro"),
4985
- featuresContent
4986
- );
4987
- const ctaContent = `---
4988
-
4989
- ---
4990
-
4991
- <section class="py-20">
4992
- <div class="container mx-auto px-4 text-center">
4993
- <h2 class="text-3xl lg:text-4xl font-bold mb-4">Ready to get started?</h2>
4994
- <p class="text-xl text-muted-foreground mb-8 max-w-xl mx-auto">
4995
- Start building your SaaS application today with our fully-featured starter template.
4996
- </p>
4997
- <a
4998
- href="https://app.example.com"
4999
- class="inline-block px-8 py-3 bg-primary text-primary-foreground rounded-lg font-semibold hover:opacity-90 transition-opacity"
5000
- >
5001
- Launch App
5002
- </a>
5003
- </div>
5004
- </section>
5005
- `;
5006
- await writeFile(
5007
- path17.join(marketingDir, "src/components/CTA.astro"),
5008
- ctaContent
5009
- );
5010
- const headerContent = `---
5011
- const navItems = [
5012
- { label: 'Features', href: '/#features' },
5013
- { label: 'Blog', href: '/blog' },
5014
- { label: 'Docs', href: '/docs' },
5015
- ]
5016
- ---
5017
-
5018
- <header class="sticky top-0 z-50 bg-background/80 backdrop-blur border-b">
5019
- <div class="container mx-auto px-4">
5020
- <nav class="flex items-center justify-between h-16">
5021
- <a href="/" class="text-xl font-bold">${config.name}</a>
5022
- <div class="hidden md:flex items-center gap-6">
5023
- {
5024
- navItems.map((item) => (
5025
- <a href={item.href} class="text-muted-foreground hover:text-foreground transition-colors">
5026
- {item.label}
5027
- </a>
5028
- ))
5029
- }
5030
- <a
5031
- href="https://app.example.com"
5032
- class="px-4 py-2 bg-primary text-primary-foreground rounded-lg font-medium"
5033
- >
5034
- Launch App
5035
- </a>
5036
- </div>
5037
- </nav>
5038
- </div>
5039
- </header>
5040
- `;
5041
- await writeFile(
5042
- path17.join(marketingDir, "src/components/Header.astro"),
5043
- headerContent
5044
- );
5045
- const footerContent = `---
5046
- const currentYear = new Date().getFullYear()
5047
- ---
5048
-
5049
- <footer class="py-12 border-t">
5050
- <div class="container mx-auto px-4">
5051
- <div class="flex flex-col md:flex-row justify-between items-center gap-4">
5052
- <p class="text-muted-foreground">
5053
- &copy; {currentYear} ${config.name}. All rights reserved.
5054
- </p>
5055
- <div class="flex gap-6">
5056
- <a href="/privacy" class="text-muted-foreground hover:text-foreground transition-colors">
5057
- Privacy
5058
- </a>
5059
- <a href="/terms" class="text-muted-foreground hover:text-foreground transition-colors">
5060
- Terms
5061
- </a>
5062
- </div>
5063
- </div>
5064
- </div>
5065
- </footer>
5066
- `;
5067
- await writeFile(
5068
- path17.join(marketingDir, "src/components/Footer.astro"),
5069
- footerContent
5070
- );
5071
- }
5072
- async function generateAstroStyles(marketingDir) {
5073
- const globalStyles = `@import "tailwindcss";
5074
-
5075
- :root {
5076
- --background: 0 0% 100%;
5077
- --foreground: 0 0% 3.9%;
5078
- --muted: 0 0% 96.1%;
5079
- --muted-foreground: 0 0% 45.1%;
5080
- --primary: 0 0% 9%;
5081
- --primary-foreground: 0 0% 98%;
5082
- --accent: 0 0% 96.1%;
5083
- --accent-foreground: 0 0% 9%;
5084
- --border: 0 0% 89.8%;
5085
- }
5086
-
5087
- .dark {
5088
- --background: 0 0% 3.9%;
5089
- --foreground: 0 0% 98%;
5090
- --muted: 0 0% 14.9%;
5091
- --muted-foreground: 0 0% 63.9%;
5092
- --primary: 0 0% 98%;
5093
- --primary-foreground: 0 0% 9%;
5094
- --accent: 0 0% 14.9%;
5095
- --accent-foreground: 0 0% 98%;
5096
- --border: 0 0% 14.9%;
5097
- }
5098
-
5099
- @theme {
5100
- --color-background: hsl(var(--background));
5101
- --color-foreground: hsl(var(--foreground));
5102
- --color-muted: hsl(var(--muted));
5103
- --color-muted-foreground: hsl(var(--muted-foreground));
5104
- --color-primary: hsl(var(--primary));
5105
- --color-primary-foreground: hsl(var(--primary-foreground));
5106
- --color-accent: hsl(var(--accent));
5107
- --color-accent-foreground: hsl(var(--accent-foreground));
5108
- --color-border: hsl(var(--border));
5109
- }
5110
-
5111
- @layer base {
5112
- body {
5113
- @apply bg-background text-foreground;
5114
- }
5115
- }
5116
- `;
5117
- await writeFile(
5118
- path17.join(marketingDir, "src/styles/global.css"),
5119
- globalStyles
5120
- );
5121
- }
5122
- async function generateAstroContent(config, marketingDir) {
5123
- const contentConfigContent = `import { defineCollection, z } from 'astro:content'
5124
-
5125
- const blog = defineCollection({
5126
- type: 'content',
5127
- schema: z.object({
5128
- title: z.string(),
5129
- description: z.string(),
5130
- pubDate: z.coerce.date(),
5131
- updatedDate: z.coerce.date().optional(),
5132
- author: z.string().optional(),
5133
- heroImage: z.string().optional(),
5134
- }),
5135
- })
5136
-
5137
- export const collections = { blog }
5138
- `;
5139
- await writeFile(
5140
- path17.join(marketingDir, "src/content/config.ts"),
5141
- contentConfigContent
5142
- );
5143
- const samplePostContent = `---
5144
- title: 'Welcome to ${config.name}'
5145
- description: 'Learn about the features and capabilities of ${config.name}.'
5146
- pubDate: '${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}'
5147
- author: 'The Team'
5148
- ---
5149
-
5150
- # Welcome to ${config.name}
5151
-
5152
- This is a sample blog post to help you get started with your marketing site.
5153
-
5154
- ## Features
5155
-
5156
- Our platform includes:
5157
-
5158
- - **Modern Stack**: Built with Next.js 15 and React 19
5159
- - **Real-time Database**: Powered by Convex
5160
- - **Authentication**: Secure auth with Better-Auth
5161
- - **Beautiful UI**: Components from shadcn/ui
5162
-
5163
- ## Getting Started
5164
-
5165
- To get started, check out our [documentation](/docs) or [launch the app](https://app.example.com).
5166
-
5167
- ## Stay Updated
5168
-
5169
- Follow our blog for updates on new features and best practices.
5170
- `;
5171
- await writeFile(
5172
- path17.join(marketingDir, "src/content/blog/welcome.md"),
5173
- samplePostContent
5174
- );
5175
- }
5176
-
5177
4641
  // src/generators/design-system.ts
5178
- import path18 from "path";
4642
+ import path17 from "path";
5179
4643
  var fontImports = {
5180
4644
  inter: {
5181
4645
  import: "import { Inter } from 'next/font/google'",
@@ -5243,16 +4707,16 @@ var spacingMultipliers = {
5243
4707
  relaxed: 1.125
5244
4708
  };
5245
4709
  async function generateDesignSystemApp(config, targetDir) {
5246
- const appDir = path18.join(targetDir, "apps/design-system");
5247
- await ensureDir(path18.join(appDir, "src/app"));
5248
- await ensureDir(path18.join(appDir, "src/app/colors"));
5249
- await ensureDir(path18.join(appDir, "src/app/typography"));
5250
- await ensureDir(path18.join(appDir, "src/app/spacing"));
5251
- await ensureDir(path18.join(appDir, "src/app/brand"));
5252
- await ensureDir(path18.join(appDir, "src/app/blocks"));
5253
- await ensureDir(path18.join(appDir, "src/app/components"));
5254
- await ensureDir(path18.join(appDir, "src/lib"));
5255
- await ensureDir(path18.join(appDir, "public/brand"));
4710
+ const appDir = path17.join(targetDir, "apps/design-system");
4711
+ await ensureDir(path17.join(appDir, "src/app"));
4712
+ await ensureDir(path17.join(appDir, "src/app/colors"));
4713
+ await ensureDir(path17.join(appDir, "src/app/typography"));
4714
+ await ensureDir(path17.join(appDir, "src/app/spacing"));
4715
+ await ensureDir(path17.join(appDir, "src/app/brand"));
4716
+ await ensureDir(path17.join(appDir, "src/app/blocks"));
4717
+ await ensureDir(path17.join(appDir, "src/app/components"));
4718
+ await ensureDir(path17.join(appDir, "src/lib"));
4719
+ await ensureDir(path17.join(appDir, "public/brand"));
5256
4720
  await generatePackageJson2(config, appDir);
5257
4721
  await generateTsConfig2(appDir);
5258
4722
  await generateNextConfig2(appDir);
@@ -5304,7 +4768,7 @@ async function generatePackageJson2(config, appDir) {
5304
4768
  typescript: "^5.0.0"
5305
4769
  }
5306
4770
  };
5307
- await writeJSON(path18.join(appDir, "package.json"), packageJson);
4771
+ await writeJSON(path17.join(appDir, "package.json"), packageJson);
5308
4772
  }
5309
4773
  async function generateTsConfig2(appDir) {
5310
4774
  const tsConfig = {
@@ -5320,7 +4784,7 @@ async function generateTsConfig2(appDir) {
5320
4784
  include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
5321
4785
  exclude: ["node_modules"]
5322
4786
  };
5323
- await writeJSON(path18.join(appDir, "tsconfig.json"), tsConfig);
4787
+ await writeJSON(path17.join(appDir, "tsconfig.json"), tsConfig);
5324
4788
  }
5325
4789
  async function generateNextConfig2(appDir) {
5326
4790
  const content = `import type { NextConfig } from 'next'
@@ -5331,7 +4795,7 @@ const nextConfig: NextConfig = {
5331
4795
 
5332
4796
  export default nextConfig
5333
4797
  `;
5334
- await writeFile(path18.join(appDir, "next.config.ts"), content);
4798
+ await writeFile(path17.join(appDir, "next.config.ts"), content);
5335
4799
  }
5336
4800
  async function generatePostCssConfig2(appDir) {
5337
4801
  const content = `export default {
@@ -5340,7 +4804,7 @@ async function generatePostCssConfig2(appDir) {
5340
4804
  },
5341
4805
  }
5342
4806
  `;
5343
- await writeFile(path18.join(appDir, "postcss.config.mjs"), content);
4807
+ await writeFile(path17.join(appDir, "postcss.config.mjs"), content);
5344
4808
  }
5345
4809
  async function generateGlobalsCss2(config, appDir) {
5346
4810
  const { designSystem } = config;
@@ -5600,7 +5064,7 @@ h1, h2, h3, h4, h5, h6 {
5600
5064
  }
5601
5065
  }
5602
5066
  `;
5603
- await writeFile(path18.join(appDir, "src/app/globals.css"), content);
5067
+ await writeFile(path17.join(appDir, "src/app/globals.css"), content);
5604
5068
  }
5605
5069
  async function generateLayoutTsx(config, appDir) {
5606
5070
  const { designSystem } = config;
@@ -5799,7 +5263,7 @@ function ThemeToggle() {
5799
5263
  )
5800
5264
  }
5801
5265
  `;
5802
- await writeFile(path18.join(appDir, "src/app/layout.tsx"), content);
5266
+ await writeFile(path17.join(appDir, "src/app/layout.tsx"), content);
5803
5267
  }
5804
5268
  async function generateHomePage(config, appDir) {
5805
5269
  const content = `export default function DesignSystemHome() {
@@ -5965,7 +5429,7 @@ function Principle({
5965
5429
  )
5966
5430
  }
5967
5431
  `;
5968
- await writeFile(path18.join(appDir, "src/app/page.tsx"), content);
5432
+ await writeFile(path17.join(appDir, "src/app/page.tsx"), content);
5969
5433
  }
5970
5434
  async function generateColorsPage(config, appDir) {
5971
5435
  const content = `export default function ColorsPage() {
@@ -6134,7 +5598,7 @@ function ColorCard({
6134
5598
  )
6135
5599
  }
6136
5600
  `;
6137
- await writeFile(path18.join(appDir, "src/app/colors/page.tsx"), content);
5601
+ await writeFile(path17.join(appDir, "src/app/colors/page.tsx"), content);
6138
5602
  }
6139
5603
  async function generateTypographyPage(config, appDir) {
6140
5604
  const { designSystem } = config;
@@ -6291,7 +5755,7 @@ function WeightCard({ weight, name }: { weight: string; name: string }) {
6291
5755
  )
6292
5756
  }
6293
5757
  `;
6294
- await writeFile(path18.join(appDir, "src/app/typography/page.tsx"), content);
5758
+ await writeFile(path17.join(appDir, "src/app/typography/page.tsx"), content);
6295
5759
  }
6296
5760
  async function generateSpacingPage(config, appDir) {
6297
5761
  const { designSystem } = config;
@@ -6424,7 +5888,7 @@ function PatternCard({
6424
5888
  )
6425
5889
  }
6426
5890
  `;
6427
- await writeFile(path18.join(appDir, "src/app/spacing/page.tsx"), content);
5891
+ await writeFile(path17.join(appDir, "src/app/spacing/page.tsx"), content);
6428
5892
  }
6429
5893
  async function generateBrandPage(config, appDir) {
6430
5894
  const content = `export default function BrandPage() {
@@ -6562,7 +6026,7 @@ function DownloadCard({
6562
6026
  )
6563
6027
  }
6564
6028
  `;
6565
- await writeFile(path18.join(appDir, "src/app/brand/page.tsx"), content);
6029
+ await writeFile(path17.join(appDir, "src/app/brand/page.tsx"), content);
6566
6030
  }
6567
6031
  async function generateBlocksPage(appDir) {
6568
6032
  const content = `export default function BlocksPage() {
@@ -6624,7 +6088,7 @@ function BlockCard({ title, description }: { title: string; description: string
6624
6088
  )
6625
6089
  }
6626
6090
  `;
6627
- await writeFile(path18.join(appDir, "src/app/blocks/page.tsx"), content);
6091
+ await writeFile(path17.join(appDir, "src/app/blocks/page.tsx"), content);
6628
6092
  }
6629
6093
  async function generateComponentsPage(appDir) {
6630
6094
  const content = `export default function ComponentsPage() {
@@ -6704,7 +6168,7 @@ function CategoryCard({
6704
6168
  )
6705
6169
  }
6706
6170
  `;
6707
- await writeFile(path18.join(appDir, "src/app/components/page.tsx"), content);
6171
+ await writeFile(path17.join(appDir, "src/app/components/page.tsx"), content);
6708
6172
  }
6709
6173
  async function generateUtils(appDir) {
6710
6174
  const content = `import { clsx, type ClassValue } from 'clsx'
@@ -6714,7 +6178,7 @@ export function cn(...inputs: ClassValue[]) {
6714
6178
  return twMerge(clsx(inputs))
6715
6179
  }
6716
6180
  `;
6717
- await writeFile(path18.join(appDir, "src/lib/utils.ts"), content);
6181
+ await writeFile(path17.join(appDir, "src/lib/utils.ts"), content);
6718
6182
  }
6719
6183
 
6720
6184
  // src/setup/env-wizard.ts
@@ -6722,7 +6186,7 @@ import * as p6 from "@clack/prompts";
6722
6186
  import pc2 from "picocolors";
6723
6187
  import { exec } from "child_process";
6724
6188
  import { promisify } from "util";
6725
- import path19 from "path";
6189
+ import path18 from "path";
6726
6190
  var execAsync = promisify(exec);
6727
6191
  async function runEnvSetupWizard(config) {
6728
6192
  console.log();
@@ -7029,7 +6493,7 @@ async function writeEnvFiles(config, envValues) {
7029
6493
  return;
7030
6494
  }
7031
6495
  p6.log.step("Writing environment files...");
7032
- const webEnvPath = config.structure === "monorepo" ? path19.join(config.targetDir, "apps/web/.env.local") : path19.join(config.targetDir, ".env.local");
6496
+ const webEnvPath = config.structure === "monorepo" ? path18.join(config.targetDir, "apps/web/.env.local") : path18.join(config.targetDir, ".env.local");
7033
6497
  if (await pathExists(webEnvPath)) {
7034
6498
  let content = await readFile(webEnvPath);
7035
6499
  for (const [key, value] of Object.entries(envValues)) {
@@ -7048,7 +6512,7 @@ ${key}="${value}"`;
7048
6512
  p6.log.success(`Updated ${config.structure === "monorepo" ? "apps/web/.env.local" : ".env.local"}`);
7049
6513
  }
7050
6514
  if (config.marketingSite === "payload" && config.structure === "monorepo") {
7051
- const marketingEnvPath = path19.join(config.targetDir, "apps/marketing/.env.local");
6515
+ const marketingEnvPath = path18.join(config.targetDir, "apps/marketing/.env.local");
7052
6516
  if (await pathExists(marketingEnvPath)) {
7053
6517
  let content = await readFile(marketingEnvPath);
7054
6518
  const payloadEnvKeys = ["PAYLOAD_SECRET", "DATABASE_URL", "S3_ENDPOINT", "S3_REGION", "S3_BUCKET", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY", "CRON_SECRET", "PREVIEW_SECRET"];
@@ -7109,7 +6573,7 @@ async function generateSingleProject(config, spinner) {
7109
6573
  await generateShadcn(config, targetDir);
7110
6574
  spinner.succeed("shadcn/ui configured");
7111
6575
  spinner.start("Setting up Convex...");
7112
- await generateConvex(config, path20.join(targetDir, "convex"));
6576
+ await generateConvex(config, path19.join(targetDir, "convex"));
7113
6577
  spinner.succeed("Convex configured");
7114
6578
  spinner.start("Configuring Better-Auth...");
7115
6579
  await generateBetterAuth(config, targetDir);
@@ -7152,7 +6616,7 @@ async function generateMonorepoProject(config, spinner) {
7152
6616
  spinner.start("Creating shared UI package...");
7153
6617
  await generateUIPackage(config, targetDir);
7154
6618
  spinner.succeed("Shared UI package created");
7155
- const webDir = path20.join(targetDir, "apps/web");
6619
+ const webDir = path19.join(targetDir, "apps/web");
7156
6620
  spinner.start("Generating web application...");
7157
6621
  await generateBaseNextjs(config, webDir);
7158
6622
  await generateTailwind(config, webDir);
@@ -7162,10 +6626,10 @@ async function generateMonorepoProject(config, spinner) {
7162
6626
  await generateEmail(config, webDir);
7163
6627
  await updateWebTsConfig(webDir);
7164
6628
  spinner.succeed("Web application generated");
7165
- const backendDir = path20.join(targetDir, "packages/backend");
6629
+ const backendDir = path19.join(targetDir, "packages/backend");
7166
6630
  spinner.start("Setting up Convex backend...");
7167
6631
  await ensureDir(backendDir);
7168
- await generateConvex(config, path20.join(backendDir, "convex"));
6632
+ await generateConvex(config, path19.join(backendDir, "convex"));
7169
6633
  spinner.succeed("Convex backend configured");
7170
6634
  if (config.integrations.analytics !== "none") {
7171
6635
  spinner.start(`Setting up ${config.integrations.analytics} analytics...`);
@@ -7188,19 +6652,17 @@ async function generateMonorepoProject(config, spinner) {
7188
6652
  spinner.succeed(`${config.integrations.monitoring} monitoring configured`);
7189
6653
  }
7190
6654
  if (config.marketingSite !== "none") {
7191
- const marketingDir = path20.join(targetDir, "apps/marketing");
6655
+ const marketingDir = path19.join(targetDir, "apps/marketing");
7192
6656
  spinner.start(`Generating ${config.marketingSite} marketing site...`);
7193
6657
  if (config.marketingSite === "payload") {
7194
6658
  await generatePayload(config, marketingDir);
7195
- } else if (config.marketingSite === "astro") {
7196
- await generateAstro(config, marketingDir);
7197
6659
  } else if (config.marketingSite === "nextjs") {
7198
6660
  await generateNextjsMarketing(config, marketingDir);
7199
6661
  }
7200
6662
  spinner.succeed(`${config.marketingSite} marketing site generated`);
7201
6663
  }
7202
6664
  if (config.includeDocs) {
7203
- const docsDir = path20.join(targetDir, "apps/docs");
6665
+ const docsDir = path19.join(targetDir, "apps/docs");
7204
6666
  spinner.start("Generating Fumadocs documentation site...");
7205
6667
  await generateFumadocs(config, docsDir);
7206
6668
  spinner.succeed("Fumadocs documentation site generated");
@@ -7221,7 +6683,7 @@ async function runPostGenerationSteps(config, spinner) {
7221
6683
  }
7222
6684
  spinner.start("Installing shadcn/ui components...");
7223
6685
  try {
7224
- const shadcnDir = config.structure === "monorepo" ? path20.join(targetDir, "packages/ui") : targetDir;
6686
+ const shadcnDir = config.structure === "monorepo" ? path19.join(targetDir, "packages/ui") : targetDir;
7225
6687
  await runShadcnAdd(shadcnDir);
7226
6688
  spinner.succeed("shadcn/ui components installed");
7227
6689
  } catch (error) {
@@ -7281,7 +6743,7 @@ async function generateBiomeConfig(targetDir) {
7281
6743
  }
7282
6744
  };
7283
6745
  await writeFile(
7284
- path20.join(targetDir, "biome.json"),
6746
+ path19.join(targetDir, "biome.json"),
7285
6747
  JSON.stringify(biomeJson, null, 2)
7286
6748
  );
7287
6749
  }
@@ -7332,13 +6794,13 @@ yarn-error.log*
7332
6794
  *.pem
7333
6795
  .cache
7334
6796
  `;
7335
- await writeFile(path20.join(targetDir, ".gitignore"), gitignoreContent);
6797
+ await writeFile(path19.join(targetDir, ".gitignore"), gitignoreContent);
7336
6798
  }
7337
6799
  async function generateHuskyHooks(targetDir) {
7338
6800
  const preCommitContent = `pnpm lint-staged
7339
6801
  `;
7340
- await ensureDir(path20.join(targetDir, ".husky"));
7341
- await writeFile(path20.join(targetDir, ".husky/pre-commit"), preCommitContent);
6802
+ await ensureDir(path19.join(targetDir, ".husky"));
6803
+ await writeFile(path19.join(targetDir, ".husky/pre-commit"), preCommitContent);
7342
6804
  }
7343
6805
  async function updateWebTsConfig(webDir) {
7344
6806
  const tsConfig = {
@@ -7352,14 +6814,14 @@ async function updateWebTsConfig(webDir) {
7352
6814
  exclude: ["node_modules"]
7353
6815
  };
7354
6816
  await writeFile(
7355
- path20.join(webDir, "tsconfig.json"),
6817
+ path19.join(webDir, "tsconfig.json"),
7356
6818
  JSON.stringify(tsConfig, null, 2)
7357
6819
  );
7358
6820
  }
7359
6821
  async function generateNextjsMarketing(config, marketingDir) {
7360
- await ensureDir(path20.join(marketingDir, "src/app"));
7361
- await ensureDir(path20.join(marketingDir, "src/components"));
7362
- await ensureDir(path20.join(marketingDir, "public"));
6822
+ await ensureDir(path19.join(marketingDir, "src/app"));
6823
+ await ensureDir(path19.join(marketingDir, "src/components"));
6824
+ await ensureDir(path19.join(marketingDir, "public"));
7363
6825
  const packageJson = {
7364
6826
  name: "@repo/marketing",
7365
6827
  version: "0.1.0",
@@ -7390,7 +6852,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7390
6852
  }
7391
6853
  };
7392
6854
  await writeFile(
7393
- path20.join(marketingDir, "package.json"),
6855
+ path19.join(marketingDir, "package.json"),
7394
6856
  JSON.stringify(packageJson, null, 2)
7395
6857
  );
7396
6858
  const homePageContent = `export default function HomePage() {
@@ -7413,7 +6875,7 @@ async function generateNextjsMarketing(config, marketingDir) {
7413
6875
  }
7414
6876
  `;
7415
6877
  await writeFile(
7416
- path20.join(marketingDir, "src/app/page.tsx"),
6878
+ path19.join(marketingDir, "src/app/page.tsx"),
7417
6879
  homePageContent
7418
6880
  );
7419
6881
  const layoutContent = `import type { Metadata } from 'next'
@@ -7437,7 +6899,7 @@ export default function RootLayout({
7437
6899
  }
7438
6900
  `;
7439
6901
  await writeFile(
7440
- path20.join(marketingDir, "src/app/layout.tsx"),
6902
+ path19.join(marketingDir, "src/app/layout.tsx"),
7441
6903
  layoutContent
7442
6904
  );
7443
6905
  const globalsCss = `@import "tailwindcss";
@@ -7449,7 +6911,7 @@ export default function RootLayout({
7449
6911
  }
7450
6912
  `;
7451
6913
  await writeFile(
7452
- path20.join(marketingDir, "src/app/globals.css"),
6914
+ path19.join(marketingDir, "src/app/globals.css"),
7453
6915
  globalsCss
7454
6916
  );
7455
6917
  const tsConfig = {
@@ -7463,7 +6925,7 @@ export default function RootLayout({
7463
6925
  exclude: ["node_modules"]
7464
6926
  };
7465
6927
  await writeFile(
7466
- path20.join(marketingDir, "tsconfig.json"),
6928
+ path19.join(marketingDir, "tsconfig.json"),
7467
6929
  JSON.stringify(tsConfig, null, 2)
7468
6930
  );
7469
6931
  const nextConfig = `import type { NextConfig } from 'next'
@@ -7474,14 +6936,14 @@ const nextConfig: NextConfig = {
7474
6936
 
7475
6937
  export default nextConfig
7476
6938
  `;
7477
- await writeFile(path20.join(marketingDir, "next.config.ts"), nextConfig);
6939
+ await writeFile(path19.join(marketingDir, "next.config.ts"), nextConfig);
7478
6940
  const postcssConfig = `export default {
7479
6941
  plugins: {
7480
6942
  '@tailwindcss/postcss': {},
7481
6943
  },
7482
6944
  }
7483
6945
  `;
7484
- await writeFile(path20.join(marketingDir, "postcss.config.mjs"), postcssConfig);
6946
+ await writeFile(path19.join(marketingDir, "postcss.config.mjs"), postcssConfig);
7485
6947
  }
7486
6948
  function displaySuccessMessage(config) {
7487
6949
  const apps = ["web"];
@@ -7551,7 +7013,7 @@ program.name("create-kofi-stack").description(
7551
7013
  "Scaffold opinionated full-stack projects with Next.js, Convex, Better-Auth, and more"
7552
7014
  ).version("1.0.0").argument("[project-name]", "Name of the project").option("--monorepo", "Use monorepo structure with Turborepo").option("--single", "Use single app structure").option(
7553
7015
  "--marketing <type>",
7554
- "Marketing site type: payload, nextjs, astro, none"
7016
+ "Marketing site type: payload, nextjs, none"
7555
7017
  ).option("--docs", "Include documentation site (Fumadocs)").option("--no-docs", "Exclude documentation site").option(
7556
7018
  "--component-library <library>",
7557
7019
  "Component library: base (Base UI), radix (Radix UI)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kofi-stack",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Scaffold opinionated full-stack projects with Next.js, Convex, Better-Auth, and more",
5
5
  "type": "module",
6
6
  "bin": {