main b214fd809a42 cached
832 files
3.4 MB
958.3k tokens
1357 symbols
1 requests
Download .txt
Showing preview only (3,840K chars total). Download the full file or copy to clipboard to get everything.
Repository: better-t-stack/create-better-t-stack
Branch: main
Commit: b214fd809a42
Files: 832
Total size: 3.4 MB

Directory structure:
gitextract_1fybze6m/

├── .github/
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   └── workflows/
│       ├── pr-preview.yaml
│       ├── release.yaml
│       └── test.yaml
├── .gitignore
├── .oxfmtrc.json
├── AGENTS.md
├── LICENSE
├── README.md
├── apps/
│   ├── cli/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── bunfig.toml
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cli.ts
│   │   │   ├── commands/
│   │   │   │   ├── history.ts
│   │   │   │   └── meta.ts
│   │   │   ├── constants.ts
│   │   │   ├── helpers/
│   │   │   │   ├── addons/
│   │   │   │   │   ├── addons-setup.ts
│   │   │   │   │   ├── evlog-setup.ts
│   │   │   │   │   ├── fumadocs-setup.ts
│   │   │   │   │   ├── mcp-setup.ts
│   │   │   │   │   ├── oxlint-setup.ts
│   │   │   │   │   ├── skills-setup.ts
│   │   │   │   │   ├── starlight-setup.ts
│   │   │   │   │   ├── tauri-setup.ts
│   │   │   │   │   ├── tui-setup.ts
│   │   │   │   │   ├── ultracite-setup.ts
│   │   │   │   │   └── wxt-setup.ts
│   │   │   │   ├── core/
│   │   │   │   │   ├── add-handler.ts
│   │   │   │   │   ├── command-handlers.ts
│   │   │   │   │   ├── convex-codegen.ts
│   │   │   │   │   ├── create-project.ts
│   │   │   │   │   ├── db-setup-options.ts
│   │   │   │   │   ├── db-setup.ts
│   │   │   │   │   ├── detect-project-config.ts
│   │   │   │   │   ├── git.ts
│   │   │   │   │   ├── install-dependencies.ts
│   │   │   │   │   └── post-installation.ts
│   │   │   │   └── database-providers/
│   │   │   │       ├── d1-setup.ts
│   │   │   │       ├── docker-compose-setup.ts
│   │   │   │       ├── mongodb-atlas-setup.ts
│   │   │   │       ├── neon-setup.ts
│   │   │   │       ├── planetscale-setup.ts
│   │   │   │       ├── prisma-postgres-setup.ts
│   │   │   │       ├── supabase-setup.ts
│   │   │   │       └── turso-setup.ts
│   │   │   ├── index.ts
│   │   │   ├── mcp.ts
│   │   │   ├── prompts/
│   │   │   │   ├── addons.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── auth.ts
│   │   │   │   ├── backend.ts
│   │   │   │   ├── config-prompts.ts
│   │   │   │   ├── database-setup.ts
│   │   │   │   ├── database.ts
│   │   │   │   ├── examples.ts
│   │   │   │   ├── frontend.ts
│   │   │   │   ├── git.ts
│   │   │   │   ├── install.ts
│   │   │   │   ├── navigable-group.ts
│   │   │   │   ├── navigable.ts
│   │   │   │   ├── orm.ts
│   │   │   │   ├── package-manager.ts
│   │   │   │   ├── payments.ts
│   │   │   │   ├── project-name.ts
│   │   │   │   ├── runtime.ts
│   │   │   │   ├── server-deploy.ts
│   │   │   │   └── web-deploy.ts
│   │   │   ├── types.ts
│   │   │   ├── utils/
│   │   │   │   ├── add-package-deps.ts
│   │   │   │   ├── analytics.ts
│   │   │   │   ├── bts-config.ts
│   │   │   │   ├── command-exists.ts
│   │   │   │   ├── compatibility-rules.ts
│   │   │   │   ├── compatibility.ts
│   │   │   │   ├── config-processing.ts
│   │   │   │   ├── config-validation.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── display-config.ts
│   │   │   │   ├── docker-utils.ts
│   │   │   │   ├── env-utils.ts
│   │   │   │   ├── errors.ts
│   │   │   │   ├── external-commands.ts
│   │   │   │   ├── file-formatter.ts
│   │   │   │   ├── get-latest-cli-version.ts
│   │   │   │   ├── get-package-manager.ts
│   │   │   │   ├── input-hardening.ts
│   │   │   │   ├── navigation.ts
│   │   │   │   ├── open-url.ts
│   │   │   │   ├── package-runner.ts
│   │   │   │   ├── project-directory.ts
│   │   │   │   ├── project-history.ts
│   │   │   │   ├── project-name-validation.ts
│   │   │   │   ├── render-title.ts
│   │   │   │   ├── sponsors.ts
│   │   │   │   ├── telemetry.ts
│   │   │   │   ├── templates.ts
│   │   │   │   ├── terminal-output.ts
│   │   │   │   └── ts-morph.ts
│   │   │   ├── validation.ts
│   │   │   └── virtual.ts
│   │   ├── test/
│   │   │   ├── add-handler.test.ts
│   │   │   ├── addon-options.test.ts
│   │   │   ├── addon-setup-regressions.test.ts
│   │   │   ├── addons.test.ts
│   │   │   ├── api.test.ts
│   │   │   ├── auth.test.ts
│   │   │   ├── backend-runtime.test.ts
│   │   │   ├── basic-configurations.test.ts
│   │   │   ├── benchmark.test.ts
│   │   │   ├── clerk-matrix.test.ts
│   │   │   ├── cli-validation.test.ts
│   │   │   ├── cloudflare-db-clients.test.ts
│   │   │   ├── database-orm.test.ts
│   │   │   ├── database-setup.test.ts
│   │   │   ├── db-setup-mode-resolution.test.ts
│   │   │   ├── db-setup-options.test.ts
│   │   │   ├── deployment.test.ts
│   │   │   ├── dry-run.test.ts
│   │   │   ├── electrobun-addon.test.ts
│   │   │   ├── examples.test.ts
│   │   │   ├── external-commands.test.ts
│   │   │   ├── frontend.test.ts
│   │   │   ├── index.test.ts
│   │   │   ├── input-schemas.test.ts
│   │   │   ├── integration.test.ts
│   │   │   ├── mcp.test.ts
│   │   │   ├── project-name-validation.test.ts
│   │   │   ├── readme.test.ts
│   │   │   ├── schema-command.test.ts
│   │   │   ├── setup.ts
│   │   │   ├── silent-create-output.test.ts
│   │   │   ├── sponsors.test.ts
│   │   │   ├── tauri-setup.test.ts
│   │   │   ├── test-utils.ts
│   │   │   ├── tui-setup.test.ts
│   │   │   └── ultracite-setup.test.ts
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   └── web/
│       ├── .eslintrc.json
│       ├── .gitignore
│       ├── .vercelignore
│       ├── README.md
│       ├── cli.json
│       ├── components.json
│       ├── content/
│       │   └── docs/
│       │       ├── analytics.mdx
│       │       ├── bts-config.mdx
│       │       ├── cli/
│       │       │   ├── agent-workflows.mdx
│       │       │   ├── compatibility.mdx
│       │       │   ├── index.mdx
│       │       │   ├── meta.json
│       │       │   ├── options.mdx
│       │       │   ├── programmatic-api.mdx
│       │       │   └── prompts.mdx
│       │       ├── contributing.mdx
│       │       ├── faq.mdx
│       │       ├── guides/
│       │       │   ├── cloudflare-alchemy.mdx
│       │       │   ├── index.mdx
│       │       │   └── meta.json
│       │       ├── index.mdx
│       │       ├── meta.json
│       │       └── project-structure.mdx
│       ├── next.config.ts
│       ├── package.json
│       ├── postcss.config.mjs
│       ├── public/
│       │   ├── _headers
│       │   ├── favicon/
│       │   │   └── site.webmanifest
│       │   └── robots.txt
│       ├── scripts/
│       │   └── generate-schema.ts
│       ├── source.config.ts
│       ├── src/
│       │   ├── app/
│       │   │   ├── (home)/
│       │   │   │   ├── _components/
│       │   │   │   │   ├── FeatureCard.tsx
│       │   │   │   │   ├── code-container.tsx
│       │   │   │   │   ├── command-section.tsx
│       │   │   │   │   ├── footer.tsx
│       │   │   │   │   ├── hero-section.tsx
│       │   │   │   │   ├── icons.tsx
│       │   │   │   │   ├── npm-package.tsx
│       │   │   │   │   ├── shiny-text.tsx
│       │   │   │   │   ├── sponsors-section.tsx
│       │   │   │   │   ├── stats-section.tsx
│       │   │   │   │   └── testimonials.tsx
│       │   │   │   ├── analytics/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── analytics-header.tsx
│       │   │   │   │   │   ├── analytics-helpers.ts
│       │   │   │   │   │   ├── analytics-page.tsx
│       │   │   │   │   │   ├── analytics-sources.tsx
│       │   │   │   │   │   ├── chart-card.tsx
│       │   │   │   │   │   ├── dev-environment-charts.tsx
│       │   │   │   │   │   ├── evil-chart-utils.ts
│       │   │   │   │   │   ├── live-logs.tsx
│       │   │   │   │   │   ├── metrics-cards.tsx
│       │   │   │   │   │   ├── preference-chart-card.tsx
│       │   │   │   │   │   ├── section-header.tsx
│       │   │   │   │   │   ├── stack-configuration-charts.tsx
│       │   │   │   │   │   ├── timeline-charts.tsx
│       │   │   │   │   │   └── types.ts
│       │   │   │   │   ├── analytics-client.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── layout.tsx
│       │   │   │   ├── new/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── action-buttons.tsx
│       │   │   │   │   │   ├── code-viewer.tsx
│       │   │   │   │   │   ├── file-explorer.tsx
│       │   │   │   │   │   ├── get-badge-color.ts
│       │   │   │   │   │   ├── preset-dropdown.tsx
│       │   │   │   │   │   ├── preview-panel.tsx
│       │   │   │   │   │   ├── share-button.tsx
│       │   │   │   │   │   ├── special-sponsors-panel.tsx
│       │   │   │   │   │   ├── stack-builder/
│       │   │   │   │   │   │   ├── index.tsx
│       │   │   │   │   │   │   ├── selected-stack-badges.tsx
│       │   │   │   │   │   │   ├── tech-categories.tsx
│       │   │   │   │   │   │   └── use-stack-builder.ts
│       │   │   │   │   │   ├── tech-icon.tsx
│       │   │   │   │   │   ├── utils.ts
│       │   │   │   │   │   └── yolo-toggle.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── page.tsx
│       │   │   │   ├── showcase/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── ShowcaseItem.tsx
│       │   │   │   │   │   └── showcase-page.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   └── stack/
│       │   │   │       ├── _components/
│       │   │   │       │   └── stack-display.tsx
│       │   │   │       └── page.tsx
│       │   │   ├── api/
│       │   │   │   ├── preview/
│       │   │   │   │   └── route.ts
│       │   │   │   └── search/
│       │   │   │       └── route.ts
│       │   │   ├── docs/
│       │   │   │   ├── [[...slug]]/
│       │   │   │   │   └── page.tsx
│       │   │   │   └── layout.tsx
│       │   │   ├── global.css
│       │   │   ├── layout.config.tsx
│       │   │   ├── layout.tsx
│       │   │   ├── llms-full.txt/
│       │   │   │   └── route.ts
│       │   │   ├── llms.mdx/
│       │   │   │   └── [[...slug]]/
│       │   │   │       └── route.ts
│       │   │   ├── manifest.ts
│       │   │   ├── not-found.tsx
│       │   │   ├── og/
│       │   │   │   └── docs/
│       │   │   │       └── [...slug]/
│       │   │   │           └── route.tsx
│       │   │   └── sitemap.ts
│       │   ├── components/
│       │   │   ├── ai/
│       │   │   │   └── page-actions.tsx
│       │   │   ├── evilcharts/
│       │   │   │   ├── charts/
│       │   │   │   │   ├── area-chart.tsx
│       │   │   │   │   ├── bar-chart.tsx
│       │   │   │   │   ├── line-chart.tsx
│       │   │   │   │   ├── pie-chart.tsx
│       │   │   │   │   ├── radar-chart.tsx
│       │   │   │   │   └── radial-chart.tsx
│       │   │   │   └── ui/
│       │   │   │       ├── background.tsx
│       │   │   │       ├── chart.tsx
│       │   │   │       ├── dot.tsx
│       │   │   │       ├── evil-brush.tsx
│       │   │   │       ├── legend.tsx
│       │   │   │       └── tooltip.tsx
│       │   │   ├── providers.tsx
│       │   │   ├── special-sponsor-banner.tsx
│       │   │   ├── theme-toggle.tsx
│       │   │   └── ui/
│       │   │       ├── accordion.tsx
│       │   │       ├── button.tsx
│       │   │       ├── card.tsx
│       │   │       ├── dialog.tsx
│       │   │       ├── dropdown-menu.tsx
│       │   │       ├── file-tree.tsx
│       │   │       ├── hover-card.tsx
│       │   │       ├── input.tsx
│       │   │       ├── kibo-ui/
│       │   │       │   ├── code-block/
│       │   │       │   │   ├── index.tsx
│       │   │       │   │   └── server.tsx
│       │   │       │   └── qr-code/
│       │   │       │       ├── index.tsx
│       │   │       │       └── server.tsx
│       │   │       ├── scroll-area.tsx
│       │   │       ├── select.tsx
│       │   │       ├── share-dialog.tsx
│       │   │       ├── skeleton.tsx
│       │   │       ├── sonner.tsx
│       │   │       ├── spinner.tsx
│       │   │       ├── switch.tsx
│       │   │       ├── tabs.tsx
│       │   │       ├── tech-badge.tsx
│       │   │       ├── toggle.tsx
│       │   │       └── tooltip.tsx
│       │   └── lib/
│       │       ├── constant.ts
│       │       ├── get-llm-text.ts
│       │       ├── sanitize-stack-addons.ts
│       │       ├── search-config.ts
│       │       ├── source.ts
│       │       ├── sponsor-utils.ts
│       │       ├── sponsors.ts
│       │       ├── stack-url-keys.ts
│       │       ├── stack-url-state.client.ts
│       │       ├── stack-url-state.ts
│       │       ├── stack-utils.ts
│       │       ├── types.ts
│       │       └── utils.ts
│       ├── test/
│       │   └── stack-builder-compatibility.test.ts
│       └── tsconfig.json
├── bunfig.toml
├── changelogithub.config.ts
├── lefthook.yml
├── package.json
├── packages/
│   ├── backend/
│   │   ├── .gitignore
│   │   ├── convex/
│   │   │   ├── README.md
│   │   │   ├── _generated/
│   │   │   │   ├── api.d.ts
│   │   │   │   ├── api.js
│   │   │   │   ├── dataModel.d.ts
│   │   │   │   ├── server.d.ts
│   │   │   │   └── server.js
│   │   │   ├── analytics.ts
│   │   │   ├── analytics_date_utils.ts
│   │   │   ├── convex.config.ts
│   │   │   ├── healthCheck.ts
│   │   │   ├── hooks.ts
│   │   │   ├── http.ts
│   │   │   ├── schema.ts
│   │   │   ├── showcase.ts
│   │   │   ├── stats.ts
│   │   │   ├── testimonials.ts
│   │   │   └── tsconfig.json
│   │   └── package.json
│   ├── create-bts/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── cli.js
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   └── package.json
│   ├── template-generator/
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── generate-templates.ts
│   │   ├── src/
│   │   │   ├── bts-config.ts
│   │   │   ├── core/
│   │   │   │   ├── template-processor.ts
│   │   │   │   ├── template-reader.ts
│   │   │   │   └── virtual-fs.ts
│   │   │   ├── fs-writer.ts
│   │   │   ├── generator.ts
│   │   │   ├── index.ts
│   │   │   ├── post-process/
│   │   │   │   ├── catalogs.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── package-configs.ts
│   │   │   ├── processors/
│   │   │   │   ├── addons-deps.ts
│   │   │   │   ├── alchemy-plugins.ts
│   │   │   │   ├── api-deps.ts
│   │   │   │   ├── auth-deps.ts
│   │   │   │   ├── auth-plugins.ts
│   │   │   │   ├── backend-deps.ts
│   │   │   │   ├── db-deps.ts
│   │   │   │   ├── deploy-deps.ts
│   │   │   │   ├── env-deps.ts
│   │   │   │   ├── env-vars.ts
│   │   │   │   ├── examples-deps.ts
│   │   │   │   ├── frontend-deps.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── infra-deps.ts
│   │   │   │   ├── nx-generator.ts
│   │   │   │   ├── payments-deps.ts
│   │   │   │   ├── pwa-plugins.ts
│   │   │   │   ├── readme-generator.ts
│   │   │   │   ├── runtime-deps.ts
│   │   │   │   ├── turbo-generator.ts
│   │   │   │   └── workspace-deps.ts
│   │   │   ├── template-handlers/
│   │   │   │   ├── addons.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── auth.ts
│   │   │   │   ├── backend.ts
│   │   │   │   ├── base.ts
│   │   │   │   ├── database.ts
│   │   │   │   ├── deploy.ts
│   │   │   │   ├── examples.ts
│   │   │   │   ├── extras.ts
│   │   │   │   ├── frontend.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── packages.ts
│   │   │   │   ├── payments.ts
│   │   │   │   └── utils.ts
│   │   │   ├── templates.generated.ts
│   │   │   ├── types.ts
│   │   │   └── utils/
│   │   │       ├── add-deps.ts
│   │   │       ├── db-scripts.ts
│   │   │       └── reproducible-command.ts
│   │   ├── templates/
│   │   │   ├── addons/
│   │   │   │   ├── biome/
│   │   │   │   │   └── biome.json.hbs
│   │   │   │   ├── electrobun/
│   │   │   │   │   └── apps/
│   │   │   │   │       └── desktop/
│   │   │   │   │           ├── .gitignore
│   │   │   │   │           ├── electrobun.config.ts.hbs
│   │   │   │   │           ├── package.json.hbs
│   │   │   │   │           ├── src/
│   │   │   │   │           │   └── bun/
│   │   │   │   │           │       └── index.ts.hbs
│   │   │   │   │           └── tsconfig.json.hbs
│   │   │   │   ├── husky/
│   │   │   │   │   └── .husky/
│   │   │   │   │       └── pre-commit
│   │   │   │   ├── lefthook/
│   │   │   │   │   └── lefthook.yml.hbs
│   │   │   │   └── pwa/
│   │   │   │       └── apps/
│   │   │   │           └── web/
│   │   │   │               ├── next/
│   │   │   │               │   ├── public/
│   │   │   │               │   │   └── favicon/
│   │   │   │               │   │       └── site.webmanifest.hbs
│   │   │   │               │   └── src/
│   │   │   │               │       └── app/
│   │   │   │               │           └── manifest.ts.hbs
│   │   │   │               └── vite/
│   │   │   │                   └── pwa-assets.config.ts.hbs
│   │   │   ├── api/
│   │   │   │   ├── orpc/
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── astro/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── pages/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               └── [...rest].ts.hbs
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── rpc/
│   │   │   │   │   │   │                   └── [[...rest]]/
│   │   │   │   │   │   │                       └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── plugins/
│   │   │   │   │   │   │   │       ├── orpc.client.ts.hbs
│   │   │   │   │   │   │   │       └── orpc.server.ts.hbs
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               ├── [...].ts.hbs
│   │   │   │   │   │   │               └── index.ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       ├── lib/
│   │   │   │   │   │   │       │   └── orpc.server.ts.hbs
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               └── [...rest]/
│   │   │   │   │   │   │                   └── +server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── rpc/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   └── utils/
│   │   │   │   │   │       └── orpc.ts.hbs
│   │   │   │   │   ├── server/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── context.ts.hbs
│   │   │   │   │   │   │   ├── index.ts.hbs
│   │   │   │   │   │   │   └── routers/
│   │   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   └── web/
│   │   │   │   │       ├── astro/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       └── lib/
│   │   │   │   │       │           └── orpc.ts.hbs
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       └── plugins/
│   │   │   │   │       │           ├── orpc.ts.hbs
│   │   │   │   │       │           └── vue-query.ts.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   └── base/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           └── utils/
│   │   │   │   │       │               └── orpc.ts.hbs
│   │   │   │   │       ├── solid/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       └── utils/
│   │   │   │   │       │           └── orpc.ts.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               └── lib/
│   │   │   │   │                   └── orpc.ts.hbs
│   │   │   │   └── trpc/
│   │   │   │       ├── fullstack/
│   │   │   │       │   ├── next/
│   │   │   │       │   │   └── src/
│   │   │   │       │   │       └── app/
│   │   │   │       │   │           └── api/
│   │   │   │       │   │               └── trpc/
│   │   │   │       │   │                   └── [trpc]/
│   │   │   │       │   │                       └── route.ts.hbs
│   │   │   │       │   └── tanstack-start/
│   │   │   │       │       └── src/
│   │   │   │       │           └── routes/
│   │   │   │       │               └── api/
│   │   │   │       │                   └── trpc/
│   │   │   │       │                       └── $.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   └── utils/
│   │   │   │       │       └── trpc.ts.hbs
│   │   │   │       ├── server/
│   │   │   │       │   ├── _gitignore
│   │   │   │       │   ├── package.json.hbs
│   │   │   │       │   ├── src/
│   │   │   │       │   │   ├── context.ts.hbs
│   │   │   │       │   │   ├── index.ts.hbs
│   │   │   │       │   │   └── routers/
│   │   │   │       │   │       └── index.ts.hbs
│   │   │   │       │   └── tsconfig.json.hbs
│   │   │   │       └── web/
│   │   │   │           └── react/
│   │   │   │               └── base/
│   │   │   │                   └── src/
│   │   │   │                       └── utils/
│   │   │   │                           └── trpc.ts.hbs
│   │   │   ├── auth/
│   │   │   │   ├── better-auth/
│   │   │   │   │   ├── convex/
│   │   │   │   │   │   ├── backend/
│   │   │   │   │   │   │   └── convex/
│   │   │   │   │   │   │       ├── auth.config.ts.hbs
│   │   │   │   │   │   │       ├── auth.ts.hbs
│   │   │   │   │   │   │       ├── http.ts.hbs
│   │   │   │   │   │   │       └── privateData.ts.hbs
│   │   │   │   │   │   ├── native/
│   │   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   │   └── lib/
│   │   │   │   │   │   │   │       └── auth-client.ts.hbs
│   │   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │   │       └── components/
│   │   │   │   │   │   │           ├── sign-in.tsx.hbs
│   │   │   │   │   │   │           └── sign-up.tsx.hbs
│   │   │   │   │   │   └── web/
│   │   │   │   │   │       └── react/
│   │   │   │   │   │           ├── next/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── app/
│   │   │   │   │   │           │       │   ├── api/
│   │   │   │   │   │           │       │   │   └── auth/
│   │   │   │   │   │           │       │   │       └── [...all]/
│   │   │   │   │   │           │       │   │           └── route.ts.hbs
│   │   │   │   │   │           │       │   └── dashboard/
│   │   │   │   │   │           │       │       └── page.tsx.hbs
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       └── lib/
│   │   │   │   │   │           │           ├── auth-client.ts.hbs
│   │   │   │   │   │           │           └── auth-server.ts.hbs
│   │   │   │   │   │           ├── react-router/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       ├── lib/
│   │   │   │   │   │           │       │   └── auth-client.ts.hbs
│   │   │   │   │   │           │       └── routes/
│   │   │   │   │   │           │           └── dashboard.tsx.hbs
│   │   │   │   │   │           ├── tanstack-router/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       ├── lib/
│   │   │   │   │   │           │       │   └── auth-client.ts.hbs
│   │   │   │   │   │           │       └── routes/
│   │   │   │   │   │           │           └── dashboard.tsx.hbs
│   │   │   │   │   │           └── tanstack-start/
│   │   │   │   │   │               └── src/
│   │   │   │   │   │                   ├── components/
│   │   │   │   │   │                   │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │                   │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │                   │   └── user-menu.tsx.hbs
│   │   │   │   │   │                   ├── lib/
│   │   │   │   │   │                   │   ├── auth-client.ts.hbs
│   │   │   │   │   │                   │   └── auth-server.ts.hbs
│   │   │   │   │   │                   └── routes/
│   │   │   │   │   │                       ├── api/
│   │   │   │   │   │                       │   └── auth/
│   │   │   │   │   │                       │       └── $.ts.hbs
│   │   │   │   │   │                       └── dashboard.tsx.hbs
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── astro/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       ├── env.d.ts.hbs
│   │   │   │   │   │   │       ├── middleware.ts.hbs
│   │   │   │   │   │   │       └── pages/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── auth/
│   │   │   │   │   │   │                   └── [...all].ts.hbs
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── auth/
│   │   │   │   │   │   │                   └── [...all]/
│   │   │   │   │   │   │                       └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── api/
│   │   │   │   │   │   │           └── auth/
│   │   │   │   │   │   │               └── [...all].ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── hooks.server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── auth/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   └── lib/
│   │   │   │   │   │   │       └── auth-client.ts.hbs
│   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   └── (drawer)/
│   │   │   │   │   │       │       └── index.tsx.hbs
│   │   │   │   │   │       └── components/
│   │   │   │   │   │           ├── sign-in.tsx.hbs
│   │   │   │   │   │           └── sign-up.tsx.hbs
│   │   │   │   │   ├── server/
│   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   │   └── index.ts.hbs
│   │   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   │   └── db/
│   │   │   │   │   │       ├── drizzle/
│   │   │   │   │   │       │   ├── mysql/
│   │   │   │   │   │       │   │   └── src/
│   │   │   │   │   │       │   │       └── schema/
│   │   │   │   │   │       │   │           └── auth.ts.hbs
│   │   │   │   │   │       │   ├── postgres/
│   │   │   │   │   │       │   │   └── src/
│   │   │   │   │   │       │   │       └── schema/
│   │   │   │   │   │       │   │           └── auth.ts.hbs
│   │   │   │   │   │       │   └── sqlite/
│   │   │   │   │   │       │       └── src/
│   │   │   │   │   │       │           └── schema/
│   │   │   │   │   │       │               └── auth.ts.hbs
│   │   │   │   │   │       ├── mongoose/
│   │   │   │   │   │       │   └── mongodb/
│   │   │   │   │   │       │       └── src/
│   │   │   │   │   │       │           └── models/
│   │   │   │   │   │       │               └── auth.model.ts.hbs
│   │   │   │   │   │       └── prisma/
│   │   │   │   │   │           ├── mongodb/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           ├── mysql/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           ├── postgres/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           └── sqlite/
│   │   │   │   │   │               └── prisma/
│   │   │   │   │   │                   └── schema/
│   │   │   │   │   │                       └── auth.prisma.hbs
│   │   │   │   │   └── web/
│   │   │   │   │       ├── astro/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── SignInForm.astro.hbs
│   │   │   │   │       │       │   └── SignUpForm.astro.hbs
│   │   │   │   │       │       ├── lib/
│   │   │   │   │       │       │   └── auth-client.ts.hbs
│   │   │   │   │       │       └── pages/
│   │   │   │   │       │           ├── dashboard.astro.hbs
│   │   │   │   │       │           ├── login.astro.hbs
│   │   │   │   │       │           └── signup.astro.hbs
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── SignInForm.vue.hbs
│   │   │   │   │       │       │   ├── SignUpForm.vue.hbs
│   │   │   │   │       │       │   └── UserMenu.vue.hbs
│   │   │   │   │       │       ├── middleware/
│   │   │   │   │       │       │   └── auth.ts.hbs
│   │   │   │   │       │       ├── pages/
│   │   │   │   │       │       │   ├── dashboard.vue.hbs
│   │   │   │   │       │       │   └── login.vue.hbs
│   │   │   │   │       │       └── plugins/
│   │   │   │   │       │           └── auth-client.ts.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   ├── base/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── lib/
│   │   │   │   │       │   │           └── auth-client.ts.hbs
│   │   │   │   │       │   ├── next/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── app/
│   │   │   │   │       │   │       │   ├── dashboard/
│   │   │   │   │       │   │       │   │   ├── dashboard.tsx.hbs
│   │   │   │   │       │   │       │   │   └── page.tsx.hbs
│   │   │   │   │       │   │       │   └── login/
│   │   │   │   │       │   │       │       └── page.tsx.hbs
│   │   │   │   │       │   │       └── components/
│   │   │   │   │       │   │           ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │           ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │           └── user-menu.tsx.hbs
│   │   │   │   │       │   ├── react-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── components/
│   │   │   │   │       │   │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           ├── dashboard.tsx.hbs
│   │   │   │   │       │   │           └── login.tsx.hbs
│   │   │   │   │       │   ├── tanstack-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── components/
│   │   │   │   │       │   │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           ├── dashboard.tsx.hbs
│   │   │   │   │       │   │           └── login.tsx.hbs
│   │   │   │   │       │   └── tanstack-start/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           ├── components/
│   │   │   │   │       │           │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │           │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │           │   └── user-menu.tsx.hbs
│   │   │   │   │       │           ├── functions/
│   │   │   │   │       │           │   └── get-user.ts.hbs
│   │   │   │   │       │           ├── middleware/
│   │   │   │   │       │           │   └── auth.ts.hbs
│   │   │   │   │       │           └── routes/
│   │   │   │   │       │               ├── dashboard.tsx.hbs
│   │   │   │   │       │               └── login.tsx.hbs
│   │   │   │   │       ├── solid/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │       ├── lib/
│   │   │   │   │       │       │   └── auth-client.ts.hbs
│   │   │   │   │       │       └── routes/
│   │   │   │   │       │           ├── dashboard.tsx.hbs
│   │   │   │   │       │           └── login.tsx.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               ├── components/
│   │   │   │   │               │   ├── SignInForm.svelte.hbs
│   │   │   │   │               │   ├── SignUpForm.svelte.hbs
│   │   │   │   │               │   └── UserMenu.svelte.hbs
│   │   │   │   │               ├── lib/
│   │   │   │   │               │   └── auth-client.ts.hbs
│   │   │   │   │               └── routes/
│   │   │   │   │                   ├── dashboard/
│   │   │   │   │                   │   └── +page.svelte.hbs
│   │   │   │   │                   └── login/
│   │   │   │   │                       └── +page.svelte.hbs
│   │   │   │   └── clerk/
│   │   │   │       ├── convex/
│   │   │   │       │   ├── backend/
│   │   │   │       │   │   └── convex/
│   │   │   │       │   │       ├── auth.config.ts.hbs
│   │   │   │       │   │       └── privateData.ts.hbs
│   │   │   │       │   ├── native/
│   │   │   │       │   │   └── base/
│   │   │   │       │   │       ├── app/
│   │   │   │       │   │       │   └── (auth)/
│   │   │   │       │   │       │       ├── _layout.tsx.hbs
│   │   │   │       │   │       │       ├── sign-in.tsx.hbs
│   │   │   │       │   │       │       └── sign-up.tsx.hbs
│   │   │   │       │   │       └── components/
│   │   │   │       │   │           └── sign-out-button.tsx.hbs
│   │   │   │       │   └── web/
│   │   │   │       │       └── react/
│   │   │   │       │           ├── next/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       ├── app/
│   │   │   │       │           │       │   └── dashboard/
│   │   │   │       │           │       │       └── page.tsx.hbs
│   │   │   │       │           │       └── proxy.ts.hbs
│   │   │   │       │           ├── react-router/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       └── routes/
│   │   │   │       │           │           └── dashboard.tsx.hbs
│   │   │   │       │           ├── tanstack-router/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       └── routes/
│   │   │   │       │           │           └── dashboard.tsx.hbs
│   │   │   │       │           └── tanstack-start/
│   │   │   │       │               └── src/
│   │   │   │       │                   ├── routes/
│   │   │   │       │                   │   └── dashboard.tsx.hbs
│   │   │   │       │                   └── start.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   └── base/
│   │   │   │       │       ├── app/
│   │   │   │       │       │   └── (auth)/
│   │   │   │       │       │       ├── _layout.tsx.hbs
│   │   │   │       │       │       ├── sign-in.tsx.hbs
│   │   │   │       │       │       └── sign-up.tsx.hbs
│   │   │   │       │       ├── components/
│   │   │   │       │       │   └── sign-out-button.tsx.hbs
│   │   │   │       │       └── utils/
│   │   │   │       │           └── clerk-auth.ts.hbs
│   │   │   │       └── web/
│   │   │   │           └── react/
│   │   │   │               ├── base/
│   │   │   │               │   └── src/
│   │   │   │               │       └── utils/
│   │   │   │               │           └── clerk-auth.ts.hbs
│   │   │   │               ├── next/
│   │   │   │               │   └── src/
│   │   │   │               │       ├── app/
│   │   │   │               │       │   └── dashboard/
│   │   │   │               │       │       └── page.tsx.hbs
│   │   │   │               │       └── proxy.ts.hbs
│   │   │   │               ├── react-router/
│   │   │   │               │   └── src/
│   │   │   │               │       └── routes/
│   │   │   │               │           └── dashboard.tsx.hbs
│   │   │   │               ├── tanstack-router/
│   │   │   │               │   └── src/
│   │   │   │               │       └── routes/
│   │   │   │               │           └── dashboard.tsx.hbs
│   │   │   │               └── tanstack-start/
│   │   │   │                   └── src/
│   │   │   │                       ├── routes/
│   │   │   │                       │   └── dashboard.tsx.hbs
│   │   │   │                       └── start.ts.hbs
│   │   │   ├── backend/
│   │   │   │   ├── convex/
│   │   │   │   │   └── packages/
│   │   │   │   │       └── backend/
│   │   │   │   │           ├── _gitignore
│   │   │   │   │           ├── convex/
│   │   │   │   │           │   ├── README.md
│   │   │   │   │           │   ├── convex.config.ts.hbs
│   │   │   │   │           │   ├── healthCheck.ts.hbs
│   │   │   │   │           │   ├── schema.ts.hbs
│   │   │   │   │           │   └── tsconfig.json.hbs
│   │   │   │   │           └── package.json.hbs
│   │   │   │   └── server/
│   │   │   │       ├── base/
│   │   │   │       │   ├── _gitignore
│   │   │   │       │   ├── package.json.hbs
│   │   │   │       │   ├── tsconfig.json.hbs
│   │   │   │       │   └── tsdown.config.ts.hbs
│   │   │   │       ├── elysia/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── express/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── fastify/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       └── hono/
│   │   │   │           └── src/
│   │   │   │               └── index.ts.hbs
│   │   │   ├── base/
│   │   │   │   ├── _gitignore
│   │   │   │   ├── package.json.hbs
│   │   │   │   └── tsconfig.json.hbs
│   │   │   ├── db/
│   │   │   │   ├── base/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── drizzle/
│   │   │   │   │   ├── base/
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── schema/
│   │   │   │   │   │           └── index.ts.hbs
│   │   │   │   │   ├── mysql/
│   │   │   │   │   │   ├── drizzle.config.ts.hbs
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   ├── postgres/
│   │   │   │   │   │   ├── drizzle.config.ts.hbs
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   └── sqlite/
│   │   │   │   │       ├── drizzle.config.ts.hbs
│   │   │   │   │       └── src/
│   │   │   │   │           └── index.ts.hbs
│   │   │   │   ├── mongoose/
│   │   │   │   │   └── mongodb/
│   │   │   │   │       └── src/
│   │   │   │   │           └── index.ts.hbs
│   │   │   │   └── prisma/
│   │   │   │       ├── mongodb/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── mysql/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── postgres/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       └── sqlite/
│   │   │   │           ├── prisma/
│   │   │   │           │   └── schema/
│   │   │   │           │       └── schema.prisma.hbs
│   │   │   │           ├── prisma.config.ts.hbs
│   │   │   │           └── src/
│   │   │   │               └── index.ts.hbs
│   │   │   ├── db-setup/
│   │   │   │   └── docker-compose/
│   │   │   │       ├── mongodb/
│   │   │   │       │   └── docker-compose.yml.hbs
│   │   │   │       ├── mysql/
│   │   │   │       │   └── docker-compose.yml.hbs
│   │   │   │       └── postgres/
│   │   │   │           └── docker-compose.yml.hbs
│   │   │   ├── examples/
│   │   │   │   ├── ai/
│   │   │   │   │   ├── convex/
│   │   │   │   │   │   └── packages/
│   │   │   │   │   │       └── backend/
│   │   │   │   │   │           └── convex/
│   │   │   │   │   │               ├── agent.ts.hbs
│   │   │   │   │   │               └── chat.ts.hbs
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── ai/
│   │   │   │   │   │   │                   └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── api/
│   │   │   │   │   │   │           └── ai.post.ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── ai/
│   │   │   │   │   │   │                   └── +server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── ai/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── ai.tsx.hbs
│   │   │   │   │   │   │   └── polyfills.js
│   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── ai.tsx.hbs
│   │   │   │   │   │   │   └── polyfills.js
│   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   └── (drawer)/
│   │   │   │   │   │       │       └── ai.tsx.hbs
│   │   │   │   │   │       └── polyfills.js
│   │   │   │   │   └── web/
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       └── pages/
│   │   │   │   │       │           └── ai.vue.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   ├── next/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── app/
│   │   │   │   │       │   │           └── ai/
│   │   │   │   │       │   │               └── page.tsx.hbs
│   │   │   │   │       │   ├── react-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           └── ai.tsx.hbs
│   │   │   │   │       │   ├── tanstack-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           └── ai.tsx.hbs
│   │   │   │   │       │   └── tanstack-start/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           └── routes/
│   │   │   │   │       │               └── ai.tsx.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               └── routes/
│   │   │   │   │                   └── ai/
│   │   │   │   │                       └── +page.svelte.hbs
│   │   │   │   └── todo/
│   │   │   │       ├── convex/
│   │   │   │       │   └── packages/
│   │   │   │       │       └── backend/
│   │   │   │       │           └── convex/
│   │   │   │       │               └── todos.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   ├── bare/
│   │   │   │       │   │   └── app/
│   │   │   │       │   │       └── (drawer)/
│   │   │   │       │   │           └── todos.tsx.hbs
│   │   │   │       │   ├── unistyles/
│   │   │   │       │   │   └── app/
│   │   │   │       │   │       └── (drawer)/
│   │   │   │       │   │           └── todos.tsx.hbs
│   │   │   │       │   └── uniwind/
│   │   │   │       │       └── app/
│   │   │   │       │           └── (drawer)/
│   │   │   │       │               └── todos.tsx.hbs
│   │   │   │       ├── server/
│   │   │   │       │   ├── drizzle/
│   │   │   │       │   │   ├── base/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── routers/
│   │   │   │       │   │   │           └── todo.ts.hbs
│   │   │   │       │   │   ├── mysql/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── schema/
│   │   │   │       │   │   │           └── todo.ts
│   │   │   │       │   │   ├── postgres/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── schema/
│   │   │   │       │   │   │           └── todo.ts
│   │   │   │       │   │   └── sqlite/
│   │   │   │       │   │       └── src/
│   │   │   │       │   │           └── schema/
│   │   │   │       │   │               └── todo.ts
│   │   │   │       │   ├── mongoose/
│   │   │   │       │   │   ├── base/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── routers/
│   │   │   │       │   │   │           └── todo.ts.hbs
│   │   │   │       │   │   └── mongodb/
│   │   │   │       │   │       └── src/
│   │   │   │       │   │           └── models/
│   │   │   │       │   │               └── todo.model.ts.hbs
│   │   │   │       │   └── prisma/
│   │   │   │       │       ├── base/
│   │   │   │       │       │   └── src/
│   │   │   │       │       │       └── routers/
│   │   │   │       │       │           └── todo.ts.hbs
│   │   │   │       │       ├── mongodb/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       ├── mysql/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       ├── postgres/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       └── sqlite/
│   │   │   │       │           └── prisma/
│   │   │   │       │               └── schema/
│   │   │   │       │                   └── todo.prisma.hbs
│   │   │   │       └── web/
│   │   │   │           ├── astro/
│   │   │   │           │   └── src/
│   │   │   │           │       └── pages/
│   │   │   │           │           └── todos.astro.hbs
│   │   │   │           ├── nuxt/
│   │   │   │           │   └── app/
│   │   │   │           │       └── pages/
│   │   │   │           │           └── todos.vue.hbs
│   │   │   │           ├── react/
│   │   │   │           │   ├── next/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── app/
│   │   │   │           │   │           └── todos/
│   │   │   │           │   │               └── page.tsx.hbs
│   │   │   │           │   ├── react-router/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── routes/
│   │   │   │           │   │           └── todos.tsx.hbs
│   │   │   │           │   ├── tanstack-router/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── routes/
│   │   │   │           │   │           └── todos.tsx.hbs
│   │   │   │           │   └── tanstack-start/
│   │   │   │           │       └── src/
│   │   │   │           │           └── routes/
│   │   │   │           │               └── todos.tsx.hbs
│   │   │   │           ├── solid/
│   │   │   │           │   └── src/
│   │   │   │           │       └── routes/
│   │   │   │           │           └── todos.tsx.hbs
│   │   │   │           └── svelte/
│   │   │   │               └── src/
│   │   │   │                   └── routes/
│   │   │   │                       └── todos/
│   │   │   │                           └── +page.svelte.hbs
│   │   │   ├── extras/
│   │   │   │   ├── _npmrc.hbs
│   │   │   │   ├── bunfig.toml.hbs
│   │   │   │   ├── env.d.ts.hbs
│   │   │   │   └── pnpm-workspace.yaml
│   │   │   ├── frontend/
│   │   │   │   ├── astro/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── astro.config.mjs.hbs
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── Header.astro.hbs
│   │   │   │   │   │   ├── layouts/
│   │   │   │   │   │   │   └── Layout.astro.hbs
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   └── index.astro.hbs
│   │   │   │   │   │   └── styles/
│   │   │   │   │   │       └── global.css
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── native/
│   │   │   │   │   ├── bare/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── (drawer)/
│   │   │   │   │   │   │   │   ├── (tabs)/
│   │   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   │   ├── index.tsx.hbs
│   │   │   │   │   │   │   │   │   └── two.tsx.hbs
│   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   │   ├── +not-found.tsx.hbs
│   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   └── modal.tsx.hbs
│   │   │   │   │   │   ├── app.json.hbs
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── container.tsx.hbs
│   │   │   │   │   │   │   ├── header-button.tsx.hbs
│   │   │   │   │   │   │   └── tabbar-icon.tsx.hbs
│   │   │   │   │   │   ├── lib/
│   │   │   │   │   │   │   ├── constants.ts.hbs
│   │   │   │   │   │   │   └── use-color-scheme.ts.hbs
│   │   │   │   │   │   ├── metro.config.js.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── (drawer)/
│   │   │   │   │   │   │   │   ├── (tabs)/
│   │   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   │   ├── index.tsx.hbs
│   │   │   │   │   │   │   │   │   └── two.tsx.hbs
│   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   │   ├── +html.tsx.hbs
│   │   │   │   │   │   │   ├── +not-found.tsx.hbs
│   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   └── modal.tsx.hbs
│   │   │   │   │   │   ├── app.json.hbs
│   │   │   │   │   │   ├── babel.config.js.hbs
│   │   │   │   │   │   ├── breakpoints.ts.hbs
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── container.tsx.hbs
│   │   │   │   │   │   │   ├── header-button.tsx.hbs
│   │   │   │   │   │   │   └── tabbar-icon.tsx.hbs
│   │   │   │   │   │   ├── index.js.hbs
│   │   │   │   │   │   ├── metro.config.js.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── theme.ts.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── unistyles.ts.hbs
│   │   │   │   │   └── uniwind/
│   │   │   │   │       ├── _gitignore
│   │   │   │   │       ├── app/
│   │   │   │   │       │   ├── (drawer)/
│   │   │   │   │       │   │   ├── (tabs)/
│   │   │   │   │       │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │       │   │   │   ├── index.tsx.hbs
│   │   │   │   │       │   │   │   └── two.tsx.hbs
│   │   │   │   │       │   │   ├── _layout.tsx.hbs
│   │   │   │   │       │   │   └── index.tsx.hbs
│   │   │   │   │       │   ├── +not-found.tsx.hbs
│   │   │   │   │       │   ├── _layout.tsx.hbs
│   │   │   │   │       │   └── modal.tsx.hbs
│   │   │   │   │       ├── app.json.hbs
│   │   │   │   │       ├── components/
│   │   │   │   │       │   ├── container.tsx.hbs
│   │   │   │   │       │   └── theme-toggle.tsx.hbs
│   │   │   │   │       ├── contexts/
│   │   │   │   │       │   └── app-theme-context.tsx.hbs
│   │   │   │   │       ├── global.css
│   │   │   │   │       ├── metro.config.js.hbs
│   │   │   │   │       ├── package.json.hbs
│   │   │   │   │       ├── tsconfig.json.hbs
│   │   │   │   │       └── uniwind-env.d.ts
│   │   │   │   ├── nuxt/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── app/
│   │   │   │   │   │   ├── app.config.ts.hbs
│   │   │   │   │   │   ├── app.vue.hbs
│   │   │   │   │   │   ├── assets/
│   │   │   │   │   │   │   └── css/
│   │   │   │   │   │   │       └── main.css
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── Header.vue.hbs
│   │   │   │   │   │   ├── layouts/
│   │   │   │   │   │   │   └── default.vue.hbs
│   │   │   │   │   │   └── pages/
│   │   │   │   │   │       └── index.vue.hbs
│   │   │   │   │   ├── nuxt.config.ts.hbs
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── public/
│   │   │   │   │   │   └── robots.txt
│   │   │   │   │   ├── server/
│   │   │   │   │   │   └── tsconfig.json
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── react/
│   │   │   │   │   ├── next/
│   │   │   │   │   │   ├── next-env.d.ts.hbs
│   │   │   │   │   │   ├── next.config.ts.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── postcss.config.mjs.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   ├── layout.tsx.hbs
│   │   │   │   │   │   │   │   └── page.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │       ├── providers.tsx.hbs
│   │   │   │   │   │   │       └── theme-provider.tsx.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   ├── react-router/
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── react-router.config.ts
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │   │   └── theme-provider.tsx.hbs
│   │   │   │   │   │   │   ├── root.tsx.hbs
│   │   │   │   │   │   │   ├── routes/
│   │   │   │   │   │   │   │   └── _index.tsx.hbs
│   │   │   │   │   │   │   └── routes.ts
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   ├── tanstack-router/
│   │   │   │   │   │   ├── index.html.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │   │   └── theme-provider.tsx.hbs
│   │   │   │   │   │   │   ├── main.tsx.hbs
│   │   │   │   │   │   │   └── routes/
│   │   │   │   │   │   │       ├── __root.tsx.hbs
│   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   ├── tanstack-start/
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── public/
│   │   │   │   │   │   │   └── robots.txt
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── router.tsx.hbs
│   │   │   │   │   │   │   └── routes/
│   │   │   │   │   │   │       ├── __root.tsx.hbs
│   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   └── web-base/
│   │   │   │   │       ├── _gitignore
│   │   │   │   │       ├── components.json.hbs
│   │   │   │   │       └── src/
│   │   │   │   │           ├── components/
│   │   │   │   │           │   ├── header.tsx.hbs
│   │   │   │   │           │   └── loader.tsx.hbs
│   │   │   │   │           └── index.css.hbs
│   │   │   │   ├── solid/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── public/
│   │   │   │   │   │   └── robots.txt
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── header.tsx.hbs
│   │   │   │   │   │   │   └── loader.tsx
│   │   │   │   │   │   ├── main.tsx.hbs
│   │   │   │   │   │   ├── routes/
│   │   │   │   │   │   │   ├── __root.tsx.hbs
│   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   └── styles.css
│   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   └── svelte/
│   │   │   │       ├── _gitignore
│   │   │   │       ├── _npmrc
│   │   │   │       ├── package.json.hbs
│   │   │   │       ├── src/
│   │   │   │       │   ├── app.css
│   │   │   │       │   ├── app.d.ts.hbs
│   │   │   │       │   ├── app.html
│   │   │   │       │   ├── components/
│   │   │   │       │   │   └── Header.svelte.hbs
│   │   │   │       │   ├── lib/
│   │   │   │       │   │   └── index.ts
│   │   │   │       │   └── routes/
│   │   │   │       │       ├── +layout.svelte.hbs
│   │   │   │       │       └── +page.svelte.hbs
│   │   │   │       ├── svelte.config.js.hbs
│   │   │   │       ├── tsconfig.json.hbs
│   │   │   │       └── vite.config.ts.hbs
│   │   │   ├── packages/
│   │   │   │   ├── config/
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   └── tsconfig.base.json.hbs
│   │   │   │   ├── env/
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── cloudflare-local.ts.hbs
│   │   │   │   │   │   ├── native.ts.hbs
│   │   │   │   │   │   ├── server.ts.hbs
│   │   │   │   │   │   └── web.ts.hbs
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── infra/
│   │   │   │   │   ├── alchemy.run.ts.hbs
│   │   │   │   │   └── package.json.hbs
│   │   │   │   └── ui/
│   │   │   │       ├── components.json.hbs
│   │   │   │       ├── package.json.hbs
│   │   │   │       ├── postcss.config.mjs.hbs
│   │   │   │       ├── src/
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── button.tsx.hbs
│   │   │   │       │   │   ├── card.tsx.hbs
│   │   │   │       │   │   ├── checkbox.tsx.hbs
│   │   │   │       │   │   ├── dropdown-menu.tsx.hbs
│   │   │   │       │   │   ├── input.tsx.hbs
│   │   │   │       │   │   ├── label.tsx.hbs
│   │   │   │       │   │   ├── skeleton.tsx.hbs
│   │   │   │       │   │   └── sonner.tsx.hbs
│   │   │   │       │   ├── hooks/
│   │   │   │       │   │   └── .gitkeep
│   │   │   │       │   ├── lib/
│   │   │   │       │   │   └── utils.ts.hbs
│   │   │   │       │   └── styles/
│   │   │   │       │       └── globals.css.hbs
│   │   │   │       └── tsconfig.json.hbs
│   │   │   └── payments/
│   │   │       └── polar/
│   │   │           ├── server/
│   │   │           │   └── base/
│   │   │           │       └── src/
│   │   │           │           └── lib/
│   │   │           │               └── payments.ts.hbs
│   │   │           └── web/
│   │   │               ├── nuxt/
│   │   │               │   └── app/
│   │   │               │       └── pages/
│   │   │               │           └── success.vue.hbs
│   │   │               ├── react/
│   │   │               │   ├── next/
│   │   │               │   │   └── src/
│   │   │               │   │       └── app/
│   │   │               │   │           └── success/
│   │   │               │   │               └── page.tsx.hbs
│   │   │               │   ├── react-router/
│   │   │               │   │   └── src/
│   │   │               │   │       └── routes/
│   │   │               │   │           └── success.tsx.hbs
│   │   │               │   ├── tanstack-router/
│   │   │               │   │   └── src/
│   │   │               │   │       └── routes/
│   │   │               │   │           └── success.tsx.hbs
│   │   │               │   └── tanstack-start/
│   │   │               │       └── src/
│   │   │               │           ├── functions/
│   │   │               │           │   └── get-payment.ts.hbs
│   │   │               │           └── routes/
│   │   │               │               └── success.tsx.hbs
│   │   │               ├── solid/
│   │   │               │   └── src/
│   │   │               │       └── routes/
│   │   │               │           └── success.tsx.hbs
│   │   │               └── svelte/
│   │   │                   └── src/
│   │   │                       └── routes/
│   │   │                           └── success/
│   │   │                               └── +page.svelte.hbs
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   └── types/
│       ├── package.json
│       ├── src/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── json-schema.ts
│       │   ├── schemas.ts
│       │   └── types.ts
│       ├── tsconfig.json
│       └── tsdown.config.ts
├── scripts/
│   ├── bump-version.ts
│   ├── canary-release.ts
│   ├── cleanup-previews.ts
│   ├── publish-smoke.ts
│   └── release.ts
├── tsconfig.json
└── turbo.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing to Better-T-Stack

Thank you for your interest in contributing to Better-T-Stack! This document provides guidelines and setup instructions for contributors.

> **⚠️ Important**: Before starting work on any new features or major changes, please open an issue first to discuss your proposal and get approval. We don't want you to waste time on work that might not align with the project's direction or get merged.

## Project Structure

This repository is organized as a monorepo containing:

- **CLI**: [`apps/cli`](apps/cli) - The scaffolding CLI tool (`create-better-t-stack`)
- **Documentation**: [`apps/web`](apps/web) - Official website and documentation

## Development Setup

### Prerequisites

- Node.js (lts)
- Bun (recommended)
- Git

### Initial Setup

1. **Clone the repository**

   ```bash
   git clone https://github.com/AmanVarshney01/create-better-t-stack.git
   cd create-better-t-stack
   ```

2. **Install dependencies**
   ```bash
   bun install
   ```

### CLI Development

1. **Navigate to CLI directory**

   ```bash
   cd apps/cli
   ```

2. **Link the CLI globally** (optional, for testing anywhere in your system)

   ```bash
   bun link
   ```

   Now you can use `create-better-t-stack` from anywhere in your system.

3. **Start development server**

   ```bash
   bun dev
   ```

   This runs tsdown build in watch mode, automatically rebuilding on changes.

4. **Test the CLI**
   Now go to anywhere else in your system (maybe like a test folder) and run:
   ```bash
   create-better-t-stack
   ```
   This will run the locally installed CLI.

### Web Development

1. **Install dependencies**

   ```bash
   # from repo root
   bun i
   ```

2. **Setup backend**

   ```bash
   cd packages/backend
   bun dev:setup  # you can choose local development too in prompts
   ```

3. **Configure environment**
   Copy the Convex URL from `packages/backend/.env.local` to `apps/web/.env`:

   ```
   NEXT_PUBLIC_CONVEX_URL=http://127.0.0.1:3210/
   ```

4. **Set GitHub tokens**
   Now run `bun dev` in the root. It will complain about GitHub token, so run this in `packages/backend`:

   ```bash
   npx convex env set GITHUB_ACCESS_TOKEN=xxxxx
   npx convex env set GITHUB_WEBHOOK_SECRET=xxxxx
   ```

5. **Start the documentation website**
   ```bash
   bun dev
   ```
   This starts the Next.js development server for the documentation site.

## Contribution Guidelines

### Standard Contribution Steps

1. **Create an issue** (if one doesn't exist)
   - Describe the bug or feature request
   - Include steps to reproduce (for bugs)
   - Discuss the proposed solution

2. **Fork the repository**
   - Click the "Fork" button on GitHub
   - Clone your fork locally

3. **Create a feature branch**

   ```bash
   git checkout -b feature/your-feature-name
   # or
   git checkout -b fix/your-bug-fix
   ```

4. **Make your changes**
   - Follow the existing code style
   - Update documentation as needed

5. **Test and format your changes** (see Testing section below)

6. **Commit your changes**

   ```bash
   git add .
   git commit -m "feat(web): add your feature description"
   # or
   git commit -m "fix(cli): fix your bug description"
   ```

7. **Push to your fork**

   ```bash
   git push origin feature/your-feature-name
   ```

8. **Create a Pull Request**
   - Link to the related issue
   - Describe your changes

### Testing

**Before committing, make sure to test your changes:**

```bash
# For CLI changes
cd apps/cli
bun dev
bun run test

# Lint and format files (from root, uses oxlint and oxfmt)
bun run check
```

- **Manual testing**: Test your changes manually to ensure everything works as expected
- For CLI changes: Test with different configurations and options
- For web changes: Ensure the site builds and displays correctly

## Commit Conventions

Use conventional commit messages with the appropriate scope:

- `feat(cli): add new CLI feature`
- `fix(cli): fix CLI bug`
- `feat(web): add new web feature`
- `fix(web): fix web bug`
- `chore(web): update dependencies`

## Getting Help

- Open an issue for bugs or feature requests
- Join discussions for questions or ideas
- Check existing issues and PRs for similar work
- Join our [Discord](https://discord.gg/ZYsbjpDaM5) if you have any problems

## License

By contributing to Better-T-Stack, you agree that your contributions will be licensed under the MIT License.


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [amanvarshney01]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/workflows/pr-preview.yaml
================================================
name: PR Preview

on:
  pull_request_target:
    types: [labeled]

permissions:
  contents: read
  pull-requests: write
  id-token: write

concurrency:
  group: pr-preview-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  publish-preview:
    name: Publish Preview
    runs-on: ubuntu-latest
    if: github.event.label.name == 'preview'
    steps:
      - name: Checkout PR Code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: package.json
          check-latest: true
          registry-url: https://registry.npmjs.org

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install Dependencies
        run: bun install --frozen-lockfile
        env:
          BTS_TELEMETRY: 0

      - name: Verify NPM auth
        run: npm whoami
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Generate Preview Version
        id: version
        run: |
          PR_NUMBER=${{ github.event.pull_request.number }}
          COMMIT_SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7)
          BASE_VERSION=$(jq -r '.version' apps/cli/package.json | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
          PREVIEW_VERSION="${BASE_VERSION}-pr${PR_NUMBER}.${COMMIT_SHA}"
          NPM_TAG="pr${PR_NUMBER}"

          echo "version=$PREVIEW_VERSION" >> $GITHUB_OUTPUT
          echo "tag=$NPM_TAG" >> $GITHUB_OUTPUT
          echo "pr=$PR_NUMBER" >> $GITHUB_OUTPUT
          echo "commit=$COMMIT_SHA" >> $GITHUB_OUTPUT

          echo "Preview version: $PREVIEW_VERSION"
          echo "NPM tag: $NPM_TAG"

      - name: Update types package version
        run: |
          cd packages/types
          jq --arg v "${{ steps.version.outputs.version }}" '.version = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Build types package
        run: cd packages/types && bun run build

      - name: Publish types to NPM
        run: cd packages/types && npm publish --access public --provenance --tag ${{ steps.version.outputs.tag }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 0

      - name: Update template-generator package version and types dependency
        run: |
          cd packages/template-generator
          jq --arg v "${{ steps.version.outputs.version }}" '.version = $v | .dependencies["@better-t-stack/types"] = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Build template-generator package
        run: cd packages/template-generator && bun run build

      - name: Publish template-generator to NPM
        run: cd packages/template-generator && npm publish --access public --provenance --tag ${{ steps.version.outputs.tag }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 0

      - name: Update CLI package version and dependencies
        run: |
          cd apps/cli
          jq --arg v "${{ steps.version.outputs.version }}" '.version = $v | .dependencies["@better-t-stack/types"] = $v | .dependencies["@better-t-stack/template-generator"] = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Update create-bts alias package version
        run: |
          cd packages/create-bts
          jq --arg v "${{ steps.version.outputs.version }}" '.version = $v | .dependencies["create-better-t-stack"] = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Build CLI
        run: cd apps/cli && bun run build
        env:
          BTS_TELEMETRY: 0

      - name: Publish CLI to NPM
        run: cd apps/cli && npm publish --access public --provenance --tag ${{ steps.version.outputs.tag }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 0

      - name: Publish create-bts to NPM
        run: cd packages/create-bts && npm publish --access public --provenance --tag ${{ steps.version.outputs.tag }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 0

      - name: Find existing preview comment
        uses: peter-evans/find-comment@v3
        id: find-comment
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-author: "github-actions[bot]"
          body-includes: "PR Preview Release"

      - name: Create or update PR comment
        uses: peter-evans/create-or-update-comment@v4
        with:
          comment-id: ${{ steps.find-comment.outputs.comment-id }}
          issue-number: ${{ github.event.pull_request.number }}
          edit-mode: replace
          body: |
            ## PR Preview Release

            A preview version has been published for this PR.

            | Package | Version | NPM Tag |
            |---------|---------|---------|
            | `create-better-t-stack` | `${{ steps.version.outputs.version }}` | `pr${{ steps.version.outputs.pr }}` |
            | `create-bts` | `${{ steps.version.outputs.version }}` | `pr${{ steps.version.outputs.pr }}` |
            | `@better-t-stack/types` | `${{ steps.version.outputs.version }}` | `pr${{ steps.version.outputs.pr }}` |
            | `@better-t-stack/template-generator` | `${{ steps.version.outputs.version }}` | `pr${{ steps.version.outputs.pr }}` |

            **Commit:** `${{ steps.version.outputs.commit }}`

            ### Install

            ```bash
            # Using the PR tag (always gets latest for this PR)
            bunx create-better-t-stack@pr${{ steps.version.outputs.pr }}
            npx create-better-t-stack@pr${{ steps.version.outputs.pr }}

            # Using exact version
            bunx create-better-t-stack@${{ steps.version.outputs.version }}
            npx create-better-t-stack@${{ steps.version.outputs.version }}

            # Using the alias
            bunx create-bts@pr${{ steps.version.outputs.pr }}
            npx create-bts@pr${{ steps.version.outputs.pr }}
            ```

            ### NPM Links
            - [create-better-t-stack@${{ steps.version.outputs.version }}](https://www.npmjs.com/package/create-better-t-stack/v/${{ steps.version.outputs.version }})
            - [create-bts@${{ steps.version.outputs.version }}](https://www.npmjs.com/package/create-bts/v/${{ steps.version.outputs.version }})
            - [@better-t-stack/types@${{ steps.version.outputs.version }}](https://www.npmjs.com/package/@better-t-stack/types/v/${{ steps.version.outputs.version }})
            - [@better-t-stack/template-generator@${{ steps.version.outputs.version }}](https://www.npmjs.com/package/@better-t-stack/template-generator/v/${{ steps.version.outputs.version }})

            ---
            *To publish a new preview after more commits, remove and re-add the `preview` label.*


================================================
FILE: .github/workflows/release.yaml
================================================
name: Release

on:
  push:
    branches:
      - main

permissions:
  contents: write
  pull-requests: write
  id-token: write

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

jobs:
  release:
    name: Release to NPM
    if: startsWith(github.event.head_commit.message, 'chore(release):')
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: package.json
          check-latest: true
          registry-url: https://registry.npmjs.org

      - name: Extract version from commit message
        id: version
        run: |
          VERSION=$(echo "${{ github.event.head_commit.message }}" | sed -E 's/^chore\(release\): ([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Releasing version: $VERSION"

      - name: Validate version format
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "Error: Invalid version format '$VERSION'. Expected semver (x.y.z)"
            exit 1
          fi

      - name: Check if version already exists
        id: check-version
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          if npm view create-better-t-stack@$VERSION version 2>/dev/null; then
            echo "Version $VERSION already exists on NPM"
            echo "exists=true" >> $GITHUB_OUTPUT
          else
            echo "Version $VERSION is new"
            echo "exists=false" >> $GITHUB_OUTPUT
          fi

      - name: Setup Bun
        if: steps.check-version.outputs.exists == 'false'
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install Dependencies
        if: steps.check-version.outputs.exists == 'false'
        run: bun install --frozen-lockfile

      - name: Verify NPM auth
        if: steps.check-version.outputs.exists == 'false'
        run: npm whoami
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Update types package version
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          cd packages/types
          jq --arg v "$VERSION" '.version = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Build types package
        if: steps.check-version.outputs.exists == 'false'
        run: cd packages/types && bun run build

      - name: Update template-generator package version and types dependency
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          cd packages/template-generator
          jq --arg v "$VERSION" --arg dep "^$VERSION" '.version = $v | .dependencies["@better-t-stack/types"] = $dep' package.json > tmp.json && mv tmp.json package.json

      - name: Build template-generator package
        if: steps.check-version.outputs.exists == 'false'
        run: cd packages/template-generator && bun run build

      - name: Update CLI types and template-generator dependencies and version
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          cd apps/cli
          jq --arg v "^$VERSION" '.dependencies["@better-t-stack/types"] = $v | .dependencies["@better-t-stack/template-generator"] = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Build CLI
        if: steps.check-version.outputs.exists == 'false'
        run: cd apps/cli && bun run build
        env:
          BTS_TELEMETRY: 1
          CONVEX_INGEST_URL: ${{ secrets.CONVEX_INGEST_URL }}

      - name: Update create-bts alias package version
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          cd packages/create-bts
          jq --arg v "$VERSION" --arg dep "^$VERSION" '.version = $v | .dependencies["create-better-t-stack"] = $dep' package.json > tmp.json && mv tmp.json package.json

      - name: Enable pnpm via corepack
        if: steps.check-version.outputs.exists == 'false'
        run: corepack enable pnpm

      # Gate all publishes on the smoke so a failure here doesn't leave a
      # partial release on npm (e.g. types/template-generator published but
      # create-better-t-stack broken).
      - name: Publish smoke test (npm, pnpm, bun)
        if: steps.check-version.outputs.exists == 'false'
        run: bun run smoke:publish

      - name: Publish types to NPM
        if: steps.check-version.outputs.exists == 'false'
        run: cd packages/types && npm publish --access public --provenance
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 1
          CONVEX_INGEST_URL: ${{ secrets.CONVEX_INGEST_URL }}

      - name: Publish template-generator to NPM
        if: steps.check-version.outputs.exists == 'false'
        run: cd packages/template-generator && npm publish --access public --provenance
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 1
          CONVEX_INGEST_URL: ${{ secrets.CONVEX_INGEST_URL }}

      - name: Publish CLI to NPM
        if: steps.check-version.outputs.exists == 'false'
        run: cd apps/cli && npm publish --access public --provenance
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 1
          CONVEX_INGEST_URL: ${{ secrets.CONVEX_INGEST_URL }}

      - name: Publish create-bts alias to NPM
        if: steps.check-version.outputs.exists == 'false'
        run: cd packages/create-bts && npm publish --access public --provenance
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          BTS_TELEMETRY: 1
          CONVEX_INGEST_URL: ${{ secrets.CONVEX_INGEST_URL }}

      - name: Create and push tag
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          git config --local user.email "amanvarshney.work@gmail.com"
          git config --local user.name "Aman Varshney"
          if ! git rev-parse "v$VERSION" >/dev/null 2>&1; then
            git tag -a "v$VERSION" -m "Release v$VERSION"
            git push --tags
          else
            echo "Tag v$VERSION already exists, skipping"
          fi

      - name: Create GitHub Release
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          if ! gh release view "v$VERSION" >/dev/null 2>&1; then
            bunx changelogithub
          else
            echo "Release v$VERSION already exists, skipping"
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Release Summary
        if: steps.check-version.outputs.exists == 'false'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          echo "## Release v$VERSION Complete!" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "### Published Packages" >> $GITHUB_STEP_SUMMARY
          echo "- [create-better-t-stack@$VERSION](https://www.npmjs.com/package/create-better-t-stack/v/$VERSION)" >> $GITHUB_STEP_SUMMARY
          echo "- [create-bts@$VERSION](https://www.npmjs.com/package/create-bts/v/$VERSION)" >> $GITHUB_STEP_SUMMARY
          echo "- [@better-t-stack/types@$VERSION](https://www.npmjs.com/package/@better-t-stack/types/v/$VERSION)" >> $GITHUB_STEP_SUMMARY
          echo "- [@better-t-stack/template-generator@$VERSION](https://www.npmjs.com/package/@better-t-stack/template-generator/v/$VERSION)" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "### GitHub Release" >> $GITHUB_STEP_SUMMARY
          echo "[v$VERSION](https://github.com/${{ github.repository }}/releases/tag/v$VERSION)" >> $GITHUB_STEP_SUMMARY


================================================
FILE: .github/workflows/test.yaml
================================================
name: Test

on:
  pull_request:
    types: [opened, synchronize, reopened]

concurrency:
  group: test-${{ github.head_ref }}
  cancel-in-progress: true

jobs:
  test:
    name: Test Suite
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version-file: package.json
          check-latest: true

      - name: Setup Git user
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install Dependencies
        run: bun install --frozen-lockfile
        env:
          BTS_TELEMETRY: 0

      - name: Build Types
        run: cd packages/types && bun run build

      - name: Build Template Generator
        run: cd packages/template-generator && bun run build

      - name: Build and Test CLI
        working-directory: apps/cli
        run: bun run build && bun run test:ci
        env:
          AGENT: 1
          BTS_TELEMETRY: 0

      - name: Enable pnpm via corepack
        run: corepack enable pnpm

      - name: Publish smoke test (npm, pnpm, bun)
        run: bun run smoke:publish


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# Dependencies
node_modules
.pnp
.pnp.js

# Local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Testing
coverage

# Turbo
.turbo

# Vercel
.vercel

# Build Outputs
out/
build
dist


# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Misc
.DS_Store
*.pem
.vscode
.env*.local

.smoke

.idea

templates-binary

# opensrc - source code for packages
opensrc/


================================================
FILE: .oxfmtrc.json
================================================
{
  "$schema": "./node_modules/oxfmt/configuration_schema.json",
  "experimentalSortImports": {
    "order": "asc"
  },
  "experimentalSortPackageJson": true,
  "ignorePatterns": [
    "*.hbs",
    "apps/cli/templates/**",
    "packages/backend/convex/_generated/**",
    "packages/template-generator/src/templates.generated.ts"
  ]
}


================================================
FILE: AGENTS.md
================================================
# Repository Guidelines

## Project Structure & Module Organization

This repo is a Bun + Turborepo monorepo.

- `apps/cli`: published CLI (`create-better-t-stack`), with source in `apps/cli/src` and tests in `apps/cli/test`.
- `apps/web`: Next.js docs/site (`apps/web/src`, `apps/web/content/docs`, `apps/web/public`).
- `packages/template-generator`: template generation engine used by the CLI.
- `packages/types`: shared schemas/types.
- `packages/backend`: Convex backend used by web features.

## Build, Test, and Development Commands

- `bun install`: install workspace dependencies.
- `bun dev:cli`: watch-build CLI package.
- `bun dev:web`: run web app locally (`next dev --port 3333`).
- `bun build`: build all packages/apps through Turbo.
- `bun build:cli`: build only the CLI target.
- `bun run check`: format + lint (`oxfmt . && oxlint .`).
- `cd apps/cli && bun run test`: run CLI tests.

## Coding Style & Naming Conventions

- Language: TypeScript (strict mode enabled across projects).
- Modules: ESM-first (`"type": "module"` where applicable).
- Formatting/linting: `oxfmt` and `oxlint`; run `bun run check` before committing.
- File naming: prefer kebab-case files (for example `database-setup.ts`).
- Symbols: `camelCase` for functions/variables, `PascalCase` for types/components.
- Keep feature logic near domain folders (`helpers`, `utils`, `template-handlers`).

## Error Handling Conventions

- In CLI code, prefer `better-result` over ad-hoc `try/catch` for recoverable flows.
- Return typed `Result<T, E>` and use `Result.ok`, `Result.err`, `Result.try`, and `Result.tryPromise`.
- Reuse domain errors from `apps/cli/src/utils/errors.ts` (`CLIError`, `ProjectCreationError`, `UserCancelledError`) and convert thrown prompt errors at boundaries.

## Template Authoring (Handlebars)

- Templates live in `packages/template-generator/templates` and use helpers from `packages/template-generator/src/core/template-processor.ts` (`eq`, `ne`, `and`, `or`, `includes`).
- For conditional ORM-specific output, use helper form with quoted values:
  - `{{#if (eq orm "prisma")}}`
  - `{{else if (eq orm "drizzle")}}`
  - `{{/if}}`
  - Example: `packages/template-generator/templates/packages/infra/alchemy.run.ts.hbs`.
- When files must contain literal `{{ ... }}` (Vue/JSX/template syntax), escape opening braces as `\{{` in `.hbs` files so Handlebars does not evaluate them.
  - Example: `packages/template-generator/templates/frontend/nuxt/app/pages/index.vue.hbs`.

## Testing Guidelines

- Framework: `bun:test`.
- Test files use `*.test.ts` naming (see `apps/cli/test` and `packages/template-generator/test`).
- Add or update tests with behavior changes, especially prompt flows, template output, and config validation.
- Keep tests deterministic; reuse shared setup utilities in `apps/cli/test/setup.ts`.

## Commit & Pull Request Guidelines

- Use Conventional Commits with scope, matching history:
  - `feat(cli): ...`, `fix(web): ...`, `docs(cli): ...`
- Open an issue/discussion before major feature work.
- PRs should include:
  - clear summary,
  - linked issue (if applicable),
  - verification steps run (`bun run check`, relevant tests),
  - screenshots/GIFs for web UI changes.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2025 Better T Stack

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Better-T-Stack

A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations

<br />
<a href="https://vercel.com/oss">
  <img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge.svg" />
</a>

## Sponsors

<p align="center">
<img src="https://sponsors.amanv.dev/sponsors.png" alt="Sponsors">
</p>

![demo](https://github.com/user-attachments/assets/12fd4d67-8494-462a-8124-76670798308a)

## Philosophy

- Roll your own stack: you pick only the parts you need, nothing extra.
- Minimal templates: bare-bones scaffolds with zero bloat.
- Latest dependencies: always use current, stable versions by default.
- Free and open source: forever.

## Quick Start

```bash
# Using bun (recommended)
bun create better-t-stack@latest

# Using pnpm
pnpm create better-t-stack@latest

# Using npm
npx create-better-t-stack@latest
```

## Features

- Frontend: React (TanStack Router, React Router, TanStack Start), Next.js, Nuxt, Svelte, Solid, Astro, React Native (Bare, NativeWind, Unistyles), or none
- Backend: Hono, Express, Fastify, Elysia, Self (fullstack web app), Convex, or none
- API: tRPC or oRPC (or none)
- Runtime: Bun, Node.js, or Cloudflare Workers
- Databases: SQLite, PostgreSQL, MySQL, MongoDB (or none)
- ORMs: Drizzle, Prisma, Mongoose (or none)
- Auth: Better Auth or Clerk (optional)
- Addons: Turborepo, Nx, PWA, Tauri, Electrobun, Biome, Lefthook, Husky, Starlight, Fumadocs, Ultracite, Oxlint, MCP, OpenTUI, WXT, Skills
- Examples: Todo, AI
- DB Setup: Turso, Neon, Supabase, Prisma PostgreSQL, MongoDB Atlas, Cloudflare D1, Docker
- Web Deploy: Cloudflare Workers

Type safety end-to-end, clean monorepo layout, and zero lock-in: you choose only what you need.

## Repository Structure

This repository is organized as a monorepo containing:

- **CLI**: [`apps/cli`](apps/cli) - The scaffolding CLI tool
- **Documentation**: [`apps/web`](apps/web) - Official website and documentation

## Documentation

Visit [better-t-stack.dev](https://better-t-stack.dev) for full documentation, guides, and examples. You can also use the visual Stack Builder at `https://better-t-stack.dev/new` to generate a command for your stack.

## Development

```bash
# Clone the repository
git clone https://github.com/AmanVarshney01/create-better-t-stack.git

# Install dependencies
bun install

# Start CLI development
bun dev:cli

# Start website development
bun dev:web
```

## Want to contribute?

Please read the Contribution Guide first and open an issue before starting new features to ensure alignment with project goals.

- Docs: [`./apps/web/content/docs/contributing.mdx`](./apps/web/content/docs/contributing.mdx)
- Repo guide: [`./.github/CONTRIBUTING.md`](./.github/CONTRIBUTING.md)

## Star History

<a href="https://www.star-history.com/#AmanVarshney01/create-better-t-stack&Date">
 <picture>
   <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=AmanVarshney01/create-better-t-stack&type=Date&theme=dark" />
   <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=AmanVarshney01/create-better-t-stack&type=Date" />
   <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=AmanVarshney01/create-better-t-stack&type=Date" />
 </picture>
</a>


================================================
FILE: apps/cli/.gitignore
================================================
/node_modules
/dist
.smoke

================================================
FILE: apps/cli/README.md
================================================
# Create Better-T-Stack CLI

A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations

## Sponsors

<p align="center">
<img src="https://sponsors.amanv.dev/sponsors.png" alt="Sponsors">
</p>

![demo](https://cdn.jsdelivr.net/gh/amanvarshney01/create-better-t-stack@master/demo.gif)

## Quick Start

Run without installing globally:

```bash
# Using bun (recommended)
bun create better-t-stack@latest

# Using pnpm
pnpm create better-t-stack@latest

# Using npm
npx create-better-t-stack@latest
```

Follow the prompts to configure your project or use the `--yes` flag for defaults.

## Features

| Category                 | Options                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **TypeScript**           | End-to-end type safety across all parts of your application                                                                                                                                                                                                                                                                                                                                                             |
| **Frontend**             | • React with TanStack Router<br>• React with React Router<br>• React with TanStack Start (SSR)<br>• Next.js<br>• SvelteKit<br>• Nuxt (Vue)<br>• SolidJS<br>• Astro<br>• React Native bare Expo<br>• React Native with NativeWind (via Expo)<br>• React Native with Unistyles (via Expo)<br>• None                                                                                                                       |
| **Backend**              | • Hono<br>• Express<br>• Elysia<br>• Fastify<br>• Self (fullstack inside the web app)<br>• Convex<br>• None                                                                                                                                                                                                                                                                                                             |
| **API Layer**            | • tRPC (type-safe APIs)<br>• oRPC (OpenAPI-compatible type-safe APIs)<br>• None                                                                                                                                                                                                                                                                                                                                         |
| **Runtime**              | • Bun<br>• Node.js<br>• Cloudflare Workers<br>• None                                                                                                                                                                                                                                                                                                                                                                    |
| **Database**             | • SQLite<br>• PostgreSQL<br>• MySQL<br>• MongoDB<br>• None                                                                                                                                                                                                                                                                                                                                                              |
| **ORM**                  | • Drizzle (TypeScript-first)<br>• Prisma (feature-rich)<br>• Mongoose (for MongoDB)<br>• None                                                                                                                                                                                                                                                                                                                           |
| **Database Setup**       | • Turso (SQLite)<br>• Cloudflare D1 (SQLite)<br>• Neon (PostgreSQL)<br>• Supabase (PostgreSQL)<br>• Prisma Postgres<br>• MongoDB Atlas<br>• None (manual setup)                                                                                                                                                                                                                                                         |
| **Authentication**       | • Better Auth<br>• Clerk                                                                                                                                                                                                                                                                                                                                                                                                |
| **Styling**              | Tailwind CSS with a shared shadcn/ui package for React web apps                                                                                                                                                                                                                                                                                                                                                         |
| **Addons**               | • PWA support<br>• Tauri (desktop applications)<br>• Electrobun (lightweight desktop shell)<br>• Starlight and Fumadocs (documentation sites)<br>• Biome, Oxlint, Ultracite (linting and formatting)<br>• Lefthook, Husky (Git hooks)<br>• evlog (request logging for server/fullstack backends)<br>• MCP, Skills (agent tooling)<br>• OpenTUI, WXT (platform extensions)<br>• Turborepo or Nx (monorepo orchestration) |
| **Examples**             | • Todo app<br>• AI Chat interface (using Vercel AI SDK)                                                                                                                                                                                                                                                                                                                                                                 |
| **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation                                                                                                                                                                                                                                                                                                      |

## Usage

```bash
Usage: create-better-t-stack [project-directory] [options]

Options:
  -V, --version                   Output the version number
  -y, --yes                       Use default configuration
  --template <type>               Use a template (mern, pern, t3, uniwind, none)
  --database <type>               Database type (none, sqlite, postgres, mysql, mongodb)
  --orm <type>                    ORM type (none, drizzle, prisma, mongoose)
  --dry-run                       Validate configuration without writing files
  --auth <provider>               Authentication (better-auth, clerk, none)
  --payments <provider>           Payments provider (polar, none)
  --frontend <types...>           Frontend types (tanstack-router, react-router, tanstack-start, next, nuxt, svelte, solid, astro, native-bare, native-uniwind, native-unistyles, none)
  --addons <types...>             Additional addons (pwa, tauri, electrobun, starlight, biome, lefthook, husky, mcp, turborepo, nx, fumadocs, ultracite, oxlint, opentui, wxt, skills, evlog, none)
  --examples <types...>           Examples to include (todo, ai, none)
  --git                           Initialize git repository
  --no-git                        Skip git initialization
  --package-manager <pm>          Package manager (npm, pnpm, bun)
  --install                       Install dependencies
  --no-install                    Skip installing dependencies
  --db-setup <setup>              Database setup (turso, d1, neon, supabase, prisma-postgres, planetscale, mongodb-atlas, docker, none)
  --web-deploy <setup>            Web deployment (cloudflare, none)
  --server-deploy <setup>         Server deployment (cloudflare, none)
  --backend <framework>           Backend framework (hono, express, fastify, elysia, convex, self, none)
  --runtime <runtime>             Runtime (bun, node, workers, none)
  --api <type>                    API type (trpc, orpc, none)
  --directory-conflict <strategy> Directory strategy (merge, overwrite, increment, error)
  --manual-db                     Skip automatic database setup prompts
  -h, --help                      Display help
```

### Agent-Focused Commands

```bash
# Raw JSON payload input (agent-friendly)
create-better-t-stack create-json --input '{"projectName":"my-app","yes":true,"dryRun":true}'
create-better-t-stack add-json --input '{"projectDir":"./my-app","addons":["wxt"],"addonOptions":{"wxt":{"template":"react"}}}'
create-better-t-stack create-json --input '{"projectName":"db-app","database":"postgres","orm":"drizzle","dbSetup":"neon","dbSetupOptions":{"mode":"manual"}}'

# Runtime schema/introspection output
create-better-t-stack schema --name all
create-better-t-stack schema --name createInput
create-better-t-stack schema --name addInput
create-better-t-stack schema --name addonOptions
create-better-t-stack schema --name dbSetupOptions
create-better-t-stack schema --name cli

# Local stdio MCP server
npx create-better-t-stack@latest mcp
```

To install Better T Stack into supported agent configs with `add-mcp` and avoid relying on a global CLI install:

```bash
npx -y add-mcp@latest "npx -y create-better-t-stack@latest mcp"
```

When you scaffold with the `mcp` addon, Better T Stack itself can also be installed into supported agent configs through `add-mcp` using a package runner command instead of assuming a global CLI install. For Bun projects, the generated config uses the equivalent `bunx create-better-t-stack@latest mcp` server command inside `add-mcp`.

For MCP project creation, prefer `install: false`. Long dependency installs can exceed common MCP client request timeouts, so the safest flow is to scaffold first and run your package manager install command afterward in the project directory.

## Telemetry

This CLI collects anonymous usage data to help improve the tool. The data collected includes:

- Configuration options selected
- CLI version
- Node.js version
- Platform (OS)

**Telemetry is enabled by default in published versions** to help us understand usage patterns and improve the tool.

### Disabling Telemetry

You can disable telemetry by setting the `BTS_TELEMETRY_DISABLED` environment variable:

```bash
# Disable telemetry for a single run
BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack

# Disable telemetry globally in your shell profile (.bashrc, .zshrc, etc.)
export BTS_TELEMETRY_DISABLED=1
```

## Examples

Create a project with default configuration:

```bash
npx create-better-t-stack --yes
```

Validate a command without writing files:

```bash
npx create-better-t-stack --yes --dry-run
```

Create a project with specific options:

```bash
npx create-better-t-stack --database postgres --orm drizzle --auth better-auth --addons pwa biome
```

Create a project with Elysia backend and Node.js runtime:

```bash
npx create-better-t-stack --backend elysia --runtime node
```

Create a project with multiple frontend options (one web + one native):

```bash
npx create-better-t-stack --frontend tanstack-router native-bare
```

Create a project with examples:

```bash
npx create-better-t-stack --examples todo ai
```

Create a project with Turso database setup:

```bash
npx create-better-t-stack --database sqlite --orm drizzle --db-setup turso
```

Create a project with Supabase PostgreSQL setup:

```bash
npx create-better-t-stack --database postgres --orm drizzle --db-setup supabase --auth better-auth
```

Create a project with Convex backend:

```bash
npx create-better-t-stack --backend convex --frontend tanstack-router
```

Create a project with documentation site:

```bash
npx create-better-t-stack --addons starlight
```

Create a minimal TypeScript project with no backend:

```bash
npx create-better-t-stack --backend none --frontend tanstack-router
```

Create a backend-only project with no frontend:

```bash
npx create-better-t-stack --frontend none --backend hono --database postgres --orm drizzle
```

Create a simple frontend-only project:

```bash
npx create-better-t-stack --backend none --frontend next --addons none --examples none
```

Create a Cloudflare Workers project:

```bash
npx create-better-t-stack --backend hono --runtime workers --database sqlite --orm drizzle --db-setup d1
```

Create a self-hosted fullstack project on Cloudflare with D1:

```bash
npx create-better-t-stack --backend self --frontend next --api trpc --database sqlite --orm drizzle --db-setup d1 --web-deploy cloudflare
```

Create a minimal API-only project:

```bash
npx create-better-t-stack --frontend none --backend hono --api trpc --database none --addons none
```

## Compatibility Notes

- **Convex backend**: Requires `database`, `orm`, `api`, `runtime`, and `server-deploy` to be `none`; auth can be `better-auth`, `clerk`, or `none` depending frontend compatibility
- **Backend 'none'**: If selected, this option will force related options like API, ORM, database, authentication, and runtime to 'none'. Examples will also be disabled (set to none/empty).
- **Frontend 'none'**: Creates a backend-only project. When selected, PWA, Tauri, Electrobun, and certain examples may be disabled.
- **API 'none'**: Disables tRPC/oRPC setup. Can be used with backend frameworks for REST APIs or custom API implementations.
- **Database 'none'**: Disables database setup and requires ORM to be `none`.
- **ORM 'none'**: Can be used when you want to handle database operations manually or use a different ORM.
- **Runtime 'none'**: Only available with Convex backend, backend `none`, or backend `self`.
- **Cloudflare Workers runtime**: Only compatible with Hono backend. If a database is used, MongoDB is not supported.
- **Cloudflare D1 setup**: Requires `sqlite` and either `--runtime workers --server-deploy cloudflare` or `--backend self --web-deploy cloudflare`. For `backend self`, D1 is supported on `next`, `tanstack-start`, `nuxt`, `svelte`, and `astro`.
- **Addons 'none'**: Skips all addons.
- **Examples 'none'**: Skips all example implementations (todo, AI chat).
- **Nuxt, Svelte, SolidJS, and Astro** frontends are only compatible with oRPC API layer
- **PWA support** requires TanStack Router, React Router, Next.js, or SolidJS
- **Tauri desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro
- **Electrobun desktop app** requires TanStack Router, React Router, TanStack Start, Next.js, Nuxt, SvelteKit, SolidJS, or Astro. Desktop packaging uses static web assets, so SSR-first frontends need a static/export build before desktop builds will work.
- **AI example** is not compatible with Solid or Astro. With Convex backend, it also excludes Nuxt and Svelte.

## Project Structure

The created project follows a clean monorepo structure:

```
my-better-t-app/
├── apps/
│   ├── web/          # Frontend application
│   ├── server/       # Backend API
│   ├── native/       # (optional) Mobile application
│   └── docs/         # (optional) Documentation site
├── packages/         # Shared packages
└── README.md         # Auto-generated project documentation
```

After project creation, you'll receive detailed instructions for next steps and additional setup requirements.


================================================
FILE: apps/cli/bunfig.toml
================================================
[test]
# Preload setup file for global setup/teardown
preload = ["./test/setup.ts"]

# Per-test timeout (3 minutes for smoke tests)
timeout = 180000

# Skip test files from coverage reports
coverageSkipTestFiles = true

# Exclude patterns from coverage
coveragePathIgnorePatterns = ["test/**", "dist/**", "templates/**", "node_modules/**"]


================================================
FILE: apps/cli/package.json
================================================
{
  "name": "create-better-t-stack",
  "version": "3.28.0",
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
  "keywords": [
    "better-auth",
    "better-t-stack",
    "biome",
    "boilerplate",
    "cli",
    "drizzle",
    "elysia",
    "expo",
    "fullstack",
    "hono",
    "monorepo",
    "prisma",
    "pwa",
    "react",
    "react-native",
    "shadcn",
    "starter",
    "tailwind",
    "tanstack",
    "tauri",
    "trpc",
    "turborepo",
    "type-safety",
    "typescript"
  ],
  "homepage": "https://better-t-stack.dev/",
  "license": "MIT",
  "author": "Aman Varshney",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/AmanVarshney01/create-better-t-stack.git",
    "directory": "apps/cli"
  },
  "bin": {
    "create-better-t-stack": "dist/cli.mjs"
  },
  "files": [
    "dist"
  ],
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.mts",
      "import": "./dist/index.mjs"
    },
    "./cli": {
      "import": "./dist/cli.mjs"
    },
    "./virtual": {
      "types": "./dist/virtual.d.mts",
      "import": "./dist/virtual.mjs"
    }
  },
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "build": "tsdown --publint",
    "dev": "tsdown --watch",
    "check-types": "tsc --noEmit",
    "test": "bun run build && bun test",
    "test:watch": "bun run build && bun test --watch",
    "test:coverage": "bun run build && bun test --coverage",
    "test:ci": "bun run build && CI=1 bun test --bail=5",
    "prepublishOnly": "npm run build"
  },
  "dependencies": {
    "@better-t-stack/template-generator": "workspace:*",
    "@better-t-stack/types": "workspace:*",
    "@clack/core": "^1.2.0",
    "@clack/prompts": "^1.2.0",
    "@modelcontextprotocol/sdk": "1.29.0",
    "@trpc/server": "^11.16.0",
    "better-result": "^2.8.2",
    "consola": "^3.4.2",
    "env-paths": "^4.0.0",
    "execa": "^9.6.1",
    "fs-extra": "^11.3.4",
    "gradient-string": "^3.0.0",
    "handlebars": "^4.7.9",
    "jsonc-parser": "^3.3.1",
    "oxfmt": "^0.46.0",
    "picocolors": "^1.1.1",
    "tinyglobby": "^0.2.15",
    "trpc-cli": "^0.14.0",
    "ts-morph": "^28.0.0",
    "yaml": "^2.8.3",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@types/bun": "^1.3.12",
    "@types/fs-extra": "^11.0.4",
    "@types/node": "^25.6.0",
    "publint": "^0.3.18",
    "tsdown": "^0.21.9",
    "typescript": "^6.0.3"
  }
}


================================================
FILE: apps/cli/src/cli.ts
================================================
import { createBtsCli } from "./index";
import { startBtsMcpServer } from "./mcp";

const [, , command, ...args] = process.argv;

if (command === "mcp") {
  if (args.includes("--help") || args.includes("-h")) {
    console.log(`Usage: create-better-t-stack mcp

Start the Better T Stack MCP server over stdio.

This command is intended to be launched by an MCP client, for example:
  create-better-t-stack mcp`);
    process.exit(0);
  }

  await startBtsMcpServer();
} else {
  await createBtsCli().run();
}


================================================
FILE: apps/cli/src/commands/history.ts
================================================
import { intro, log } from "@clack/prompts";
import pc from "picocolors";

import { clearHistory, getHistory, type ProjectHistoryEntry } from "../utils/project-history";
import { renderTitle } from "../utils/render-title";

export type HistoryCommandInput = {
  limit: number;
  clear: boolean;
  json: boolean;
};

function formatStackSummary(entry: ProjectHistoryEntry): string {
  const parts: string[] = [];

  if (entry.stack.frontend.length > 0 && !entry.stack.frontend.includes("none")) {
    parts.push(entry.stack.frontend.join(", "));
  }

  if (entry.stack.backend && entry.stack.backend !== "none") {
    parts.push(entry.stack.backend);
  }

  if (entry.stack.database && entry.stack.database !== "none") {
    parts.push(entry.stack.database);
  }

  if (entry.stack.orm && entry.stack.orm !== "none") {
    parts.push(entry.stack.orm);
  }

  return parts.length > 0 ? parts.join(" + ") : "minimal";
}

function formatDate(isoString: string): string {
  const date = new Date(isoString);
  return date.toLocaleDateString("en-US", {
    year: "numeric",
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

export async function historyHandler(input: HistoryCommandInput): Promise<void> {
  if (input.clear) {
    const clearResult = await clearHistory();
    if (clearResult.isErr()) {
      log.warn(pc.yellow(clearResult.error.message));
      return;
    }
    log.success(pc.green("Project history cleared."));
    return;
  }

  const historyResult = await getHistory(input.limit);
  if (historyResult.isErr()) {
    log.warn(pc.yellow(historyResult.error.message));
    return;
  }
  const entries = historyResult.value;

  if (entries.length === 0) {
    log.info(pc.dim("No projects in history yet."));
    log.info(pc.dim("Create a project with: create-better-t-stack my-app"));
    return;
  }

  if (input.json) {
    console.log(JSON.stringify(entries, null, 2));
    return;
  }

  renderTitle();
  intro(pc.magenta(`Project History (${entries.length} entries)`));

  for (const [index, entry] of entries.entries()) {
    const num = pc.dim(`${index + 1}.`);
    const name = pc.cyan(pc.bold(entry.projectName));
    const stack = pc.dim(formatStackSummary(entry));

    log.message(`${num} ${name}`);
    log.message(`   ${pc.dim("Created:")} ${formatDate(entry.createdAt)}`);
    log.message(`   ${pc.dim("Path:")} ${entry.projectDir}`);
    log.message(`   ${pc.dim("Stack:")} ${stack}`);
    log.message(`   ${pc.dim("Command:")} ${pc.dim(entry.reproducibleCommand)}`);
    log.message("");
  }
}


================================================
FILE: apps/cli/src/commands/meta.ts
================================================
import { intro, log } from "@clack/prompts";
import { Result } from "better-result";
import pc from "picocolors";

import { displayError } from "../utils/errors";
import { openUrl } from "../utils/open-url";
import { renderTitle } from "../utils/render-title";
import { displaySponsors, fetchSponsors } from "../utils/sponsors";

const DOCS_URL = "https://better-t-stack.dev/docs";
const BUILDER_URL = "https://better-t-stack.dev/new";

async function openExternalUrl(url: string, successMessage: string) {
  const result = await Result.tryPromise({
    try: () => openUrl(url),
    catch: () => null,
  });

  if (result.isOk()) {
    log.success(pc.blue(successMessage));
  } else {
    log.message(`Please visit ${url}`);
  }
}

export async function showSponsorsCommand() {
  renderTitle();
  intro(pc.magenta("Better-T-Stack Sponsors"));

  const sponsorsResult = await fetchSponsors();
  if (sponsorsResult.isErr()) {
    displayError(sponsorsResult.error);
    process.exit(1);
    return;
  }

  displaySponsors(sponsorsResult.value);
}

export async function openDocsCommand() {
  await openExternalUrl(DOCS_URL, "Opened docs in your default browser.");
}

export async function openBuilderCommand() {
  await openExternalUrl(BUILDER_URL, "Opened builder in your default browser.");
}


================================================
FILE: apps/cli/src/constants.ts
================================================
import path from "node:path";
import { fileURLToPath } from "node:url";

import { desktopWebFrontends } from "@better-t-stack/types";

import { getUserPkgManager } from "./utils/get-package-manager";

// Re-export from template-generator (single source of truth)
export {
  dependencyVersionMap,
  type AvailableDependencies,
} from "@better-t-stack/template-generator";

const __filename = fileURLToPath(import.meta.url);
const distPath = path.dirname(__filename);
export const PKG_ROOT = path.join(distPath, "../");

export const DEFAULT_CONFIG_BASE = {
  projectName: "my-better-t-app",
  relativePath: "my-better-t-app",
  frontend: ["tanstack-router"],
  database: "sqlite",
  orm: "drizzle",
  auth: "better-auth",
  payments: "none",
  addons: ["turborepo"],
  examples: [],
  git: true,
  install: true,
  dbSetup: "none",
  backend: "hono",
  runtime: "bun",
  api: "trpc",
  webDeploy: "none",
  serverDeploy: "none",
} as const;

export function getDefaultConfig() {
  return {
    ...DEFAULT_CONFIG_BASE,
    projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
    packageManager: getUserPkgManager(),
    frontend: [...DEFAULT_CONFIG_BASE.frontend],
    addons: [...DEFAULT_CONFIG_BASE.addons],
    examples: [...DEFAULT_CONFIG_BASE.examples],
  };
}

export const DEFAULT_CONFIG = getDefaultConfig();

export { desktopWebFrontends };

export const ADDON_COMPATIBILITY = {
  pwa: ["tanstack-router", "react-router", "solid", "next"],
  tauri: desktopWebFrontends,
  electrobun: desktopWebFrontends,
  biome: [],
  husky: [],
  lefthook: [],
  turborepo: [],
  nx: [],
  starlight: [],
  ultracite: [],
  mcp: [],
  oxlint: [],
  fumadocs: [],
  opentui: [],
  wxt: [],
  skills: [],
  evlog: [],
  none: [],
} as const;


================================================
FILE: apps/cli/src/helpers/addons/addons-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import fs from "fs-extra";
import pc from "picocolors";

import { desktopWebFrontends, type ProjectConfig } from "../../types";
import { addPackageDependency } from "../../utils/add-package-deps";
import { AddonSetupError, UserCancelledError } from "../../utils/errors";
import { cliConsola } from "../../utils/terminal-output";
import { setupEvlog } from "./evlog-setup";
import { setupFumadocs } from "./fumadocs-setup";
import { setupMcp } from "./mcp-setup";
import { setupOxlint } from "./oxlint-setup";
import { setupSkills } from "./skills-setup";
import { setupStarlight } from "./starlight-setup";
import { setupTauri } from "./tauri-setup";
import { setupTui } from "./tui-setup";
import { setupUltracite } from "./ultracite-setup";
import { setupWxt } from "./wxt-setup";

// Helper to run setup and handle Result
async function runSetup<T, E extends AddonSetupError | UserCancelledError>(
  setupFn: () => Promise<Result<T, E>>,
): Promise<void> {
  const result = await setupFn();
  if (result.isErr()) {
    // Re-throw user cancellation to propagate up
    if (UserCancelledError.is(result.error)) {
      throw result.error;
    }
    // Log other errors but don't fail the overall project creation
    cliConsola.error(pc.red(result.error.message));
  }
}

async function runAddonStep(addon: string, step: () => Promise<void>): Promise<void> {
  const result = await Result.tryPromise({
    try: async () => step(),
    catch: (e) =>
      new AddonSetupError({
        addon,
        message: `Failed to set up ${addon}: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (result.isErr()) {
    cliConsola.error(pc.red(result.error.message));
  }
}

export async function setupAddons(config: ProjectConfig) {
  const { addons, frontend, projectDir } = config;
  const hasWebFrontend = frontend.some((value) =>
    (desktopWebFrontends as readonly string[]).includes(value),
  );

  if (addons.includes("tauri") && hasWebFrontend) {
    await runSetup(() => setupTauri(config));
  }

  const hasUltracite = addons.includes("ultracite");
  const hasBiome = addons.includes("biome");
  const hasHusky = addons.includes("husky");
  const hasLefthook = addons.includes("lefthook");
  const hasOxlint = addons.includes("oxlint");

  if (hasUltracite) {
    const gitHooks: string[] = [];
    if (hasHusky) gitHooks.push("husky");
    if (hasLefthook) gitHooks.push("lefthook");
    await runSetup(() => setupUltracite(config, gitHooks));
  } else {
    if (hasBiome) {
      await runAddonStep("biome", () => setupBiome(projectDir));
    }

    if (hasOxlint) {
      await runSetup(() => setupOxlint(projectDir, config.packageManager));
    }

    if (hasHusky || hasLefthook) {
      let linter: "biome" | "oxlint" | undefined;
      if (hasOxlint) {
        linter = "oxlint";
      } else if (hasBiome) {
        linter = "biome";
      }
      if (hasHusky) {
        await runAddonStep("husky", () => setupHusky(projectDir, linter));
      }
      if (hasLefthook) {
        await runAddonStep("lefthook", () => setupLefthook(projectDir));
      }
    }
  }

  if (addons.includes("starlight")) {
    await runSetup(() => setupStarlight(config));
  }

  if (addons.includes("fumadocs")) {
    await runSetup(() => setupFumadocs(config));
  }

  if (addons.includes("opentui")) {
    await runSetup(() => setupTui(config));
  }

  if (addons.includes("wxt")) {
    await runSetup(() => setupWxt(config));
  }

  if (addons.includes("skills")) {
    await runSetup(() => setupSkills(config));
  }

  if (addons.includes("mcp")) {
    await runSetup(() => setupMcp(config));
  }

  if (addons.includes("evlog")) {
    await runSetup(() => setupEvlog(config));
  }
}

export async function setupBiome(projectDir: string) {
  await addPackageDependency({
    devDependencies: ["@biomejs/biome"],
    projectDir,
  });

  const packageJsonPath = path.join(projectDir, "package.json");
  if (await fs.pathExists(packageJsonPath)) {
    const packageJson = await fs.readJson(packageJsonPath);

    packageJson.scripts = {
      ...packageJson.scripts,
      check: "biome check --write .",
    };

    await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
  }
}

export async function setupHusky(projectDir: string, linter?: "biome" | "oxlint") {
  await addPackageDependency({
    devDependencies: ["husky", "lint-staged"],
    projectDir,
  });

  const packageJsonPath = path.join(projectDir, "package.json");
  if (await fs.pathExists(packageJsonPath)) {
    const packageJson = await fs.readJson(packageJsonPath);

    packageJson.scripts = {
      ...packageJson.scripts,
      prepare: "husky",
    };

    if (linter === "oxlint") {
      packageJson["lint-staged"] = {
        "*": ["oxlint", "oxfmt --write"],
      };
    } else if (linter === "biome") {
      packageJson["lint-staged"] = {
        "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": ["biome check --write ."],
      };
    } else {
      packageJson["lint-staged"] = {
        "**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue,astro,svelte}": "",
      };
    }

    await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
  }
}

export async function setupLefthook(projectDir: string) {
  await addPackageDependency({
    devDependencies: ["lefthook"],
    projectDir,
  });
  // lefthook.yml is generated by template-generator from templates/addons/lefthook/
}


================================================
FILE: apps/cli/src/helpers/addons/evlog-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import fs from "fs-extra";

import type { Backend, Frontend, ProjectConfig } from "../../types";
import { AddonSetupError } from "../../utils/errors";

type EvlogBackend = Extract<Backend, "hono" | "express" | "fastify" | "elysia">;
type EvlogWebFrontend = Extract<Frontend, "next" | "nuxt" | "svelte" | "tanstack-start" | "astro">;

const evlogBackends = ["hono", "express", "fastify", "elysia"] as const;
const evlogWebFrontends = ["next", "nuxt", "svelte", "tanstack-start", "astro"] as const;

function isEvlogBackend(backend: Backend): backend is EvlogBackend {
  return (evlogBackends as readonly Backend[]).includes(backend);
}

function getEvlogWebFrontend(frontends: Frontend[]): EvlogWebFrontend | undefined {
  return frontends.find((frontend): frontend is EvlogWebFrontend =>
    (evlogWebFrontends as readonly Frontend[]).includes(frontend),
  );
}

function shouldIdentifyWebAuth(config: ProjectConfig) {
  return config.auth === "better-auth" && config.backend === "self";
}

function prependMissingImports(content: string, imports: string[]) {
  const missingImports = imports.filter((line) => !content.includes(line));
  if (missingImports.length === 0) return content;

  const importBlock = `${missingImports.join("\n")}\n`;
  const referenceMatch = content.match(/^(?:\/\/\/ <reference[^\n]*>\n)+/);
  if (referenceMatch) {
    return `${referenceMatch[0]}${importBlock}${content.slice(referenceMatch[0].length)}`;
  }

  return `${importBlock}${content}`;
}

function addNamedImport(content: string, moduleName: string, names: string[]) {
  const importRegex = new RegExp(
    `import \\{([^}]+)\\} from "${moduleName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}";`,
  );
  const match = content.match(importRegex);

  if (!match) {
    return prependMissingImports(content, [`import { ${names.join(", ")} } from "${moduleName}";`]);
  }

  const existingNames = match[1]
    .split(",")
    .map((name) => name.trim())
    .filter(Boolean);
  const nextNames = [...existingNames];

  for (const name of names) {
    if (!nextNames.includes(name)) {
      nextNames.push(name);
    }
  }

  return content.replace(match[0], `import { ${nextNames.join(", ")} } from "${moduleName}";`);
}

function insertBeforeOnce(
  content: string,
  marker: string,
  snippet: string,
  alreadyPresent: string,
) {
  if (content.includes(alreadyPresent)) return content;
  if (!content.includes(marker)) return content;
  return content.replace(marker, `${snippet}${marker}`);
}

function insertAfterOnce(content: string, marker: string, snippet: string, alreadyPresent: string) {
  if (content.includes(alreadyPresent)) return content;
  if (!content.includes(marker)) return content;
  return content.replace(marker, `${marker}${snippet}`);
}

async function writeFileIfChanged(filePath: string, content: string) {
  const existing = (await fs.pathExists(filePath))
    ? await fs.readFile(filePath, "utf-8")
    : undefined;
  if (existing === content) return;
  await fs.ensureDir(path.dirname(filePath));
  await fs.writeFile(filePath, content);
}

async function updateFileIfExists(filePath: string, update: (content: string) => string) {
  if (!(await fs.pathExists(filePath))) return;
  const content = await fs.readFile(filePath, "utf-8");
  const nextContent = update(content);
  if (nextContent !== content) {
    await fs.writeFile(filePath, nextContent);
  }
}

function usesCreateAuthFactory(config: ProjectConfig) {
  return (
    config.runtime === "workers" ||
    config.serverDeploy === "cloudflare" ||
    (config.backend === "self" && config.webDeploy === "cloudflare")
  );
}

function getAuthImportLine(config: ProjectConfig) {
  return usesCreateAuthFactory(config)
    ? `import { createAuth } from "@${config.projectName}/auth";`
    : `import { auth } from "@${config.projectName}/auth";`;
}

function getAuthExpression(config: ProjectConfig) {
  return usesCreateAuthFactory(config) ? "createAuth()" : "auth";
}

function addAiSdkEvlogTelemetry(content: string, loggerExpression: string) {
  let nextContent = addNamedImport(content, "evlog/ai", [
    "createAILogger",
    "createEvlogIntegration",
  ]);

  if (!nextContent.includes("const ai = createAILogger(")) {
    nextContent = nextContent.replace(
      /^(\s*)const model = wrapLanguageModel\({/m,
      (_match, indent: string) =>
        `${indent}const ai = createAILogger(${loggerExpression});\n${indent}const model = wrapLanguageModel({`,
    );
  }

  if (!nextContent.includes("model: ai.wrap(model)")) {
    nextContent = nextContent.replace(
      /(const result = streamText\({\n\s*)model,/,
      "$1model: ai.wrap(model),",
    );
  }

  if (!nextContent.includes("createEvlogIntegration(ai)")) {
    nextContent = nextContent.replace(
      /(messages:\s*await convertToModelMessages\([^)]+\),?)/,
      (match) =>
        `${match.endsWith(",") ? match : `${match},`}\n\t\texperimental_telemetry: {\n\t\t\tisEnabled: true,\n\t\t\tintegrations: [createEvlogIntegration(ai)],\n\t\t},`,
    );
  }

  return nextContent;
}

function addEvlogBetterAuthServerSetup(
  content: string,
  backend: EvlogBackend,
  authExpression: string,
) {
  let nextContent = addNamedImport(content, "evlog/better-auth", [
    "createAuthMiddleware",
    "type BetterAuthInstance",
  ]);
  const usesAuthFactory = authExpression.endsWith("()");
  const evlogAuthExpression = `${authExpression} as BetterAuthInstance`;
  const authOptions = '{ exclude: ["/api/auth/**"], maskEmail: true }';
  const identifySnippet = usesAuthFactory
    ? ""
    : `const identifyUser = createAuthMiddleware(${evlogAuthExpression}, ${authOptions});\n\n`;
  const identifyUserSetup = usesAuthFactory
    ? `\n\tconst identifyUser = createAuthMiddleware(${evlogAuthExpression}, ${authOptions});`
    : "";

  if (backend === "hono") {
    nextContent = insertBeforeOnce(
      nextContent,
      "const app = new Hono",
      identifySnippet,
      "createAuthMiddleware(",
    );
    return insertAfterOnce(
      nextContent,
      "app.use(evlog());",
      `\napp.use("*", async (c, next) => {${identifyUserSetup}\n\tawait identifyUser(c.get("log"), c.req.raw.headers, c.req.path);\n\tawait next();\n});`,
      'identifyUser(c.get("log")',
    );
  }

  if (backend === "express") {
    nextContent = insertBeforeOnce(
      nextContent,
      "const app = express();",
      identifySnippet,
      "createAuthMiddleware(",
    );
    return insertAfterOnce(
      nextContent,
      "app.use(evlog());",
      `\napp.use(async (req, _res, next) => {${identifyUserSetup}\n\tawait identifyUser(req.log, req.headers, req.path);\n\tnext();\n});`,
      "identifyUser(req.log",
    );
  }

  if (backend === "fastify") {
    nextContent = addNamedImport(nextContent, "evlog/fastify", ["useLogger"]);
    nextContent = insertBeforeOnce(
      nextContent,
      "const fastify = Fastify",
      identifySnippet,
      "createAuthMiddleware(",
    );
    return insertAfterOnce(
      nextContent,
      "fastify.register(evlog);",
      `\nfastify.addHook("preHandler", async (request) => {${identifyUserSetup}\n\tawait identifyUser(useLogger(), request.headers, request.url);\n});`,
      "identifyUser(useLogger()",
    );
  }

  nextContent = insertBeforeOnce(
    nextContent,
    "new Elysia",
    identifySnippet,
    "createAuthMiddleware(",
  );
  return insertAfterOnce(
    nextContent,
    ".use(evlog())",
    `\n\t.derive(async ({ request, log }) => {${identifyUserSetup.replace(/\n\t/g, "\n\t\t")}\n\t\tawait identifyUser(log, request.headers, new URL(request.url).pathname);\n\t\treturn {};\n\t})`,
    "identifyUser(log",
  );
}

export function addEvlogServerSetup(content: string, backend: EvlogBackend, serviceName: string) {
  const initSnippet = `initLogger({\n\tenv: { service: "${serviceName}" },\n});\n\n`;

  if (backend === "hono") {
    let nextContent = prependMissingImports(content, [
      'import { initLogger } from "evlog";',
      'import { evlog, type EvlogVariables } from "evlog/hono";',
    ]);
    nextContent = insertBeforeOnce(
      nextContent,
      "const app = new Hono",
      initSnippet,
      "initLogger({",
    );
    nextContent = nextContent.replace(
      "const app = new Hono();",
      "const app = new Hono<EvlogVariables>();",
    );
    nextContent = nextContent
      .replace('import { logger } from "hono/logger";\n', "")
      .replace(/\napp\.use\(logger\(\)\);/, "");
    return insertAfterOnce(
      nextContent,
      "const app = new Hono<EvlogVariables>();",
      "\n\napp.use(evlog());",
      "app.use(evlog());",
    );
  }

  if (backend === "express") {
    let nextContent = prependMissingImports(content, [
      'import { initLogger } from "evlog";',
      'import { evlog } from "evlog/express";',
    ]);
    nextContent = insertBeforeOnce(
      nextContent,
      "const app = express();",
      initSnippet,
      "initLogger({",
    );
    return insertAfterOnce(
      nextContent,
      "const app = express();",
      "\n\napp.use(evlog());",
      "app.use(evlog());",
    );
  }

  if (backend === "fastify") {
    let nextContent = prependMissingImports(content, [
      'import { initLogger } from "evlog";',
      'import { evlog } from "evlog/fastify";',
    ]);
    nextContent = insertBeforeOnce(
      nextContent,
      "const fastify = Fastify",
      initSnippet,
      "initLogger({",
    );
    return insertBeforeOnce(
      nextContent,
      "fastify.register(fastifyCors",
      "fastify.register(evlog);\n",
      "fastify.register(evlog);",
    );
  }

  let nextContent = prependMissingImports(content, [
    'import { initLogger } from "evlog";',
    'import { evlog } from "evlog/elysia";',
  ]);
  nextContent = insertBeforeOnce(nextContent, "new Elysia", initSnippet, "initLogger({");
  for (const marker of ["new Elysia({ adapter: node() })", "new Elysia()"]) {
    nextContent = insertAfterOnce(nextContent, marker, "\n\t.use(evlog())", ".use(evlog())");
  }
  return nextContent;
}

function addNuxtEvlogSetup(content: string, serviceName: string) {
  let nextContent = content;
  if (!nextContent.includes('"evlog/nuxt"') && !nextContent.includes("'evlog/nuxt'")) {
    nextContent = nextContent.replace(/modules:\s*\[/, (match) => `${match}\n    "evlog/nuxt",`);
  }

  if (!nextContent.includes("evlog:")) {
    nextContent = nextContent.replace(/\n\}\)\s*$/, (match) => {
      const contentBeforeConfigClose = nextContent.slice(0, -match.length);
      const needsComma = !/[,{]\s*$/.test(contentBeforeConfigClose);
      return `${needsComma ? "," : ""}\n  evlog: {\n    env: { service: "${serviceName}" },\n  },\n})`;
    });
  }

  return nextContent;
}

function addSvelteViteEvlogSetup(content: string, serviceName: string) {
  let nextContent = prependMissingImports(content, ['import evlog from "evlog/vite";']);
  if (nextContent.includes("evlog({")) return nextContent;

  return nextContent.replace(
    "plugins: [tailwindcss(), sveltekit()],",
    `plugins: [\n    tailwindcss(),\n    sveltekit(),\n    evlog({ service: "${serviceName}" }),\n  ],`,
  );
}

function addSvelteHooksEvlogSetup(content: string) {
  let nextContent = prependMissingImports(content, [
    'import { createEvlogHooks } from "evlog/sveltekit";',
  ]);

  if (!nextContent.includes("export const handle") && !nextContent.includes("const authHandle")) {
    if (!nextContent.includes("createEvlogHooks()")) {
      nextContent = `${nextContent.trimEnd()}\n\nexport const { handle, handleError } = createEvlogHooks();\n`;
    }
    return nextContent;
  }

  nextContent = prependMissingImports(nextContent, [
    'import { sequence } from "@sveltejs/kit/hooks";',
  ]);
  if (!nextContent.includes("const { handle: evlogHandle, handleError }")) {
    nextContent = nextContent.replace(
      /((?:import .+\n)+)/,
      `$1\nconst { handle: evlogHandle, handleError } = createEvlogHooks();\n\n`,
    );
  }
  nextContent = nextContent.replace(
    /export const handle(:\s*Handle)?\s*=\s*async/,
    (_match, typeAnnotation: string | undefined) =>
      `const authHandle${typeAnnotation ?? ""} = async`,
  );

  if (!nextContent.includes("sequence(evlogHandle, authHandle)")) {
    nextContent = `${nextContent.trimEnd()}\n\nexport const handle = sequence(evlogHandle as Handle, authHandle);\nexport { handleError };\n`;
  }

  return nextContent;
}

function addSvelteLocalsType(content: string) {
  let nextContent = prependMissingImports(content, ['import type { RequestLogger } from "evlog";']);

  if (nextContent.includes("log: RequestLogger")) return nextContent;

  if (nextContent.includes("// interface Locals {}")) {
    return nextContent.replace(
      "// interface Locals {}",
      "interface Locals {\n\t\t\tlog: RequestLogger;\n\t\t}",
    );
  }

  return nextContent.replace(
    "namespace App {",
    "namespace App {\n\t\tinterface Locals {\n\t\t\tlog: RequestLogger;\n\t\t}\n",
  );
}

function addTanstackStartRootEvlogSetup(content: string) {
  let nextContent = prependMissingImports(content, [
    'import { createMiddleware } from "@tanstack/react-start";',
    'import { evlogErrorHandler } from "evlog/nitro/v3";',
  ]);

  const middlewareEntry = "createMiddleware().server(evlogErrorHandler)";
  if (nextContent.includes(`middleware: [${middlewareEntry}]`)) {
    return nextContent;
  }

  if (nextContent.includes("middleware: [")) {
    return nextContent.replace("middleware: [", `middleware: [${middlewareEntry}, `);
  }

  if (/server:\s*{/.test(nextContent)) {
    return nextContent.replace(
      /server:\s*{\n/,
      `server: {\n    middleware: [${middlewareEntry}],\n`,
    );
  }

  return nextContent.replace(
    "head: () => ({",
    `server: {\n    middleware: [${middlewareEntry}],\n  },\n\n  head: () => ({`,
  );
}

function addAstroMiddlewareEvlogSetup(content: string, serviceName: string) {
  let nextContent = prependMissingImports(content, [
    'import { createRequestLogger, initLogger } from "evlog";',
  ]);
  const initSnippet = `initLogger({\n  env: { service: "${serviceName}" },\n});\n\n`;

  nextContent = insertBeforeOnce(
    nextContent,
    "export const onRequest",
    initSnippet,
    "initLogger({",
  );

  if (nextContent.includes("createRequestLogger({")) return nextContent;

  const contextMarker = "export const onRequest = defineMiddleware(async (context, next) => {";
  if (nextContent.includes(contextMarker)) {
    nextContent = insertAfterOnce(
      nextContent,
      contextMarker,
      `\n  const url = new URL(context.request.url);\n  const log = createRequestLogger({\n    method: context.request.method,\n    path: url.pathname,\n  });\n\n  context.locals.log = log;\n`,
      "const log = createRequestLogger({",
    );

    return nextContent.replace(
      "return next();",
      "const response = await next();\n  log.emit();\n  return response;",
    );
  }

  const localsMarker =
    "export const onRequest = defineMiddleware(async ({ request, locals }, next) => {";
  if (nextContent.includes(localsMarker)) {
    nextContent = insertAfterOnce(
      nextContent,
      localsMarker,
      `\n  const url = new URL(request.url);\n  const log = createRequestLogger({\n    method: request.method,\n    path: url.pathname,\n  });\n\n  locals.log = log;\n`,
      "const log = createRequestLogger({",
    );

    return nextContent.replace(
      "return next();",
      "const response = await next();\n  log.emit();\n  return response;",
    );
  }

  return nextContent;
}

function addAstroLocalsType(content: string) {
  let nextContent = prependMissingImports(content, ['import type { RequestLogger } from "evlog";']);

  if (nextContent.includes("log: RequestLogger")) return nextContent;

  if (nextContent.includes("interface Locals {")) {
    return nextContent.replace("interface Locals {", "interface Locals {\n    log: RequestLogger;");
  }

  if (nextContent.includes("declare namespace App {")) {
    return nextContent.replace(
      "declare namespace App {",
      "declare namespace App {\n  interface Locals {\n    log: RequestLogger;\n  }\n",
    );
  }

  return `${nextContent.trimEnd()}\n\ndeclare namespace App {\n  interface Locals {\n    log: RequestLogger;\n  }\n}\n`;
}

function addNextRouteWrappers(content: string) {
  let nextContent = prependMissingImports(content, ['import { withEvlog } from "@/lib/evlog";']);
  if (
    nextContent.includes("withEvlog(handler)") ||
    nextContent.includes("withEvlog(handleRequest)")
  ) {
    return nextContent;
  }

  nextContent = nextContent.replace(
    "export { handler as GET, handler as POST };",
    "export const GET = withEvlog(handler);\nexport const POST = withEvlog(handler);",
  );

  for (const method of ["GET", "POST", "PUT", "PATCH", "DELETE"]) {
    nextContent = nextContent.replace(
      `export const ${method} = handleRequest;`,
      `export const ${method} = withEvlog(handleRequest);`,
    );
  }

  return nextContent;
}

function addNextAiEvlogSetup(content: string) {
  let nextContent = addNamedImport(content, "@/lib/evlog", ["withEvlog"]);

  if (!nextContent.includes("withEvlog(async (req: Request)")) {
    nextContent = nextContent.replace(
      "export async function POST(req: Request) {",
      "export const POST = withEvlog(async (req: Request) => {",
    );
    if (nextContent.includes("export const POST = withEvlog(async (req: Request) => {")) {
      nextContent = nextContent.replace(/\n}\s*$/, "\n});\n");
    }
  }

  // Next emits the evlog route event when the streaming Response is returned.
  // AI SDK stream telemetry arrives later, so wiring createAILogger here drops `ai`.
  return nextContent;
}

function addNuxtAiEvlogSetup(content: string) {
  return addAiSdkEvlogTelemetry(content, "useLogger(event)");
}

function addSvelteAiEvlogSetup(content: string) {
  let nextContent = content.replace(
    "export const POST: RequestHandler = async ({ request }) => {",
    "export const POST: RequestHandler = async ({ request, locals }) => {",
  );

  return addAiSdkEvlogTelemetry(nextContent, "locals.log");
}

function addTanstackStartAiEvlogSetup(content: string) {
  let nextContent = prependMissingImports(content, [
    'import type { RequestLogger } from "evlog";',
    'import { useRequest } from "nitro/context";',
  ]);

  return addAiSdkEvlogTelemetry(nextContent, "useRequest().context.log as RequestLogger");
}

function addBackendAiEvlogSetup(content: string, backend: EvlogBackend) {
  if (backend === "hono") {
    return addAiSdkEvlogTelemetry(content, 'c.get("log")');
  }

  if (backend === "express") {
    return addAiSdkEvlogTelemetry(content, "req.log");
  }

  if (backend === "fastify") {
    const nextContent = addNamedImport(content, "evlog/fastify", ["useLogger"]);
    return addAiSdkEvlogTelemetry(nextContent, "useLogger()");
  }

  return addAiSdkEvlogTelemetry(content, "context.log");
}

function addNextBetterAuthToRoute(content: string) {
  let nextContent = addNamedImport(content, "@/lib/evlog-auth", ["identifyEvlogUser"]);

  nextContent = nextContent.replace("function handler(req:", "async function handler(req:");

  for (const marker of [
    "async function handler(req: NextRequest) {",
    "async function handleRequest(req: NextRequest) {",
    "export const POST = withEvlog(async (req: Request) => {",
  ]) {
    nextContent = insertAfterOnce(
      nextContent,
      marker,
      "\n\tawait identifyEvlogUser(req);",
      "identifyEvlogUser(req)",
    );
  }

  return nextContent;
}

function addSvelteBetterAuthEvlogSetup(content: string, config: ProjectConfig) {
  if (!content.includes("authHandle") || content.includes("evlogAuthHandle")) {
    return content;
  }

  let nextContent = addNamedImport(content, "evlog/better-auth", [
    "createAuthMiddleware",
    "type BetterAuthInstance",
  ]);
  if (!nextContent.includes(`@${config.projectName}/auth`)) {
    nextContent = prependMissingImports(nextContent, [getAuthImportLine(config)]);
  }
  if (
    usesCreateAuthFactory(config) &&
    config.webDeploy === "cloudflare" &&
    !nextContent.includes(`@${config.projectName}/env/server`)
  ) {
    nextContent = prependMissingImports(nextContent, [
      `import { env as localEnv } from "@${config.projectName}/env/server";`,
    ]);
  }
  const authExpression = getAuthExpression(config);
  const authOptions = '{ exclude: ["/api/auth/**"], maskEmail: true }';
  const authHandleSnippet =
    usesCreateAuthFactory(config) && config.webDeploy === "cloudflare"
      ? `const evlogAuthHandle: Handle = async ({ event, resolve }) => {\n\tif (building) {\n\t\treturn resolve(event);\n\t}\n\n\tconst authEnv = event.platform?.env ?? localEnv;\n\tconst identifyUser = createAuthMiddleware(createAuth(authEnv) as BetterAuthInstance, ${authOptions});\n\tawait identifyUser(event.locals.log, event.request.headers, event.url.pathname);\n\treturn resolve(event);\n};\n\n`
      : `const identifyUser = createAuthMiddleware(${authExpression} as BetterAuthInstance, ${authOptions});\n\nconst evlogAuthHandle: Handle = async ({ event, resolve }) => {\n\tawait identifyUser(event.locals.log, event.request.headers, event.url.pathname);\n\treturn resolve(event);\n};\n\n`;

  nextContent = insertAfterOnce(
    nextContent,
    "const { handle: evlogHandle, handleError } = createEvlogHooks();\n\n",
    authHandleSnippet,
    "evlogAuthHandle",
  );

  return nextContent
    .replace(
      "sequence(evlogHandle as Handle, authHandle)",
      "sequence(evlogHandle as Handle, evlogAuthHandle, authHandle)",
    )
    .replace(
      "sequence(evlogHandle, authHandle)",
      "sequence(evlogHandle as Handle, evlogAuthHandle, authHandle)",
    );
}

function addAstroBetterAuthEvlogSetup(content: string, config: ProjectConfig) {
  if (content.includes("createAuthMiddleware(")) return content;

  let nextContent = addNamedImport(content, "evlog/better-auth", [
    "createAuthMiddleware",
    "type BetterAuthInstance",
  ]);
  if (!nextContent.includes(`@${config.projectName}/auth`)) {
    nextContent = prependMissingImports(nextContent, [getAuthImportLine(config)]);
  }
  const authExpression = getAuthExpression(config);
  const authOptions = '{ exclude: ["/api/auth/**"], maskEmail: true }';
  const usesFactory = usesCreateAuthFactory(config);
  if (!usesFactory) {
    nextContent = insertBeforeOnce(
      nextContent,
      "export const onRequest",
      `const identifyUser = createAuthMiddleware(${authExpression} as BetterAuthInstance, ${authOptions});\n\n`,
      "const identifyUser = createAuthMiddleware(",
    );
  }

  for (const marker of ["context.locals.log = log;", "locals.log = log;"]) {
    if (!nextContent.includes(marker)) continue;

    const requestExpression = marker.startsWith("context") ? "context.request" : "request";
    const identifySnippet = usesFactory
      ? `\n\n  const identifyUser = createAuthMiddleware(${authExpression} as BetterAuthInstance, ${authOptions});\n  await identifyUser(log, ${requestExpression}.headers, url.pathname);`
      : `\n\n  await identifyUser(log, ${requestExpression}.headers, url.pathname);`;

    return insertAfterOnce(nextContent, marker, identifySnippet, "identifyUser(log");
  }

  return nextContent;
}

function getNextEvlogFile(serviceName: string) {
  return `import { createEvlog } from "evlog/next";
import { createInstrumentation } from "evlog/next/instrumentation";

export const { withEvlog, useLogger, log, createError } = createEvlog({
  service: "${serviceName}",
});

export const { register, onRequestError } = createInstrumentation({
  service: "${serviceName}",
});
`;
}

function getNextInstrumentationFile() {
  return `import { defineNodeInstrumentation } from "evlog/next/instrumentation";

export const { register, onRequestError } = defineNodeInstrumentation(() => import("./src/lib/evlog"));
`;
}

function getNextProxyFile() {
  return `import { evlogMiddleware } from "evlog/next";

export const proxy = evlogMiddleware();

export const config = {
  matcher: ["/api/:path*"],
};
`;
}

function getNextEvlogAuthFile(config: ProjectConfig) {
  if (usesCreateAuthFactory(config)) {
    return `${getAuthImportLine(config)}
import { createAuthMiddleware, type BetterAuthInstance } from "evlog/better-auth";
import { useLogger } from "@/lib/evlog";

export async function identifyEvlogUser(request: Request) {
  const identifyUser = createAuthMiddleware(${getAuthExpression(config)} as BetterAuthInstance, {
    exclude: ["/api/auth/**"],
    maskEmail: true,
  });
  await identifyUser(useLogger(), request.headers, new URL(request.url).pathname);
}
`;
  }

  return `${getAuthImportLine(config)}
import { createAuthMiddleware, type BetterAuthInstance } from "evlog/better-auth";
import { useLogger } from "@/lib/evlog";

const identifyUser = createAuthMiddleware(${getAuthExpression(config)} as BetterAuthInstance, {
  exclude: ["/api/auth/**"],
  maskEmail: true,
});

export async function identifyEvlogUser(request: Request) {
  await identifyUser(useLogger(), request.headers, new URL(request.url).pathname);
}
`;
}

function getNitroEvlogAuthPluginFile(config: ProjectConfig) {
  if (usesCreateAuthFactory(config)) {
    return `${getAuthImportLine(config)}
import { createAuthIdentifier, type BetterAuthInstance } from "evlog/better-auth";

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook("request", async (event) => {
    const identify = createAuthIdentifier(${getAuthExpression(config)} as BetterAuthInstance, {
      exclude: ["/api/auth/**"],
      maskEmail: true,
    });
    await identify(event);
  });
});
`;
  }

  return `${getAuthImportLine(config)}
import { createAuthIdentifier, type BetterAuthInstance } from "evlog/better-auth";

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook(
    "request",
    createAuthIdentifier(${getAuthExpression(config)} as BetterAuthInstance, {
      exclude: ["/api/auth/**"],
      maskEmail: true,
    }),
  );
});
`;
}

function getNuxtEvlogAuthMiddlewareFile(config: ProjectConfig) {
  if (usesCreateAuthFactory(config)) {
    return `${getAuthImportLine(config)}
import { createAuthMiddleware, type BetterAuthInstance } from "evlog/better-auth";

export default defineEventHandler(async (event) => {
  if (!event.context.log) return;
  const identify = createAuthMiddleware(${getAuthExpression(config)} as BetterAuthInstance, {
    exclude: ["/api/auth/**"],
    maskEmail: true,
  });
  await identify(event.context.log, event.headers, event.path);
});
`;
  }

  return `${getAuthImportLine(config)}
import { createAuthMiddleware, type BetterAuthInstance } from "evlog/better-auth";

const identify = createAuthMiddleware(${getAuthExpression(config)} as BetterAuthInstance, {
  exclude: ["/api/auth/**"],
  maskEmail: true,
});

export default defineEventHandler(async (event) => {
  if (!event.context.log) return;
  await identify(event.context.log, event.headers, event.path);
});
`;
}

function getTanstackNitroConfigFile(serviceName: string) {
  return `import { defineConfig } from "nitro";
import evlog from "evlog/nitro/v3";

export default defineConfig({
  experimental: {
    asyncContext: true,
  },
  modules: [
    evlog({
      env: { service: "${serviceName}" },
    }),
  ],
});
`;
}

function getAstroMiddlewareFile(serviceName: string) {
  return `import { defineMiddleware } from "astro:middleware";
import { createRequestLogger, initLogger } from "evlog";

initLogger({
  env: { service: "${serviceName}" },
});

export const onRequest = defineMiddleware(async ({ request, locals }, next) => {
  const url = new URL(request.url);
  const log = createRequestLogger({
    method: request.method,
    path: url.pathname,
  });

  locals.log = log;

  try {
    const response = await next();
    log.emit();
    return response;
  } catch (error) {
    log.error(error instanceof Error ? error : new Error(String(error)));
    log.emit();
    throw error;
  }
});
`;
}

function getAstroEnvFile() {
  return `/// <reference types="astro/client" />

import type { RequestLogger } from "evlog";

declare namespace App {
  interface Locals {
    log: RequestLogger;
  }
}
`;
}

async function setupNextEvlog(config: ProjectConfig, serviceName: string) {
  const webDir = path.join(config.projectDir, "apps/web");

  const evlogPath = path.join(webDir, "src/lib/evlog.ts");
  if (!(await fs.pathExists(evlogPath))) {
    await writeFileIfChanged(evlogPath, getNextEvlogFile(serviceName));
  }

  const identifyWebAuth = shouldIdentifyWebAuth(config);

  if (identifyWebAuth) {
    const evlogAuthPath = path.join(webDir, "src/lib/evlog-auth.ts");
    if (!(await fs.pathExists(evlogAuthPath))) {
      await writeFileIfChanged(evlogAuthPath, getNextEvlogAuthFile(config));
    }
  }

  const instrumentationPath = path.join(webDir, "instrumentation.ts");
  if (!(await fs.pathExists(instrumentationPath))) {
    await writeFileIfChanged(instrumentationPath, getNextInstrumentationFile());
  }

  const proxyPath = path.join(webDir, "src/proxy.ts");
  const rootProxyPath = path.join(webDir, "proxy.ts");
  if (!(await fs.pathExists(proxyPath)) && !(await fs.pathExists(rootProxyPath))) {
    await writeFileIfChanged(proxyPath, getNextProxyFile());
  }

  const updateNextApiRoute = (content: string) => {
    let nextContent = addNextRouteWrappers(content);
    if (identifyWebAuth) {
      nextContent = addNextBetterAuthToRoute(nextContent);
    }
    return nextContent;
  };

  await updateFileIfExists(
    path.join(webDir, "src/app/api/trpc/[trpc]/route.ts"),
    updateNextApiRoute,
  );
  await updateFileIfExists(
    path.join(webDir, "src/app/api/rpc/[[...rest]]/route.ts"),
    updateNextApiRoute,
  );

  if (config.examples.includes("ai")) {
    await updateFileIfExists(path.join(webDir, "src/app/api/ai/route.ts"), (content) => {
      let nextContent = addNextAiEvlogSetup(content);
      if (identifyWebAuth) {
        nextContent = addNextBetterAuthToRoute(nextContent);
      }
      return nextContent;
    });
  }
}

async function setupNuxtEvlog(config: ProjectConfig, serviceName: string) {
  const webDir = path.join(config.projectDir, "apps/web");
  await updateFileIfExists(path.join(webDir, "nuxt.config.ts"), (content) =>
    addNuxtEvlogSetup(content, serviceName),
  );

  if (shouldIdentifyWebAuth(config)) {
    const oldAuthPluginPath = path.join(webDir, "server/plugins/evlog-auth.ts");
    if (await fs.pathExists(oldAuthPluginPath)) {
      const oldAuthPlugin = await fs.readFile(oldAuthPluginPath, "utf-8");
      if (oldAuthPlugin.includes("evlog/better-auth")) {
        await fs.remove(oldAuthPluginPath);
      }
    }

    const authMiddlewarePath = path.join(webDir, "server/middleware/evlog-auth.ts");
    if (!(await fs.pathExists(authMiddlewarePath))) {
      await writeFileIfChanged(authMiddlewarePath, getNuxtEvlogAuthMiddlewareFile(config));
    }
  }

  if (config.examples.includes("ai")) {
    await updateFileIfExists(path.join(webDir, "server/api/ai.post.ts"), addNuxtAiEvlogSetup);
  }
}

async function setupSvelteEvlog(config: ProjectConfig, serviceName: string) {
  const webDir = path.join(config.projectDir, "apps/web");
  await updateFileIfExists(path.join(webDir, "vite.config.ts"), (content) =>
    addSvelteViteEvlogSetup(content, serviceName),
  );

  const hooksPath = path.join(webDir, "src/hooks.server.ts");
  if (await fs.pathExists(hooksPath)) {
    await updateFileIfExists(hooksPath, addSvelteHooksEvlogSetup);
  } else {
    await writeFileIfChanged(
      hooksPath,
      `import { createEvlogHooks } from "evlog/sveltekit";

export const { handle, handleError } = createEvlogHooks();
`,
    );
  }

  await updateFileIfExists(path.join(webDir, "src/app.d.ts"), addSvelteLocalsType);

  if (shouldIdentifyWebAuth(config)) {
    await updateFileIfExists(path.join(webDir, "src/hooks.server.ts"), (content) =>
      addSvelteBetterAuthEvlogSetup(content, config),
    );
  }

  if (config.examples.includes("ai")) {
    await updateFileIfExists(
      path.join(webDir, "src/routes/api/ai/+server.ts"),
      addSvelteAiEvlogSetup,
    );
  }
}

async function setupTanstackStartEvlog(config: ProjectConfig, serviceName: string) {
  const webDir = path.join(config.projectDir, "apps/web");
  const nitroConfigPath = path.join(webDir, "nitro.config.ts");
  if (!(await fs.pathExists(nitroConfigPath))) {
    await writeFileIfChanged(nitroConfigPath, getTanstackNitroConfigFile(serviceName));
  }
  await updateFileIfExists(
    path.join(webDir, "src/routes/__root.tsx"),
    addTanstackStartRootEvlogSetup,
  );

  if (shouldIdentifyWebAuth(config)) {
    const authPluginPath = path.join(webDir, "server/plugins/evlog-auth.ts");
    if (!(await fs.pathExists(authPluginPath))) {
      await writeFileIfChanged(authPluginPath, getNitroEvlogAuthPluginFile(config));
    }
  }

  if (config.examples.includes("ai")) {
    await updateFileIfExists(
      path.join(webDir, "src/routes/api/ai/$.ts"),
      addTanstackStartAiEvlogSetup,
    );
  }
}

async function setupAstroEvlog(config: ProjectConfig, serviceName: string) {
  const webDir = path.join(config.projectDir, "apps/web");
  const middlewarePath = path.join(webDir, "src/middleware.ts");
  if (!(await fs.pathExists(middlewarePath))) {
    await writeFileIfChanged(middlewarePath, getAstroMiddlewareFile(serviceName));
  } else {
    await updateFileIfExists(middlewarePath, (content) =>
      addAstroMiddlewareEvlogSetup(content, serviceName),
    );
  }

  const envPath = path.join(webDir, "src/env.d.ts");
  if (!(await fs.pathExists(envPath))) {
    await writeFileIfChanged(envPath, getAstroEnvFile());
  } else {
    await updateFileIfExists(envPath, addAstroLocalsType);
  }

  if (shouldIdentifyWebAuth(config)) {
    await updateFileIfExists(middlewarePath, (content) =>
      addAstroBetterAuthEvlogSetup(content, config),
    );
  }
}

async function setupEvlogWeb(config: ProjectConfig) {
  const frontend = getEvlogWebFrontend(config.frontend);
  if (!frontend) return;

  const serviceName = `${config.projectName}-web`;

  if (frontend === "next") {
    await setupNextEvlog(config, serviceName);
  } else if (frontend === "nuxt") {
    await setupNuxtEvlog(config, serviceName);
  } else if (frontend === "svelte") {
    await setupSvelteEvlog(config, serviceName);
  } else if (frontend === "tanstack-start") {
    await setupTanstackStartEvlog(config, serviceName);
  } else if (frontend === "astro") {
    await setupAstroEvlog(config, serviceName);
  }
}

export async function setupEvlog(config: ProjectConfig): Promise<Result<void, AddonSetupError>> {
  return Result.tryPromise({
    try: async () => {
      if (isEvlogBackend(config.backend)) {
        const serverIndexPath = path.join(config.projectDir, "apps/server/src/index.ts");
        if (await fs.pathExists(serverIndexPath)) {
          const content = await fs.readFile(serverIndexPath, "utf-8");
          let nextContent = addEvlogServerSetup(
            content,
            config.backend,
            `${config.projectName}-server`,
          );

          if (config.auth === "better-auth") {
            nextContent = addEvlogBetterAuthServerSetup(
              nextContent,
              config.backend,
              getAuthExpression(config),
            );
          }

          if (config.examples.includes("ai")) {
            nextContent = addBackendAiEvlogSetup(nextContent, config.backend);
          }

          if (nextContent !== content) {
            await fs.writeFile(serverIndexPath, nextContent);
          }
        }
      }

      await setupEvlogWeb(config);
    },
    catch: (error) =>
      new AddonSetupError({
        addon: "evlog",
        message: `Failed to set up evlog: ${error instanceof Error ? error.message : String(error)}`,
        cause: error,
      }),
  });
}


================================================
FILE: apps/cli/src/helpers/addons/fumadocs-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";

import { navigableSelect } from "../../prompts/navigable";
import { navigableGroup } from "../../prompts/navigable-group";
import type { ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError, userCancelled } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionArgs } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type FumadocsTemplate =
  | "next-mdx"
  | "next-mdx-static"
  | "waku"
  | "react-router"
  | "react-router-spa"
  | "tanstack-start"
  | "tanstack-start-spa";

type FumadocsSearch = "orama" | "orama-cloud";
type FumadocsOgImage = "next-og" | "takumi";
type FumadocsAiChat = "openrouter" | "inkeep";

const TEMPLATES = {
  "next-mdx": {
    label: "Next.js: Fumadocs MDX",
    hint: "recommended",
    value: "+next+fuma-docs-mdx",
  },
  "next-mdx-static": {
    label: "Next.js Static: Fumadocs MDX",
    value: "+next+fuma-docs-mdx+static",
  },
  waku: {
    label: "Waku: Fumadocs MDX",
    value: "waku",
  },
  "react-router": {
    label: "React Router: Fumadocs MDX (not RSC)",
    value: "react-router",
  },
  "react-router-spa": {
    label: "React Router SPA: Fumadocs MDX (not RSC)",
    hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
    value: "react-router-spa",
  },
  "tanstack-start": {
    label: "Tanstack Start: Fumadocs MDX (not RSC)",
    value: "tanstack-start",
  },
  "tanstack-start-spa": {
    label: "Tanstack Start SPA: Fumadocs MDX (not RSC)",
    hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
    value: "tanstack-start-spa",
  },
} as const;

const DEFAULT_TEMPLATE: FumadocsTemplate = "next-mdx";
const DEFAULT_DEV_PORT = 4000;

function aiChatDisabledForTemplate(template: FumadocsTemplate): boolean {
  return template === "next-mdx-static" || template.endsWith("-spa");
}

export async function setupFumadocs(
  config: ProjectConfig,
): Promise<Result<void, AddonSetupError | UserCancelledError>> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;

  cliLog.info("Setting up Fumadocs...");

  const configuredOptions = config.addonOptions?.fumadocs;

  let template = configuredOptions?.template;
  let search: FumadocsSearch | undefined = configuredOptions?.search;
  let ogImage: FumadocsOgImage | undefined = configuredOptions?.ogImage;
  let aiChat: FumadocsAiChat | undefined = configuredOptions?.aiChat;

  if (isSilent()) {
    template = template ?? DEFAULT_TEMPLATE;
  } else {
    const promptResult = await Result.tryPromise({
      try: () =>
        navigableGroup<{
          template: FumadocsTemplate;
          search: FumadocsSearch;
          ogImage: FumadocsOgImage | "skip";
          aiChat: FumadocsAiChat | "none";
        }>({
          template: async () => {
            if (template !== undefined) return template;
            return navigableSelect<FumadocsTemplate>({
              message: "Choose a template",
              options: Object.entries(TEMPLATES).map(([key, t]) => ({
                value: key as FumadocsTemplate,
                label: t.label,
                hint: "hint" in t ? t.hint : undefined,
              })),
              initialValue: DEFAULT_TEMPLATE,
            });
          },
          search: async () => {
            if (search !== undefined) return search;
            return navigableSelect<FumadocsSearch>({
              message: "Choose a search solution?",
              options: [
                {
                  value: "orama",
                  label: "Default",
                  hint: "local search powered by Orama, recommended",
                },
                {
                  value: "orama-cloud",
                  label: "Orama Cloud",
                  hint: "3rd party search solution, signup needed",
                },
              ],
              initialValue: "orama",
            });
          },
          ogImage: async ({ results }) => {
            if (ogImage !== undefined) return ogImage;
            const picked = results.template ?? template ?? DEFAULT_TEMPLATE;
            if (!picked.startsWith("next-")) return "skip";
            return navigableSelect<FumadocsOgImage>({
              message: "Configure Open Graph Image generation?",
              options: [
                { value: "next-og", label: "next/og", hint: "Next.js built-in solution" },
                {
                  value: "takumi",
                  label: "Takumi",
                  hint: "Output WebP format, framework-agnostic",
                },
              ],
              initialValue: "next-og",
            });
          },
          aiChat: async ({ results }) => {
            if (aiChat !== undefined) return aiChat;
            const picked = results.template ?? template ?? DEFAULT_TEMPLATE;
            if (aiChatDisabledForTemplate(picked)) return "none";
            return navigableSelect<FumadocsAiChat | "none">({
              message: "Configure AI Chat?",
              options: [
                { value: "none", label: "No" },
                { value: "openrouter", label: "AI SDK", hint: "default to OpenRouter" },
                { value: "inkeep", label: "Inkeep AI", hint: "API key required" },
              ],
              initialValue: "none",
            });
          },
        }),
      catch: (e) =>
        new AddonSetupError({
          addon: "fumadocs",
          message: `Failed to run Fumadocs prompts: ${e instanceof Error ? e.message : String(e)}`,
          cause: e,
        }),
    });

    if (promptResult.isErr()) return Result.err(promptResult.error);
    const results = promptResult.value;

    // Cancel mid-group leaves later slots undefined; skip/none sentinels are defined.
    if (
      results.template === undefined ||
      results.search === undefined ||
      results.ogImage === undefined ||
      results.aiChat === undefined
    ) {
      return userCancelled("Operation cancelled");
    }

    template = results.template;
    search = results.search;
    ogImage = results.ogImage === "skip" ? undefined : results.ogImage;
    aiChat = results.aiChat === "none" ? undefined : results.aiChat;
  }

  if (!template) {
    return userCancelled("Operation cancelled");
  }

  const isNextTemplate = template.startsWith("next-");

  // Normalize pre-configured flags against the chosen template so we don't emit
  // upstream-broken combinations (AI chat on a static export, etc.).
  if (!isNextTemplate) {
    ogImage = undefined;
  }
  if (aiChatDisabledForTemplate(template)) {
    aiChat = undefined;
  }

  const templateArg = TEMPLATES[template].value;
  const devPort = configuredOptions?.devPort ?? DEFAULT_DEV_PORT;

  const options: string[] = [`--template ${templateArg}`, `--pm ${packageManager}`, "--no-git"];

  if (isNextTemplate) {
    options.push("--src");
  }

  // create-fumadocs-app's --linter flag only accepts "eslint" or "biome"
  // (oxlint exists only in the interactive prompt, not as a flag choice).
  if (config.addons.includes("biome") || config.addons.includes("ultracite")) {
    options.push("--linter biome");
  }

  if (search) options.push(`--search ${search}`);
  if (ogImage) options.push(`--og-image ${ogImage}`);
  if (aiChat) options.push(`--ai-chat ${aiChat}`);

  const commandWithArgs = `create-fumadocs-app@latest fumadocs ${options.join(" ")}`;
  const args = getPackageExecutionArgs(packageManager, commandWithArgs);

  const appsDir = path.join(projectDir, "apps");
  await fs.ensureDir(appsDir);

  const s = createSpinner();
  s.start("Running Fumadocs create command...");

  const result = await Result.tryPromise({
    try: async () => {
      await $({ cwd: appsDir, env: { CI: "true" } })`${args}`;

      const fumadocsDir = path.join(projectDir, "apps", "fumadocs");
      const packageJsonPath = path.join(fumadocsDir, "package.json");

      if (await fs.pathExists(packageJsonPath)) {
        const packageJson = await fs.readJson(packageJsonPath);
        packageJson.name = "fumadocs";

        if (packageJson.scripts?.dev) {
          packageJson.scripts.dev = `${packageJson.scripts.dev} --port=${devPort}`;
        }

        await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
      }
    },
    catch: (e) =>
      new AddonSetupError({
        addon: "fumadocs",
        message: `Failed to set up Fumadocs: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (result.isErr()) {
    s.stop("Failed to set up Fumadocs");
    return result;
  }

  s.stop("Fumadocs setup complete!");
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/mcp-setup.ts
================================================
import { Result } from "better-result";
import { $ } from "execa";
import pc from "picocolors";

import { navigableMultiselect, navigableSelect } from "../../prompts/navigable";
import { navigableGroup } from "../../prompts/navigable-group";
import type { AddonOptions, ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionCommand, getPackageRunnerPrefix } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type McpTransport = "http" | "sse";

type McpOptions = NonNullable<AddonOptions["mcp"]>;
type McpServerKey = NonNullable<McpOptions["servers"]>[number];
type McpAgent = NonNullable<McpOptions["agents"]>[number];
type InstallScope = NonNullable<McpOptions["scope"]>;

export type McpServerDef = {
  key: McpServerKey;
  label: string;
  name: string;
  target: string;
  transport?: McpTransport;
  headers?: string[];
};

type AgentScope = "project" | "global" | "both";

type AgentOption = {
  value: McpAgent;
  label: string;
  scope: AgentScope;
};

const MCP_AGENTS: AgentOption[] = [
  { value: "antigravity", label: "Antigravity", scope: "global" },
  { value: "cline", label: "Cline VSCode Extension", scope: "global" },
  { value: "cline-cli", label: "Cline CLI", scope: "global" },
  { value: "cursor", label: "Cursor", scope: "both" },
  { value: "claude-code", label: "Claude Code", scope: "both" },
  { value: "codex", label: "Codex", scope: "both" },
  { value: "opencode", label: "OpenCode", scope: "both" },
  { value: "gemini-cli", label: "Gemini CLI", scope: "both" },
  { value: "github-copilot-cli", label: "GitHub Copilot CLI", scope: "both" },
  { value: "mcporter", label: "MCPorter", scope: "both" },
  { value: "vscode", label: "VS Code (GitHub Copilot)", scope: "both" },
  { value: "zed", label: "Zed", scope: "both" },
  { value: "claude-desktop", label: "Claude Desktop", scope: "global" },
  { value: "goose", label: "Goose", scope: "global" },
];

const DEFAULT_SCOPE: InstallScope = "project";
const DEFAULT_AGENTS: McpAgent[] = ["cursor", "claude-code", "vscode"];

function uniqueValues<T>(values: T[]): T[] {
  return Array.from(new Set(values));
}

function hasReactBasedFrontend(frontend: ProjectConfig["frontend"]): boolean {
  return (
    frontend.includes("react-router") ||
    frontend.includes("tanstack-router") ||
    frontend.includes("tanstack-start") ||
    frontend.includes("next")
  );
}

function hasNativeFrontend(frontend: ProjectConfig["frontend"]): boolean {
  return (
    frontend.includes("native-bare") ||
    frontend.includes("native-uniwind") ||
    frontend.includes("native-unistyles")
  );
}

function getAllMcpServers(config: ProjectConfig): McpServerDef[] {
  return [
    {
      key: "better-t-stack",
      label: "Better T Stack",
      name: "better-t-stack",
      target: getPackageExecutionCommand(config.packageManager, "create-better-t-stack@latest mcp"),
    },
    {
      key: "context7",
      label: "Context7",
      name: "context7",
      target: "@upstash/context7-mcp",
    },
    {
      key: "nx",
      label: "Nx Workspace",
      name: "nx",
      target: "npx nx mcp .",
    },
    {
      key: "cloudflare-docs",
      label: "Cloudflare Docs",
      name: "cloudflare-docs",
      target: "https://docs.mcp.cloudflare.com/sse",
      transport: "sse",
    },
    {
      key: "convex",
      label: "Convex",
      name: "convex",
      target: "npx -y convex@latest mcp start",
    },
    {
      key: "shadcn",
      label: "shadcn/ui",
      name: "shadcn",
      target: "npx -y shadcn@latest mcp",
    },
    {
      key: "next-devtools",
      label: "Next Devtools",
      name: "next-devtools",
      target: "npx -y next-devtools-mcp@latest",
    },
    {
      key: "nuxt-docs",
      label: "Nuxt Docs",
      name: "nuxt",
      target: "https://nuxt.com/mcp",
    },
    {
      key: "nuxt-ui-docs",
      label: "Nuxt UI Docs",
      name: "nuxt-ui",
      target: "https://ui.nuxt.com/mcp",
    },
    {
      key: "svelte-docs",
      label: "Svelte Docs",
      name: "svelte",
      target: "https://mcp.svelte.dev/mcp",
    },
    {
      key: "astro-docs",
      label: "Astro Docs",
      name: "astro-docs",
      target: "https://mcp.docs.astro.build/mcp",
    },
    {
      key: "planetscale",
      label: "PlanetScale",
      name: "planetscale",
      target: "https://mcp.pscale.dev/mcp/planetscale",
    },
    {
      key: "neon",
      label: "Neon",
      name: "neon",
      target: "https://mcp.neon.tech/mcp",
    },
    {
      key: "supabase",
      label: "Supabase",
      name: "supabase",
      target: "https://mcp.supabase.com/mcp",
    },
    {
      key: "better-auth",
      label: "Better Auth",
      name: "better-auth",
      target: "https://mcp.inkeep.com/better-auth/mcp",
    },
    {
      key: "clerk",
      label: "Clerk",
      name: "clerk",
      target: "https://mcp.clerk.com/mcp",
    },
    {
      key: "expo",
      label: "Expo",
      name: "expo-mcp",
      target: "https://mcp.expo.dev/mcp",
    },
    {
      key: "polar",
      label: "Polar",
      name: "polar",
      target: "https://mcp.polar.sh/mcp/polar-mcp",
    },
  ];
}

export function getRecommendedMcpServers(
  config: ProjectConfig,
  scope: InstallScope,
): McpServerDef[] {
  const serversByKey = new Map(getAllMcpServers(config).map((server) => [server.key, server]));
  const recommendedServerKeys: McpServerKey[] = ["better-t-stack", "context7"];

  if (scope === "project" && config.addons.includes("nx")) {
    recommendedServerKeys.push("nx");
  }

  if (
    config.runtime === "workers" ||
    config.webDeploy === "cloudflare" ||
    config.serverDeploy === "cloudflare"
  ) {
    recommendedServerKeys.push("cloudflare-docs");
  }

  if (config.backend === "convex") {
    recommendedServerKeys.push("convex");
  }

  if (hasReactBasedFrontend(config.frontend)) {
    recommendedServerKeys.push("shadcn");
  }

  if (config.frontend.includes("next")) {
    recommendedServerKeys.push("next-devtools");
  }

  if (config.frontend.includes("nuxt")) {
    recommendedServerKeys.push("nuxt-docs", "nuxt-ui-docs");
  }

  if (config.frontend.includes("svelte")) {
    recommendedServerKeys.push("svelte-docs");
  }

  if (config.frontend.includes("astro")) {
    recommendedServerKeys.push("astro-docs");
  }

  if (config.dbSetup === "planetscale") {
    recommendedServerKeys.push("planetscale");
  }

  if (config.dbSetup === "neon") {
    recommendedServerKeys.push("neon");
  }

  if (config.dbSetup === "supabase") {
    recommendedServerKeys.push("supabase");
  }

  if (config.auth === "better-auth") {
    recommendedServerKeys.push("better-auth");
  }

  if (config.auth === "clerk") {
    recommendedServerKeys.push("clerk");
  }

  if (hasNativeFrontend(config.frontend)) {
    recommendedServerKeys.push("expo");
  }

  if (config.payments === "polar") {
    recommendedServerKeys.push("polar");
  }

  return uniqueValues(recommendedServerKeys)
    .map((serverKey) => serversByKey.get(serverKey))
    .filter((server): server is McpServerDef => server !== undefined);
}

function filterAgentsForScope(scope: InstallScope): AgentOption[] {
  return MCP_AGENTS.filter((a) => a.scope === "both" || a.scope === scope);
}

export async function setupMcp(
  config: ProjectConfig,
): Promise<Result<void, AddonSetupError | UserCancelledError>> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;

  cliLog.info("Setting up MCP servers...");

  const configuredScope = config.addonOptions?.mcp?.scope;
  const configuredServerKeys = config.addonOptions?.mcp?.servers;
  const configuredAgents = config.addonOptions?.mcp?.agents;

  const allServersByKey = new Map(getAllMcpServers(config).map((server) => [server.key, server]));
  const availableServerKeys = new Set(allServersByKey.keys());

  let scope: InstallScope;
  let selectedServerKeys: McpServerKey[];
  let selectedAgents: McpAgent[];

  if (isSilent()) {
    scope = configuredScope ?? DEFAULT_SCOPE;
    const recommendedServers = getRecommendedMcpServers(config, scope);
    if (recommendedServers.length === 0) return Result.ok(undefined);
    const serverOptions = recommendedServers.map((s) => s.key);
    selectedServerKeys =
      configuredServerKeys?.filter((k) => availableServerKeys.has(k)) ?? serverOptions;
    if (selectedServerKeys.length === 0) return Result.ok(undefined);
    const agentOptions = filterAgentsForScope(scope);
    const defaultAgents = uniqueValues(
      DEFAULT_AGENTS.filter((a) => agentOptions.some((o) => o.value === a)),
    );
    selectedAgents =
      configuredAgents?.filter((a) => agentOptions.some((o) => o.value === a)) ?? defaultAgents;
    if (selectedAgents.length === 0) return Result.ok(undefined);
  } else {
    const results = await navigableGroup<{
      scope: InstallScope;
      servers: McpServerKey[];
      agents: McpAgent[];
    }>({
      scope: async () => {
        if (configuredScope !== undefined) return configuredScope;
        return navigableSelect<InstallScope>({
          message: "Where should MCP servers be installed?",
          options: [
            {
              value: "project",
              label: "Project",
              hint: "Writes to project config files (recommended for teams)",
            },
            {
              value: "global",
              label: "Global",
              hint: "Writes to user-level config files (personal machine)",
            },
          ],
          initialValue: DEFAULT_SCOPE,
        });
      },
      servers: async ({ results: r }) => {
        const currentScope = (r.scope ?? configuredScope ?? DEFAULT_SCOPE) as InstallScope;
        const recommended = getRecommendedMcpServers(config, currentScope);
        if (recommended.length === 0) return [];
        const options = recommended.map((s) => ({
          value: s.key,
          label: s.label,
          hint: s.target,
        }));
        if (configuredServerKeys !== undefined) {
          return configuredServerKeys.filter((k) => availableServerKeys.has(k));
        }
        return navigableMultiselect<McpServerKey>({
          message: "Select MCP servers to install",
          options,
          required: false,
          initialValues: options.map((o) => o.value),
        });
      },
      agents: async ({ results: r }) => {
        const currentScope = (r.scope ?? configuredScope ?? DEFAULT_SCOPE) as InstallScope;
        const currentServers = r.servers as McpServerKey[] | undefined;
        if (currentServers !== undefined && currentServers.length === 0) return [];
        const agentOpts = filterAgentsForScope(currentScope);
        if (agentOpts.length === 0) return [];
        const defaults = uniqueValues(
          DEFAULT_AGENTS.filter((a) => agentOpts.some((o) => o.value === a)),
        );
        if (configuredAgents !== undefined) {
          return configuredAgents.filter((a) => agentOpts.some((o) => o.value === a));
        }
        return navigableMultiselect<McpAgent>({
          message: "Select agents to install MCP servers to",
          options: agentOpts.map((a) => ({ value: a.value, label: a.label })),
          required: false,
          initialValues: defaults,
        });
      },
    });

    if (
      results.scope === undefined ||
      results.servers === undefined ||
      results.agents === undefined
    ) {
      return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
    }

    scope = results.scope;
    selectedServerKeys = results.servers as McpServerKey[];
    selectedAgents = results.agents as McpAgent[];

    if (selectedServerKeys.length === 0 || selectedAgents.length === 0) {
      return Result.ok(undefined);
    }
  }

  const selectedServers: McpServerDef[] = [];
  for (const key of selectedServerKeys) {
    const server = allServersByKey.get(key);
    if (server) selectedServers.push(server);
  }

  if (selectedServers.length === 0) {
    return Result.ok(undefined);
  }

  const installSpinner = createSpinner();
  installSpinner.start("Installing MCP servers...");

  const runner = getPackageRunnerPrefix(packageManager);
  const globalFlags = scope === "global" ? ["-g"] : [];
  let successfulInstalls = 0;

  for (const server of selectedServers) {
    const transportFlags = server.transport ? ["-t", server.transport] : [];
    const headerFlags = (server.headers ?? []).flatMap((h) => ["--header", h]);
    const agentFlags = selectedAgents.flatMap((agent) => ["-a", agent]);

    const args = [
      ...runner,
      "add-mcp@latest",
      server.target,
      "--name",
      server.name,
      ...transportFlags,
      ...headerFlags,
      ...agentFlags,
      ...globalFlags,
      "-y",
    ];

    const installResult = await Result.tryPromise({
      try: async () => {
        await $({ cwd: projectDir, env: { CI: "true" } })`${args}`;
      },
      catch: (e) =>
        new AddonSetupError({
          addon: "mcp",
          message: `Failed to install MCP server '${server.name}': ${e instanceof Error ? e.message : String(e)}`,
          cause: e,
        }),
    });

    if (installResult.isErr()) {
      cliLog.warn(pc.yellow(`Warning: Could not install MCP server '${server.name}'`));
      continue;
    }

    successfulInstalls += 1;
  }

  if (successfulInstalls === 0) {
    installSpinner.stop(pc.red("Failed to install MCP servers"));
    return Result.err(
      new AddonSetupError({
        addon: "mcp",
        message: `Failed to install all requested MCP servers: ${selectedServers.map((server) => server.name).join(", ")}`,
      }),
    );
  }

  installSpinner.stop(
    successfulInstalls === selectedServers.length
      ? "MCP servers installed"
      : "MCP servers installed with warnings",
  );
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/oxlint-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";

import type { PackageManager } from "../../types";
import { addPackageDependency } from "../../utils/add-package-deps";
import { AddonSetupError } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionArgs } from "../../utils/package-runner";
import { createSpinner } from "../../utils/terminal-output";

export async function setupOxlint(
  projectDir: string,
  packageManager: PackageManager,
): Promise<Result<void, AddonSetupError>> {
  return Result.tryPromise({
    try: async () => {
      await addPackageDependency({
        devDependencies: ["oxlint", "oxfmt"],
        projectDir,
      });

      const packageJsonPath = path.join(projectDir, "package.json");
      if (await fs.pathExists(packageJsonPath)) {
        const packageJson = await fs.readJson(packageJsonPath);

        packageJson.scripts = {
          ...packageJson.scripts,
          check: "oxlint && oxfmt --write",
        };

        await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
      }

      if (shouldSkipExternalCommands()) {
        return;
      }

      const s = createSpinner();

      try {
        s.start("Initializing oxlint and oxfmt...");

        const oxlintArgs = getPackageExecutionArgs(packageManager, "oxlint@latest --init");
        await $({ cwd: projectDir, env: { CI: "true" } })`${oxlintArgs}`;

        const oxfmtArgs = getPackageExecutionArgs(packageManager, "oxfmt@latest --init");
        await $({ cwd: projectDir, env: { CI: "true" } })`${oxfmtArgs}`;

        s.stop("oxlint and oxfmt initialized successfully!");
      } catch (error) {
        s.stop("Failed to initialize oxlint and oxfmt");
        throw error;
      }
    },
    catch: (error) =>
      new AddonSetupError({
        addon: "oxlint",
        message: `Failed to set up oxlint: ${error instanceof Error ? error.message : String(error)}`,
        cause: error,
      }),
  });
}


================================================
FILE: apps/cli/src/helpers/addons/skills-setup.ts
================================================
import { Result } from "better-result";
import { $ } from "execa";
import pc from "picocolors";

import { navigableMultiselect, navigableSelect } from "../../prompts/navigable";
import { navigableGroup } from "../../prompts/navigable-group";
import type { AddonOptions, ProjectConfig } from "../../types";
import { readBtsConfig } from "../../utils/bts-config";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageRunnerPrefix } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type SkillSource = {
  label: string;
};

type AgentOption = {
  value: SkillAgent;
  label: string;
};

type SkillsOptions = NonNullable<AddonOptions["skills"]>;
type SkillAgent = NonNullable<SkillsOptions["agents"]>[number];
type InstallScope = NonNullable<SkillsOptions["scope"]>;

// Skill sources - using GitHub shorthand or full URLs
const SKILL_SOURCES = {
  "vercel-labs/agent-skills": {
    label: "Vercel Agent Skills",
  },
  "vercel/ai": {
    label: "Vercel AI SDK",
  },
  "vercel/turborepo": {
    label: "Turborepo",
  },
  "yusukebe/hono-skill": {
    label: "Hono Backend",
  },
  "vercel-labs/next-skills": {
    label: "Next.js Best Practices",
  },
  "nuxt/ui": {
    label: "Nuxt UI",
  },
  "heroui-inc/heroui": {
    label: "HeroUI Native",
  },
  "shadcn/ui": {
    label: "shadcn/ui",
  },
  "better-auth/skills": {
    label: "Better Auth",
  },
  "clerk/skills": {
    label: "Clerk",
  },
  "neondatabase/agent-skills": {
    label: "Neon Database",
  },
  "supabase/agent-skills": {
    label: "Supabase",
  },
  "planetscale/database-skills": {
    label: "PlanetScale",
  },
  "expo/skills": {
    label: "Expo",
  },
  "prisma/skills": {
    label: "Prisma",
  },
  "elysiajs/skills": {
    label: "ElysiaJS",
  },
  "waynesutton/convexskills": {
    label: "Convex",
  },
  "msmps/opentui-skill": {
    label: "OpenTUI Platform",
  },
  "haydenbleasel/ultracite": {
    label: "Ultracite",
  },
  "https://www.evlog.dev": {
    label: "evlog",
  },
} satisfies Record<string, SkillSource>;

type SourceKey = keyof typeof SKILL_SOURCES;

// All available agents from add-skill CLI
const AVAILABLE_AGENTS: AgentOption[] = [
  { value: "cursor", label: "Cursor" },
  { value: "claude-code", label: "Claude Code" },
  { value: "cline", label: "Cline" },
  { value: "github-copilot", label: "GitHub Copilot" },
  { value: "codex", label: "Codex" },
  { value: "opencode", label: "OpenCode" },
  { value: "windsurf", label: "Windsurf" },
  { value: "goose", label: "Goose" },
  { value: "roo", label: "Roo Code" },
  { value: "kilo", label: "Kilo Code" },
  { value: "gemini-cli", label: "Gemini CLI" },
  { value: "antigravity", label: "Antigravity" },
  { value: "openhands", label: "OpenHands" },
  { value: "trae", label: "Trae" },
  { value: "amp", label: "Amp" },
  { value: "pi", label: "Pi" },
  { value: "qoder", label: "Qoder" },
  { value: "qwen-code", label: "Qwen Code" },
  { value: "kiro-cli", label: "Kiro CLI" },
  { value: "droid", label: "Droid" },
  { value: "command-code", label: "Command Code" },
  { value: "clawdbot", label: "Clawdbot" },
  { value: "zencoder", label: "Zencoder" },
  { value: "neovate", label: "Neovate" },
  { value: "mcpjam", label: "MCPJam" },
];

const DEFAULT_SCOPE: InstallScope = "project";
const DEFAULT_AGENTS: SkillAgent[] = ["cursor", "claude-code", "github-copilot"];

function hasReactBasedFrontend(frontend: ProjectConfig["frontend"]): boolean {
  return (
    frontend.includes("react-router") ||
    frontend.includes("tanstack-router") ||
    frontend.includes("tanstack-start") ||
    frontend.includes("next")
  );
}

function hasNativeFrontend(frontend: ProjectConfig["frontend"]): boolean {
  return (
    frontend.includes("native-bare") ||
    frontend.includes("native-uniwind") ||
    frontend.includes("native-unistyles")
  );
}

function getRecommendedSourceKeys(config: ProjectConfig): SourceKey[] {
  const sources: SourceKey[] = [];
  const { frontend, backend, dbSetup, auth, examples, addons, orm } = config;

  if (hasReactBasedFrontend(frontend)) {
    sources.push("vercel-labs/agent-skills");
    sources.push("shadcn/ui");
  }

  if (frontend.includes("next")) {
    sources.push("vercel-labs/next-skills");
  }

  if (frontend.includes("nuxt")) {
    sources.push("nuxt/ui");
  }

  if (frontend.includes("native-uniwind")) {
    sources.push("heroui-inc/heroui");
  }

  if (hasNativeFrontend(frontend)) {
    sources.push("expo/skills");
  }

  if (auth === "better-auth") {
    sources.push("better-auth/skills");
  }

  if (auth === "clerk") {
    sources.push("clerk/skills");
  }

  if (dbSetup === "neon") {
    sources.push("neondatabase/agent-skills");
  }

  if (dbSetup === "supabase") {
    sources.push("supabase/agent-skills");
  }

  if (dbSetup === "planetscale") {
    sources.push("planetscale/database-skills");
  }

  if (orm === "prisma" || dbSetup === "prisma-postgres") {
    sources.push("prisma/skills");
  }

  if (examples.includes("ai")) {
    sources.push("vercel/ai");
  }

  if (addons.includes("turborepo")) {
    sources.push("vercel/turborepo");
  }

  if (backend === "hono") {
    sources.push("yusukebe/hono-skill");
  }

  if (backend === "elysia") {
    sources.push("elysiajs/skills");
  }

  if (backend === "convex") {
    sources.push("waynesutton/convexskills");
  }

  if (addons.includes("opentui")) {
    sources.push("msmps/opentui-skill");
  }

  if (addons.includes("ultracite")) {
    sources.push("haydenbleasel/ultracite");
  }

  if (addons.includes("evlog")) {
    sources.push("https://www.evlog.dev");
  }

  return sources;
}

const CURATED_SKILLS_BY_SOURCE: Record<SourceKey, (config: ProjectConfig) => string[]> = {
  "vercel-labs/agent-skills": (config) => {
    const skills = [
      "web-design-guidelines",
      "vercel-composition-patterns",
      "vercel-react-best-practices",
    ];
    if (hasNativeFrontend(config.frontend)) {
      skills.push("vercel-react-native-skills");
    }
    return skills;
  },
  "vercel/ai": () => ["ai-sdk"],
  "vercel/turborepo": () => ["turborepo"],
  "yusukebe/hono-skill": () => ["hono"],
  "vercel-labs/next-skills": () => ["next-best-practices", "next-cache-components"],
  "nuxt/ui": () => ["nuxt-ui"],
  "heroui-inc/heroui": () => ["heroui-native"],
  "shadcn/ui": () => ["shadcn"],
  "better-auth/skills": () => ["better-auth-best-practices"],
  "clerk/skills": (config) => {
    const skills = [
      "clerk",
      "clerk-setup",
      "clerk-custom-ui",
      "clerk-webhooks",
      "clerk-testing",
      "clerk-orgs",
    ];

    if (config.frontend.includes("next")) {
      skills.push("clerk-nextjs-patterns");
    }

    return skills;
  },
  "neondatabase/agent-skills": () => ["neon-postgres"],
  "supabase/agent-skills": () => ["supabase-postgres-best-practices"],
  "planetscale/database-skills": (config) => {
    if (config.dbSetup !== "planetscale") {
      return [];
    }

    if (config.database === "postgres") {
      return ["postgres", "neki"];
    }

    if (config.database === "mysql") {
      return ["mysql", "vitess"];
    }

    return [];
  },
  "expo/skills": (config) => {
    const skills = [
      "expo-dev-client",
      "building-native-ui",
      "native-data-fetching",
      "expo-deployment",
      "expo-cicd-workflows",
    ];
    if (config.frontend.includes("native-uniwind")) {
      skills.push("expo-tailwind-setup");
    }
    return skills;
  },
  "prisma/skills": (config) => {
    const skills: string[] = [];

    if (config.orm === "prisma") {
      skills.push("prisma-cli", "prisma-client-api", "prisma-database-setup");
    }

    if (config.dbSetup === "prisma-postgres") {
      skills.push("prisma-postgres");
    }

    return skills;
  },
  "elysiajs/skills": () => ["elysiajs"],
  "waynesutton/convexskills": () => [
    "convex-best-practices",
    "convex-functions",
    "convex-schema-validator",
    "convex-realtime",
    "convex-http-actions",
    "convex-cron-jobs",
    "convex-file-storage",
    "convex-migrations",
    "convex-security-check",
  ],
  "msmps/opentui-skill": () => ["opentui"],
  "haydenbleasel/ultracite": () => ["ultracite"],
  "https://www.evlog.dev": () => ["review-logging-patterns", "analyze-logs"],
};

function getCuratedSkillNamesForSourceKey(sourceKey: SourceKey, config: ProjectConfig): string[] {
  return CURATED_SKILLS_BY_SOURCE[sourceKey](config);
}

function uniqueValues<T>(values: T[]): T[] {
  return Array.from(new Set(values));
}

export async function setupSkills(
  config: ProjectConfig,
): Promise<Result<void, AddonSetupError | UserCancelledError>> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;

  // Load full config from bts.jsonc to get all addons (existing + new)
  const btsConfig = await readBtsConfig(projectDir);
  const fullConfig: ProjectConfig = btsConfig
    ? {
        ...config,
        addons: btsConfig.addons ?? config.addons,
        addonOptions: btsConfig.addonOptions ?? config.addonOptions,
      }
    : config;

  const recommendedSourceKeys = getRecommendedSourceKeys(fullConfig);
  const skillsOptions = fullConfig.addonOptions?.skills;
  const configuredSourceKeys = uniqueValues(
    (skillsOptions?.selections ?? []).map((selection) => selection.source),
  );
  const sourceKeys = uniqueValues([...recommendedSourceKeys, ...configuredSourceKeys]);

  if (sourceKeys.length === 0) {
    return Result.ok(undefined);
  }

  const skillOptions = sourceKeys.flatMap((sourceKey) => {
    const source = SKILL_SOURCES[sourceKey];
    const skillNames = getCuratedSkillNamesForSourceKey(sourceKey, fullConfig);
    return skillNames.map((skillName) => ({
      value: `${sourceKey}::${skillName}`,
      label: skillName,
      hint: source.label,
    }));
  });

  if (skillOptions.length === 0) {
    return Result.ok(undefined);
  }

  const configuredScope = skillsOptions?.scope;
  const configuredSelections = skillsOptions?.selections;
  const configuredAgents = skillsOptions?.agents;
  const allSkillValues = skillOptions.map((opt) => opt.value);

  let scope: InstallScope;
  let selectedSkills: string[];
  let selectedAgents: SkillAgent[];

  if (isSilent()) {
    scope = configuredScope ?? DEFAULT_SCOPE;
    selectedSkills =
      configuredSelections !== undefined
        ? configuredSelections.flatMap((selection) =>
            selection.skills.map((skill) => `${selection.source}::${skill}`),
          )
        : allSkillValues;
    if (selectedSkills.length === 0) return Result.ok(undefined);
    selectedAgents = configuredAgents ? [...configuredAgents] : [...DEFAULT_AGENTS];
    if (selectedAgents.length === 0) return Result.ok(undefined);
  } else {
    const results = await navigableGroup<{
      scope: InstallScope;
      skills: string[];
      agents: SkillAgent[];
    }>({
      scope: async () => {
        if (configuredScope !== undefined) return configuredScope;
        return navigableSelect<InstallScope>({
          message: "Where should skills be installed?",
          options: [
            {
              value: "project",
              label: "Project",
              hint: "Writes to project config files (recommended for teams)",
            },
            {
              value: "global",
              label: "Global",
              hint: "Writes to user-level config files (personal machine)",
            },
          ],
          initialValue: DEFAULT_SCOPE,
        });
      },
      skills: async () => {
        if (configuredSelections !== undefined) {
          return configuredSelections.flatMap((selection) =>
            selection.skills.map((skill) => `${selection.source}::${skill}`),
          );
        }
        return navigableMultiselect<string>({
          message: "Select skills to install",
          options: skillOptions,
          required: false,
          initialValues: allSkillValues,
        });
      },
      agents: async ({ results: r }) => {
        const pickedSkills = r.skills as string[] | undefined;
        if (pickedSkills !== undefined && pickedSkills.length === 0) return [];
        if (configuredAgents !== undefined) return [...configuredAgents];
        return navigableMultiselect<SkillAgent>({
          message: "Select agents to install skills to",
          options: AVAILABLE_AGENTS,
          required: false,
          initialValues: [...DEFAULT_AGENTS],
        });
      },
    });

    if (
      results.scope === undefined ||
      results.skills === undefined ||
      results.agents === undefined
    ) {
      return Result.err(new UserCancelledError({ message: "Operation cancelled" }));
    }

    scope = results.scope;
    selectedSkills = results.skills as string[];
    selectedAgents = results.agents as SkillAgent[];

    if (selectedSkills.length === 0 || selectedAgents.length === 0) {
      return Result.ok(undefined);
    }
  }

  // Group skills by source
  const skillsBySource: Record<string, string[]> = {};
  for (const skillKey of selectedSkills) {
    const [source, skillName] = skillKey.split("::");
    if (!skillsBySource[source]) {
      skillsBySource[source] = [];
    }
    skillsBySource[source].push(skillName);
  }

  const installSpinner = createSpinner();
  installSpinner.start("Installing skills...");

  const runner = getPackageRunnerPrefix(packageManager);
  const globalFlags = scope === "global" ? ["-g"] : [];

  // Install skills grouped by source (project scope, no -g flag)
  for (const [source, skills] of Object.entries(skillsBySource)) {
    const installResult = await Result.tryPromise({
      try: async () => {
        const args = [
          ...runner,
          "skills@latest",
          "add",
          source,
          ...globalFlags,
          "--skill",
          ...skills,
          "--agent",
          ...selectedAgents,
          "-y",
        ];
        await $({ cwd: projectDir, env: { CI: "true" } })`${args}`;
      },
      catch: (e) =>
        new AddonSetupError({
          addon: "skills",
          message: `Failed to install skills from ${source}: ${e instanceof Error ? e.message : String(e)}`,
          cause: e,
        }),
    });

    if (installResult.isErr()) {
      cliLog.warn(pc.yellow(`Warning: Could not install skills from ${source}`));
    }
  }

  installSpinner.stop("Skills installed");

  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/starlight-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";

import type { ProjectConfig } from "../../types";
import { AddonSetupError } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionArgs } from "../../utils/package-runner";
import { createSpinner } from "../../utils/terminal-output";

export async function setupStarlight(
  config: ProjectConfig,
): Promise<Result<void, AddonSetupError>> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;
  const s = createSpinner();

  s.start("Setting up Starlight docs...");

  const starlightArgs = [
    "docs",
    "--template",
    "starlight",
    "--yes",
    "--no-install",
    "--no-git",
    "--skip-houston",
  ];
  const starlightArgsString = starlightArgs.join(" ");

  const commandWithArgs = `create-astro@latest ${starlightArgsString}`;
  const args = getPackageExecutionArgs(packageManager, commandWithArgs);

  const appsDir = path.join(projectDir, "apps");
  await fs.ensureDir(appsDir);

  const result = await Result.tryPromise({
    try: async () => {
      await $({ cwd: appsDir, env: { CI: "true" } })`${args}`;
    },
    catch: (e) =>
      new AddonSetupError({
        addon: "starlight",
        message: `Failed to set up Starlight docs: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (result.isErr()) {
    s.stop("Failed to set up Starlight docs");
    return result;
  }

  s.stop("Starlight docs setup successfully!");
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/tauri-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { execa } from "execa";
import fs from "fs-extra";

import { desktopWebFrontends, type ProjectConfig } from "../../types";
import { AddonSetupError } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageRunnerPrefix } from "../../utils/package-runner";
import { createSpinner } from "../../utils/terminal-output";

function getWebFrontend(frontend: Pick<ProjectConfig, "frontend">["frontend"]) {
  return frontend.find((value) => (desktopWebFrontends as readonly string[]).includes(value));
}

function getTauriDevUrl(frontend: Pick<ProjectConfig, "frontend">["frontend"]) {
  const webFrontend = getWebFrontend(frontend);

  switch (webFrontend) {
    case "react-router":
    case "svelte":
      return "http://localhost:5173";
    case "astro":
      return "http://localhost:4321";
    default:
      return "http://localhost:3001";
  }
}

function getTauriFrontendDist(frontend: Pick<ProjectConfig, "frontend">["frontend"]) {
  const webFrontend = getWebFrontend(frontend);

  switch (webFrontend) {
    case "react-router":
      return "../build/client";
    case "tanstack-start":
      return "../dist/client";
    case "next":
      return "../out";
    case "nuxt":
      return "../.output/public";
    case "svelte":
      return "../build";
    default:
      return "../dist";
  }
}

function getTauriBeforeBuildCommand(
  packageManager: Pick<ProjectConfig, "packageManager">["packageManager"],
  frontend: Pick<ProjectConfig, "frontend">["frontend"],
) {
  return frontend.includes("nuxt")
    ? `${packageManager} run generate`
    : `${packageManager} run build`;
}

export function buildTauriInitArgs(
  config: Pick<ProjectConfig, "packageManager" | "frontend" | "projectDir">,
) {
  const { packageManager, frontend, projectDir } = config;

  return [
    ...getPackageRunnerPrefix(packageManager),
    "@tauri-apps/cli@latest",
    "init",
    "--ci",
    "--app-name",
    path.basename(projectDir),
    "--window-title",
    path.basename(projectDir),
    "--frontend-dist",
    getTauriFrontendDist(frontend),
    "--dev-url",
    getTauriDevUrl(frontend),
    "--before-dev-command",
    `${packageManager} run dev`,
    "--before-build-command",
    getTauriBeforeBuildCommand(packageManager, frontend),
  ];
}

export async function setupTauri(config: ProjectConfig): Promise<Result<void, AddonSetupError>> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, frontend, projectDir } = config;
  const s = createSpinner();
  const clientPackageDir = path.join(projectDir, "apps/web");

  if (!(await fs.pathExists(clientPackageDir))) {
    return Result.ok(undefined);
  }

  s.start("Setting up Tauri desktop app support...");

  const [command, ...args] = buildTauriInitArgs({ packageManager, frontend, projectDir });

  const result = await Result.tryPromise({
    try: async () => {
      await execa(command, args, {
        cwd: clientPackageDir,
        env: { CI: "true" },
      });
    },
    catch: (e) =>
      new AddonSetupError({
        addon: "tauri",
        message: `Failed to set up Tauri: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (result.isErr()) {
    s.stop("Failed to set up Tauri");
    return result;
  }

  s.stop("Tauri desktop app support configured successfully!");
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/tui-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";
import pc from "picocolors";

import { isCancel, navigableSelect, setIsFirstPrompt } from "../../prompts/navigable";
import type { ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError, userCancelled } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionArgs } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type TuiTemplate = "core" | "react" | "solid";

type TuiSetupResult = Result<void, AddonSetupError | UserCancelledError>;

const TEMPLATES = {
  core: {
    label: "Core",
    hint: "Basic OpenTUI template",
  },
  react: {
    label: "React",
    hint: "React-based OpenTUI template",
  },
  solid: {
    label: "Solid",
    hint: "SolidJS-based OpenTUI template",
  },
} as const;

const DEFAULT_TEMPLATE: TuiTemplate = "core";
const TUI_LOCKFILES = ["bun.lock", "package-lock.json", "pnpm-lock.yaml", "yarn.lock"] as const;

export function resolveTuiTemplate(config: ProjectConfig): TuiTemplate | undefined {
  const configuredTemplate = config.addonOptions?.opentui?.template;

  if (configuredTemplate) {
    return configuredTemplate;
  }

  if (isSilent()) {
    return DEFAULT_TEMPLATE;
  }

  return undefined;
}

export async function setupTui(config: ProjectConfig): Promise<TuiSetupResult> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;

  cliLog.info("Setting up OpenTUI...");

  let template = resolveTuiTemplate(config);

  if (!template) {
    setIsFirstPrompt(true);
    const selectedTemplate = await navigableSelect<TuiTemplate>({
      message: "Choose a template",
      options: Object.entries(TEMPLATES).map(([key, templateOption]) => ({
        value: key as TuiTemplate,
        label: templateOption.label,
        hint: templateOption.hint,
      })),
      initialValue: DEFAULT_TEMPLATE,
    });

    if (isCancel(selectedTemplate)) {
      return userCancelled("Operation cancelled");
    }

    template = selectedTemplate as TuiTemplate;
  }

  const commandWithArgs = `create-tui@latest --template ${template} --no-git --no-install tui`;
  const args = getPackageExecutionArgs(packageManager, commandWithArgs);

  const appsDir = path.join(projectDir, "apps");

  const ensureDirResult = await Result.tryPromise({
    try: () => fs.ensureDir(appsDir),
    catch: (e) =>
      new AddonSetupError({
        addon: "tui",
        message: `Failed to create directory: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (ensureDirResult.isErr()) {
    return ensureDirResult;
  }

  const s = createSpinner();
  s.start("Running OpenTUI create command...");

  const initResult = await Result.tryPromise({
    try: async () => {
      await $({ cwd: appsDir, env: { CI: "true" } })`${args}`;
    },
    catch: (e) => {
      s.stop(pc.red("Failed to run OpenTUI create command"));
      return new AddonSetupError({
        addon: "tui",
        message: `Failed to set up OpenTUI: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      });
    },
  });

  if (initResult.isErr()) {
    cliLog.error(pc.red("Failed to set up OpenTUI"));
    return initResult;
  }

  const postProcessResult = await postProcessTuiWorkspace(path.join(appsDir, "tui"));
  if (postProcessResult.isErr()) {
    s.stop(pc.yellow("OpenTUI setup completed with warnings"));
    cliLog.warn(pc.yellow("OpenTUI setup completed but workspace normalization had warnings"));
    return postProcessResult;
  }

  s.stop("OpenTUI setup complete!");
  return Result.ok(undefined);
}

export async function postProcessTuiWorkspace(
  tuiDir: string,
): Promise<Result<void, AddonSetupError | UserCancelledError>> {
  const packageJsonPath = path.join(tuiDir, "package.json");

  const packageJsonResult = await Result.tryPromise({
    try: async () => {
      const packageJson = await fs.readJson(packageJsonPath);
      packageJson.scripts = packageJson.scripts || {};

      if (!packageJson.scripts["check-types"]) {
        packageJson.scripts["check-types"] = "tsc --noEmit";
      }

      await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
    },
    catch: (e) =>
      new AddonSetupError({
        addon: "tui",
        message: `Failed to normalize OpenTUI package.json: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (packageJsonResult.isErr()) {
    return packageJsonResult;
  }

  for (const lockfile of TUI_LOCKFILES) {
    const lockfilePath = path.join(tuiDir, lockfile);

    const removeLockfileResult = await Result.tryPromise({
      try: async () => {
        if (await fs.pathExists(lockfilePath)) {
          await fs.remove(lockfilePath);
        }
      },
      catch: (e) =>
        new AddonSetupError({
          addon: "tui",
          message: `Failed to remove nested OpenTUI lockfile '${lockfile}': ${e instanceof Error ? e.message : String(e)}`,
          cause: e,
        }),
    });

    if (removeLockfileResult.isErr()) {
      return removeLockfileResult;
    }
  }

  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/ultracite-setup.ts
================================================
import { Result } from "better-result";
import { $ } from "execa";
import pc from "picocolors";

import { navigableMultiselect, navigableSelect } from "../../prompts/navigable";
import { navigableGroup } from "../../prompts/navigable-group";
import type { ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError, userCancelled } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageRunnerPrefix } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type UltraciteLinter = "biome" | "eslint" | "oxlint";

type UltraciteEditor =
  | "vscode"
  | "cursor"
  | "windsurf"
  | "codebuddy"
  | "antigravity"
  | "bob"
  | "kiro"
  | "trae"
  | "void"
  | "zed";

type UltraciteAgent =
  | "universal"
  | "claude"
  | "codex"
  | "jules"
  | "replit"
  | "devin"
  | "lovable"
  | "zencoder"
  | "ona"
  | "openclaw"
  | "continue"
  | "snowflake-cortex"
  | "deepagents"
  | "qoder"
  | "kimi-cli"
  | "mcpjam"
  | "mux"
  | "pi"
  | "adal"
  | "copilot"
  | "cline"
  | "amp"
  | "aider"
  | "firebase-studio"
  | "open-hands"
  | "gemini"
  | "junie"
  | "augmentcode"
  | "bob"
  | "kilo-code"
  | "goose"
  | "roo-code"
  | "warp"
  | "droid"
  | "opencode"
  | "crush"
  | "qwen"
  | "amazon-q-cli"
  | "firebender"
  | "cursor-cli"
  | "mistral-vibe"
  | "vercel";

type UltraciteHook = "cursor" | "windsurf" | "codebuddy" | "claude" | "copilot";

type UltraciteSetupResult = Result<void, AddonSetupError | UserCancelledError>;
type UltraciteInitArgsInput = {
  packageManager: ProjectConfig["packageManager"];
  linter: UltraciteLinter;
  frameworks: string[];
  editors: UltraciteEditor[];
  agents: UltraciteAgent[];
  hooks: UltraciteHook[];
  gitHooks: string[];
};

const LINTERS = {
  biome: { label: "Biome (Recommended)" },
  eslint: { label: "ESLint + Prettier + Stylelint" },
  oxlint: { label: "Oxlint + Oxfmt" },
} as const;

const AGENTS = {
  universal: { label: "Universal (AGENTS.md — covers all agents)" },
  claude: { label: "Claude Code" },
  codex: { label: "Codex" },
  jules: { label: "Jules" },
  replit: { label: "Replit Agent" },
  devin: { label: "Devin" },
  lovable: { label: "Lovable" },
  zencoder: { label: "Zencoder" },
  ona: { label: "Ona" },
  openclaw: { label: "OpenClaw" },
  continue: { label: "Continue" },
  "snowflake-cortex": { label: "Snowflake Cortex" },
  deepagents: { label: "Deepagents" },
  qoder: { label: "Qoder" },
  "kimi-cli": { label: "Kimi CLI" },
  mcpjam: { label: "MCPJam" },
  mux: { label: "Mux" },
  pi: { label: "Pi" },
  adal: { label: "AdaL" },
  copilot: { label: "GitHub Copilot" },
  cline: { label: "Cline" },
  amp: { label: "AMP" },
  aider: { label: "Aider" },
  "firebase-studio": { label: "Firebase Studio" },
  "open-hands": { label: "OpenHands" },
  gemini: { label: "Gemini" },
  junie: { label: "Junie" },
  augmentcode: { label: "Augment Code" },
  bob: { label: "IBM Bob" },
  "kilo-code": { label: "Kilo Code" },
  goose: { label: "Goose" },
  "roo-code": { label: "Roo Code" },
  warp: { label: "Warp" },
  droid: { label: "Droid" },
  opencode: { label: "OpenCode" },
  crush: { label: "Crush" },
  qwen: { label: "Qwen Code" },
  "amazon-q-cli": { label: "Amazon Q CLI" },
  firebender: { label: "Firebender" },
  "cursor-cli": { label: "Cursor CLI" },
  "mistral-vibe": { label: "Mistral Vibe" },
  vercel: { label: "Vercel Agent" },
} as const;

const HOOKS = {
  cursor: { label: "Cursor" },
  windsurf: { label: "Windsurf" },
  codebuddy: { label: "CodeBuddy" },
  claude: { label: "Claude Code" },
  copilot: { label: "GitHub Copilot" },
} as const;

const DEFAULT_LINTER: UltraciteLinter = "biome";
const DEFAULT_EDITORS: UltraciteEditor[] = ["vscode"];
const DEFAULT_AGENTS: UltraciteAgent[] = ["universal"];
const DEFAULT_HOOKS: UltraciteHook[] = [];

function getFrameworksFromFrontend(frontend: string[]): string[] {
  const frameworkMap: Record<string, string> = {
    "tanstack-router": "react",
    "react-router": "react",
    "tanstack-start": "react",
    next: "next",
    nuxt: "vue",
    "native-bare": "react",
    "native-uniwind": "react",
    "native-unistyles": "react",
    svelte: "svelte",
    solid: "solid",
    astro: "astro",
  };

  const frameworks = new Set<string>();

  for (const f of frontend) {
    if (f !== "none" && frameworkMap[f]) {
      frameworks.add(frameworkMap[f]);
    }
  }

  return Array.from(frameworks);
}

export function buildUltraciteInitArgs({
  packageManager,
  linter,
  frameworks,
  editors,
  agents,
  hooks,
  gitHooks,
}: UltraciteInitArgsInput): string[] {
  const ultraciteArgs = ["init", "--pm", packageManager, "--linter", linter];

  if (frameworks.length > 0) {
    ultraciteArgs.push("--frameworks", ...frameworks);
  }

  if (editors.length > 0) {
    ultraciteArgs.push("--editors", ...editors);
  }

  if (agents.length > 0) {
    ultraciteArgs.push("--agents", ...agents);
  }

  if (hooks.length > 0) {
    ultraciteArgs.push("--hooks", ...hooks);
  }

  if (gitHooks.length > 0) {
    ultraciteArgs.push("--integrations", ...gitHooks);
  }

  return [
    ...getPackageRunnerPrefix(packageManager),
    "ultracite@latest",
    ...ultraciteArgs,
    "--skip-install",
    "--quiet",
  ];
}

export async function setupUltracite(
  config: ProjectConfig,
  gitHooks: string[],
): Promise<UltraciteSetupResult> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir, frontend } = config;

  cliLog.info("Setting up Ultracite...");

  const configuredOptions = config.addonOptions?.ultracite;
  let linter = configuredOptions?.linter;
  let editors = configuredOptions?.editors;
  let agents = configuredOptions?.agents;
  let hooks = configuredOptions?.hooks;

  if (!linter || !editors || !agents || !hooks) {
    if (isSilent()) {
      linter = linter ?? DEFAULT_LINTER;
      editors = editors ?? [...DEFAULT_EDITORS];
      agents = agents ?? [...DEFAULT_AGENTS];
      hooks = hooks ?? [...DEFAULT_HOOKS];
    } else {
      const results = await navigableGroup<{
        linter: UltraciteLinter;
        editors: UltraciteEditor[];
        agents: UltraciteAgent[];
        hooks: UltraciteHook[];
      }>({
        linter: async () => {
          if (linter !== undefined) return linter;
          return navigableSelect<UltraciteLinter>({
            message: "Which linter do you want to use?",
            options: Object.entries(LINTERS).map(([key, linterOption]) => ({
              value: key as UltraciteLinter,
              label: linterOption.label,
            })),
            initialValue: linter ?? DEFAULT_LINTER,
          });
        },
        editors: async () => {
          if (editors !== undefined) return editors;
          return navigableMultiselect<UltraciteEditor>({
            message: "Which editors do you want to configure (recommended)?",
            required: false,
            options: [
              { value: "vscode", label: "VSCode / Cursor / Windsurf" },
              { value: "zed", label: "Zed" },
            ],
          });
        },
        agents: async () => {
          if (agents !== undefined) return agents;
          return navigableMultiselect<UltraciteAgent>({
            message: "Which agent files do you want to add (optional)?",
            required: false,
            options: Object.entries(AGENTS).map(([key, agent]) => ({
              value: key as UltraciteAgent,
              label: agent.label,
            })),
          });
        },
        hooks: async () => {
          if (hooks !== undefined) return hooks;
          return navigableMultiselect<UltraciteHook>({
            message: "Which agent hooks do you want to enable (optional)?",
            required: false,
            options: Object.entries(HOOKS).map(([key, hook]) => ({
              value: key as UltraciteHook,
              label: hook.label,
            })),
          });
        },
      });

      if (
        results.linter === undefined ||
        results.editors === undefined ||
        results.agents === undefined ||
        results.hooks === undefined
      ) {
        return userCancelled("Operation cancelled");
      }

      linter = results.linter;
      editors = results.editors;
      agents = results.agents;
      hooks = results.hooks;
    }
  }

  const frameworks = getFrameworksFromFrontend(frontend);
  const args = buildUltraciteInitArgs({
    packageManager,
    linter,
    frameworks,
    editors,
    agents,
    hooks,
    gitHooks,
  });

  const s = createSpinner();
  s.start("Running Ultracite init command...");

  const initResult = await Result.tryPromise({
    try: async () => {
      await $({ cwd: projectDir, env: { CI: "true" } })`${args}`;
    },
    catch: (e) => {
      s.stop(pc.red("Failed to run Ultracite init command"));
      return new AddonSetupError({
        addon: "ultracite",
        message: `Failed to set up Ultracite: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      });
    },
  });

  if (initResult.isErr()) {
    cliLog.error(pc.red("Failed to set up Ultracite"));
    return initResult;
  }

  s.stop("Ultracite setup successfully!");
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/addons/wxt-setup.ts
================================================
import path from "node:path";

import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";
import pc from "picocolors";

import { isCancel, navigableSelect, setIsFirstPrompt } from "../../prompts/navigable";
import type { ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { AddonSetupError, UserCancelledError, userCancelled } from "../../utils/errors";
import { shouldSkipExternalCommands } from "../../utils/external-commands";
import { getPackageExecutionArgs } from "../../utils/package-runner";
import { cliLog, createSpinner } from "../../utils/terminal-output";

type WxtTemplate = "vanilla" | "vue" | "react" | "solid" | "svelte";

type WxtSetupResult = Result<void, AddonSetupError | UserCancelledError>;

const TEMPLATES = {
  vanilla: {
    label: "Vanilla",
    hint: "Vanilla JavaScript template",
  },
  vue: {
    label: "Vue",
    hint: "Vue.js template",
  },
  react: {
    label: "React",
    hint: "React template",
  },
  solid: {
    label: "Solid",
    hint: "SolidJS template",
  },
  svelte: {
    label: "Svelte",
    hint: "Svelte template",
  },
} as const;

const DEFAULT_TEMPLATE: WxtTemplate = "react";
const DEFAULT_DEV_PORT = 5555;

export async function setupWxt(config: ProjectConfig): Promise<WxtSetupResult> {
  if (shouldSkipExternalCommands()) {
    return Result.ok(undefined);
  }

  const { packageManager, projectDir } = config;

  cliLog.info("Setting up WXT...");

  const configuredOptions = config.addonOptions?.wxt;
  let template = configuredOptions?.template;

  if (!template) {
    if (isSilent()) {
      template = DEFAULT_TEMPLATE;
    } else {
      setIsFirstPrompt(true);
      const selectedTemplate = await navigableSelect<WxtTemplate>({
        message: "Choose a template",
        options: Object.entries(TEMPLATES).map(([key, templateOption]) => ({
          value: key as WxtTemplate,
          label: templateOption.label,
          hint: templateOption.hint,
        })),
        initialValue: DEFAULT_TEMPLATE,
      });

      if (isCancel(selectedTemplate)) {
        return userCancelled("Operation cancelled");
      }

      template = selectedTemplate as WxtTemplate;
    }
  }

  const devPort = configuredOptions?.devPort ?? DEFAULT_DEV_PORT;

  const commandWithArgs = `wxt@latest init extension --template ${template} --pm ${packageManager}`;
  const args = getPackageExecutionArgs(packageManager, commandWithArgs);

  const appsDir = path.join(projectDir, "apps");

  const ensureDirResult = await Result.tryPromise({
    try: () => fs.ensureDir(appsDir),
    catch: (e) =>
      new AddonSetupError({
        addon: "wxt",
        message: `Failed to create directory: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (ensureDirResult.isErr()) {
    return ensureDirResult;
  }

  const s = createSpinner();
  s.start("Running WXT init command...");

  const initResult = await Result.tryPromise({
    try: async () => {
      await $({ cwd: appsDir, env: { CI: "true" } })`${args}`;
    },
    catch: (e) => {
      s.stop(pc.red("Failed to run WXT init command"));
      return new AddonSetupError({
        addon: "wxt",
        message: `Failed to set up WXT: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      });
    },
  });

  if (initResult.isErr()) {
    cliLog.error(pc.red("Failed to set up WXT"));
    return initResult;
  }

  const extensionDir = path.join(projectDir, "apps", "extension");
  const packageJsonPath = path.join(extensionDir, "package.json");

  const updatePackageResult = await Result.tryPromise({
    try: async () => {
      if (await fs.pathExists(packageJsonPath)) {
        const packageJson = await fs.readJson(packageJsonPath);
        packageJson.name = "extension";

        if (packageJson.scripts?.dev) {
          packageJson.scripts.dev = `${packageJson.scripts.dev} --port ${devPort}`;
        }

        await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
      }
    },
    catch: (e) =>
      new AddonSetupError({
        addon: "wxt",
        message: `Failed to update package.json: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });

  if (updatePackageResult.isErr()) {
    // Log but don't fail - the main setup succeeded
    cliLog.warn(pc.yellow("WXT setup completed but failed to update package.json"));
  }

  s.stop("WXT setup complete!");
  return Result.ok(undefined);
}


================================================
FILE: apps/cli/src/helpers/core/add-handler.ts
================================================
import path from "node:path";

import {
  EMBEDDED_TEMPLATES,
  processAddonTemplates,
  processAddonsDeps,
  VirtualFileSystem,
} from "@better-t-stack/template-generator";
import { writeTree } from "@better-t-stack/template-generator/fs-writer";
import { intro, log, outro } from "@clack/prompts";
import { Result } from "better-result";
import fs from "fs-extra";
import pc from "picocolors";

import { getAddonsToAdd } from "../../prompts/addons";
import type { AddInput, Addons, AddonOptions, ProjectConfig } from "../../types";
import { updateBtsConfig } from "../../utils/bts-config";
import { validateAddonsAgainstConfig } from "../../utils/compatibility-rules";
import { isSilent, runWithContextAsync } from "../../utils/context";
import { CLIError, UserCancelledError, displayError } from "../../utils/errors";
import { validateAgentSafePathInput } from "../../utils/input-hardening";
import { renderTitle } from "../../utils/render-title";
import { setupAddons } from "../addons/addons-setup";
import { detectProjectConfig } from "./detect-project-config";
import { installDependencies } from "./install-dependencies";

export interface AddHandlerOptions {
  silent?: boolean;
}

export interface AddResult {
  success: boolean;
  addedAddons: Addons[];
  projectDir: string;
  dryRun?: boolean;
  plannedFileCount?: number;
  error?: string;
}

function mergeAddonOptions(
  existingAddonOptions?: AddonOptions,
  nextAddonOptions?: AddonOptions,
): AddonOptions | undefined {
  if (!existingAddonOptions && !nextAddonOptions) {
    return undefined;
  }

  const mergedAddonOptions: Partial<AddonOptions> = { ...existingAddonOptions };

  if (nextAddonOptions) {
    for (const addonKey of Object.keys(nextAddonOptions) as (keyof AddonOptions)[]) {
      const existingOptionsForAddon = existingAddonOptions?.[addonKey];
      const nextOptionsForAddon = nextAddonOptions[addonKey];
      const mergedOptionsForAddon =
        existingOptionsForAddon && nextOptionsForAddon
          ? { ...existingOptionsForAddon, ...nextOptionsForAddon }
          : nextOptionsForAddon;

      (
        mergedAddonOptions as Record<
          keyof AddonOptions,
          AddonOptions[keyof AddonOptions] | undefined
        >
      )[addonKey] = mergedOptionsForAddon as AddonOptions[keyof AddonOptions];
    }
  }

  return Object.keys(mergedAddonOptions).length > 0
    ? (mergedAddonOptions as AddonOptions)
    : undefined;
}

export async function addHandler(
  input: AddInput,
  options: AddHandlerOptions = {},
): Promise<AddResult | undefined> {
  const { silent = false } = options;

  return runWithContextAsync({ silent }, async () => {
    const result = await addHandlerInternal(input);

    if (result.isOk()) {
      return result.value;
    }

    const error = result.error;

    if (UserCancelledError.is(error)) {
      if (isSilent()) {
        return {
          success: false,
          addedAddons: [],
          projectDir: "",
          error: error.message,
        };
      }
      return undefined;
    }

    if (isSilent()) {
      return {
        success: false,
        addedAddons: [],
        projectDir: "",
        error: error.message,
      };
    }

    displayError(error);
    process.exit(1);
  });
}

async function addHandlerInternal(
  input: AddInput,
): Promise<Result<AddResult, UserCancelledError | CLIError>> {
  const projectDir = input.projectDir || process.cwd();
  const hardeningResult = validateAgentSafePathInput(projectDir, "projectDir");
  if (hardeningResult.isErr()) {
    return Result.err(
      new CLIError({
        message: hardeningResult.error.message,
        cause: hardeningResult.error,
      }),
    );
  }

  if (!isSilent()) {
    renderTitle();
    intro(pc.magenta("Add addons to your Better-T-Stack project"));
  }

  // Detect existing project configuration
  const existingConfig = await detectProjectConfig(projectDir);

  if (!existingConfig) {
    return Result.err(
      new CLIError({
        message: `No Better-T-Stack project found in ${projectDir}. Make sure bts.jsonc exists.`,
      }),
    );
  }

  if (!isSilent()) {
    log.info(pc.dim(`Detected project: ${existingConfig.projectName}`));
  }

  // Determine which addons to add
  let addonsToAdd: Addons[];

  if (input.addons && input.addons.length > 0) {
    // Filter out 'none' and already installed addons
    addonsToAdd = input.addons.filter(
      (addon) => addon !== "none" && !existingConfig.addons.includes(addon),
    );

    if (addonsToAdd.length === 0) {
      if (!isSilent()) {
        log.warn(pc.yellow("All specified addons are already installed or invalid."));
      }
      return Result.ok({
        success: true,
        addedAddons: [],
        projectDir,
      });
    }
  } else if (isSilent()) {
    return Result.err(
      new CLIError({
        message: "Addons are required in silent mode. Provide them via add() or add-json.",
      }),
    );
  } else {
    // Interactive mode - prompt user to select addons
    const promptResult = await Result.tryPromise({
      try: () => getAddonsToAdd(existingConfig),
      catch: (e: unknown) => {
        if (UserCancelledError.is(e)) return e;
        return new CLIError({
          message: e instanceof Error ? e.message : String(e),
          cause: e,
        });
      },
    });

    if (promptResult.isErr()) {
      return Result.err(promptResult.error);
    }

    const selectedAddons = promptResult.value;

    if (selectedAddons.length === 0) {
      if (!isSilent()) {
        log.info(pc.dim("No addons selected."));
        outro(pc.magenta("Nothing to add."));
      }
      return Result.ok({
        success: true,
        addedAddons: [],
        projectDir,
      });
    }

    addonsToAdd = selectedAddons;
  }

  const addonsValidationResult = validateAddonsAgainstConfig(addonsToAdd, existingConfig);
  if (addonsValidationResult.isErr()) {
    return Result.err(new CLIError({ message: addonsValidationResult.error.message }));
  }

  if (!isSilent()) {
    log.info(pc.cyan(`Adding addons: ${addonsToAdd.join(", ")}`));
  }

  // Build config for addon setup
  const updatedAddons = [...existingConfig.addons, ...addonsToAdd];
  const mergedAddonOptions = mergeAddonOptions(existingConfig.addonOptions, input.addonOptions);
  const config: ProjectConfig = {
    projectName: existingConfig.projectName,
    projectDir,
    relativePath: ".",
    addonOptions: mergedAddonOptions,
    database: existingConfig.database,
    orm: existingConfig.orm,
    backend: existingConfig.backend,
    runtime: existingConfig.runtime,
    frontend: existingConfig.frontend,
    addons: addonsToAdd, // Only the new addons for template processing
    examples: existingConfig.examples,
    auth: existingConfig.auth,
    payments: existingConfig.payments,
    git: false,
    packageManager: input.packageManager || existingConfig.packageManager,
    install: input.install ?? false,
    dbSetup: existingConfig.dbSetup,
    api: existingConfig.api,
    webDeploy: existingConfig.webDeploy,
    serverDeploy: existingConfig.serverDeploy,
  };

  // Create VFS and process addon templates using template-generator's logic
  if (!isSilent()) {
    log.info(pc.dim("Installing addon files..."));
  }

  const vfs = new VirtualFileSystem();

  // Pre-load existing package.json files into VFS so processAddonsDeps can modify them
  const packageJsonPaths = [
    "package.json",
    "apps/web/package.json",
    "apps/server/package.json",
    "apps/native/package.json",
  ];
  for (const pkgPath of packageJsonPaths) {
    const fullPath = path.join(projectDir, pkgPath);
    if (await fs.pathExists(fullPath)) {
      const content = await fs.readFile(fullPath, "utf-8");
      vfs.writeFile(pkgPath, content);
    }
  }

  // Process addon templates
  await processAddonTemplates(vfs, EMBEDDED_TEMPLATES, config);

  // Process addon dependencies (adds deps to package.json files in VFS)
  processAddonsDeps(vfs, config);

  // Write VFS to disk
  const tree = {
    root: vfs.toTree(""),
    fileCount: vfs.getFileCount(),
    directoryCount: vfs.getDirectoryCount(),
    config,
  };

  if (input.dryRun) {
    if (!isSilent()) {
      log.success(pc.green("Dry run validation passed. No addon files were written."));
      log.info(pc.dim(`Planned addon files: ${vfs.getFileCount()}`));
      outro(pc.magenta("Dry run complete."));
    }

    return Result.ok({
      success: true,
      addedAddons: addonsToAdd,
      projectDir,
      dryRun: true,
      plannedFileCount: vfs.getFileCount(),
    });
  }

  const writeResult = await writeTree(tree, projectDir);

  if (writeResult.isErr()) {
    return Result.err(
      new CLIError({
        message: `Failed to write addon files: ${writeResult.error.message}`,
      }),
    );
  }

  if (vfs.getFileCount() > 0 && !isSilent()) {
    log.info(pc.dim(`Wrote ${vfs.getFileCount()} addon files`));
  }

  // Run addon setup (handles deps and interactive prompts)
  // Wrap with Result.tryPromise since setupAddons can throw UserCancelledError
  const setupResult = await Result.tryPromise({
    try: () => setupAddons(config),
    catch: (e: unknown) => {
      if (UserCancelledError.is(e)) return e;
      return new CLIError({
        message: e instanceof Error ? e.message : String(e),
        cause: e,
      });
    },
  });

  if (setupResult.isErr()) {
    return Result.err(setupResult.error);
  }

  // Update bts.jsonc with new addons
  await updateBtsConfig(projectDir, {
    addons: updatedAddons,
    addonOptions: config.addonOptions,
  });

  // Install dependencies if requested
  if (input.install) {
    if (!isSilent()) {
      log.info(pc.dim("Installing dependencies..."));
    }
    await installDependencies({ projectDir, packageManager: config.packageManager });
  }

  if (!isSilent()) {
    log.success(pc.green(`Successfully added: ${addonsToAdd.join(", ")}`));

    if (!input.install) {
      log.info(
        pc.yellow(
          `Run '${config.packageManager === "npm" ? "npm install" : `${config.packageManager} install`}' to install new dependencies.`,
        ),
      );
    }

    outro(pc.magenta("Addons added successfully!"));
  }

  return Result.ok({
    success: true,
    addedAddons: addonsToAdd,
    projectDir,
    plannedFileCount: vfs.getFileCount(),
  });
}


================================================
FILE: apps/cli/src/helpers/core/command-handlers.ts
================================================
import path from "node:path";

import { generateReproducibleCommand } from "@better-t-stack/template-generator";
import { intro, log, outro } from "@clack/prompts";
import { Result, UnhandledException } from "better-result";
import fs from "fs-extra";
import pc from "picocolors";

import { getDefaultConfig } from "../../constants";
import { gatherConfig } from "../../prompts/config-prompts";
import { getProjectName } from "../../prompts/project-name";
import type { CreateInput, DirectoryConflict, ProjectConfig } from "../../types";
import { trackProjectCreation } from "../../utils/analytics";
import { validateAddonsAgainstFrontends } from "../../utils/compatibility-rules";
import { isSilent, runWithContextAsync } from "../../utils/context";
import { displayConfig } from "../../utils/display-config";
import {
  type AppError,
  CLIError,
  DirectoryConflictError,
  ProjectCreationError,
  UserCancelledError,
  displayError,
} from "../../utils/errors";
import { validateAgentSafePathInput } from "../../utils/input-hardening";
import { handleDirectoryConflict, setupProjectDirectory } from "../../utils/project-directory";
import { addToHistory } from "../../utils/project-history";
import { validateProjectName } from "../../utils/project-name-validation";
import { renderTitle } from "../../utils/render-title";
import { getTemplateConfig, getTemplateDescription } from "../../utils/templates";
import { cliConsola } from "../../utils/terminal-output";
import {
  getProvidedFlags,
  processAndValidateFlags,
  processProvidedFlagsWithoutValidation,
  validateConfigCompatibility,
} from "../../validation";
import { createProject } from "./create-project";
import { mergeResolvedDbSetupOptions } from "./db-setup-options";

export interface CreateHandlerOptions {
  silent?: boolean;
}

/**
 * Result type for project creation
 */
export interface CreateProjectResult {
  success: boolean;
  projectConfig: ProjectConfig;
  reproducibleCommand: string;
  timeScaffolded: string;
  elapsedTimeMs: number;
  projectDirectory: string;
  relativePath: string;
  error?: string;
}

/**
 * Create an empty/failed result
 */
function createEmptyResult(
  timeScaffolded: string,
  elapsedTimeMs: number,
  error?: string,
): CreateProjectResult {
  return {
    success: false,
    projectConfig: {
      projectName: "",
      projectDir: "",
      relativePath: "",
      database: "none",
      orm: "none",
      backend: "none",
      runtime: "none",
      frontend: [],
      addons: [],
      examples: [],
      auth: "none",
      payments: "none",
      git: false,
      packageManager: "npm",
      install: false,
      dbSetup: "none",
      api: "none",
      webDeploy: "none",
      serverDeploy: "none",
    } satisfies ProjectConfig,
    reproducibleCommand: "",
    timeScaffolded,
    elapsedTimeMs,
    projectDirectory: "",
    relativePath: "",
    error,
  };
}

type CreateHandlerError =
  | UserCancelledError
  | CLIError
  | DirectoryConflictError
  | ProjectCreationError
  | UnhandledException;

export async function createProjectHandler(
  input: CreateInput & { projectName?: string },
  options: CreateHandlerOptions = {},
): Promise<CreateProjectResult | undefined> {
  const { silent = false } = options;

  return runWithContextAsync({ silent }, async () => {
    const startTime = Date.now();
    const timeScaffolded = new Date().toISOString();

    const result = await createProjectHandlerInternal(input, startTime, timeScaffolded);

    // Handle success case
    if (result.isOk()) {
      return result.value;
    }

    // Handle error cases
    const error = result.error;
    const elapsedTimeMs = Date.now() - startTime;

    // Handle user cancellation specially
    if (UserCancelledError.is(error)) {
      if (isSilent()) {
        return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
      }
      // In CLI mode, just return undefined (the cancel UI was already shown)
      return undefined;
    }

    // For silent mode, always return a failed result instead of throwing
    if (isSilent()) {
      return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
    }

    // In CLI mode, display error and exit
    displayError(error as AppError);
    process.exit(1);
  });
}

async function createProjectHandlerInternal(
  input: CreateInput & { projectName?: string },
  startTime: number,
  timeScaffolded: string,
): Promise<Result<CreateProjectResult, CreateHandlerError>> {
  return Result.gen(async function* () {
    if (!isSilent() && input.renderTitle !== false) {
      renderTitle();
    }
    if (!isSilent()) intro(pc.magenta("Creating a new Better-T-Stack project"));

    if (!isSilent() && input.yolo) {
      cliConsola.fatal("YOLO mode enabled - skipping checks. Things may break!");
    }

    // Get project name
    let currentPathInput: string;
    if (isSilent()) {
      const silentProjectName = yield* Result.await(resolveProjectNameForSilent(input));
      currentPathInput = silentProjectName;
    } else if (input.yes && input.projectName) {
      currentPathInput = input.projectName;
    } else if (input.yes) {
      const defaultConfig = getDefaultConfig();
      let defaultName: string = defaultConfig.relativePath;
      let counter = 1;
      while (
        (await fs.pathExists(path.resolve(process.cwd(), defaultName))) &&
        (await fs.readdir(path.resolve(process.cwd(), defaultName))).length > 0
      ) {
        defaultName = `${defaultConfig.projectName}-${counter}`;
        counter++;
      }
      currentPathInput = defaultName;
    } else {
      // getProjectName may throw UserCancelledError
      const projectNameResult = yield* Result.await(
        Result.tryPromise({
          try: async () => getProjectName(input.projectName),
          catch: (e: unknown) => {
            if (e instanceof UserCancelledError) return e;
            return new CLIError({
              message: e instanceof Error ? e.message : String(e),
              cause: e,
            });
          },
        }),
      );
      currentPathInput = projectNameResult;
    }

    yield* validateResolvedProjectPathInput(currentPathInput);

    // Handle directory conflict
    let finalPathInput: string;
    let shouldClearDirectory: boolean;

    const conflictResult = yield* Result.await(
      handleDirectoryConflictResult(currentPathInput, input.directoryConflict),
    );
    finalPathInput = conflictResult.finalPathInput;
    shouldClearDirectory = conflictResult.shouldClearDirectory;
    yield* validateResolvedProjectPathInput(finalPathInput);

    let finalResolvedPath: string;
    let finalBaseName: string;

    if (input.dryRun) {
      finalResolvedPath =
        finalPathInput === "." ? process.cwd() : path.resolve(process.cwd(), finalPathInput);
      finalBaseName = path.basename(finalResolvedPath);
    } else {
      // Setup project directory
      const setupResult = yield* Result.await(
        Result.tryPromise({
          try: async () => setupProjectDirectory(finalPathInput, shouldClearDirectory),
          catch: (e: unknown) => {
            if (e instanceof UserCancelledError) return e;
            return new CLIError({
              message: e instanceof Error ? e.message : String(e),
              cause: e,
            });
          },
        }),
      );
      finalResolvedPath = setupResult.finalResolvedPath;
      finalBaseName = setupResult.finalBaseName;
    }

    const originalInput = {
      ...input,
      projectDirectory: input.projectName,
    };

    const providedFlags = getProvidedFlags(originalInput);

    let cliInput = originalInput;

    // Handle template
    if (input.template && input.template !== "none") {
      const templateConfig = getTemplateConfig(input.template);
      if (templateConfig) {
        const templateName = input.template.toUpperCase();
        const templateDescription = getTemplateDescription(input.template);
        if (!isSilent()) {
          log.message(pc.bold(pc.cyan(`Using template: ${pc.white(templateName)}`)));
          log.message(pc.dim(`   ${templateDescription}`));
        }
        const userOverrides: Record<string, unknown> = {};
        for (const [key, value] of Object.entries(originalInput)) {
          if (value !== undefined) {
            userOverrides[key] = value;
          }
        }
        cliInput = {
          ...templateConfig,
          ...userOverrides,
          template: input.template,
          projectDirectory: originalInput.projectDirectory,
        };
      }
    }

    // Build config
    let config: ProjectConfig;
    if (cliInput.yes) {
      const flagConfigResult = processProvidedFlagsWithoutValidation(cliInput, finalBaseName);
      if (flagConfigResult.isErr()) {
        return Result.err(
          new CLIError({ message: flagConfigResult.error.message, cause: flagConfigResult.error }),
        );
      }
      const flagConfig = flagConfigResult.value;

      config = {
        ...getDefaultConfig(),
        ...flagConfig,
        projectName: finalBaseName,
        projectDir: finalResolvedPath,
        relativePath: finalPathInput,
      };

      // Validate config compatibility
      const validationResult = validateConfigCompatibility(config, providedFlags, cliInput);
      if (validationResult.isErr()) {
        return Result.err(
          new CLIError({ message: validationResult.error.message, cause: validationResult.error }),
        );
      }

      if (!isSilent()) {
        log.info(pc.yellow("Using default/flag options (config prompts skipped):"));
        log.message(displayConfig(config));
      }
    } else {
      // Process and validate flags
      const flagConfigResult = processAndValidateFlags(cliInput, providedFlags, finalBaseName);
      if (flagConfigResult.isErr()) {
        return Result.err(
          new CLIError({ message: flagConfigResult.error.message, cause: flagConfigResult.error }),
        );
      }
      const flagConfig = flagConfigResult.value;
      const { projectName: _projectNameFromFlags, ...otherFlags } = flagConfig;

      if (!isSilent() && Object.keys(otherFlags).length > 0) {
        log.info(pc.yellow("Using these pre-selected options:"));
        log.message(displayConfig(otherFlags));
        log.message("");
      }

      // gatherConfig may throw UserCancelledError
      const gatherResult = yield* Result.await(
        Result.tryPromise({
          try: async () =>
            gatherConfig(flagConfig, finalBaseName, finalResolvedPath, finalPathInput),
          catch: (e: unknown) => {
            if (e instanceof UserCancelledError) return e;
            return new CLIError({
              message: e instanceof Error ? e.message : String(e),
              cause: e,
            });
          },
        }),
      );
      config = gatherResult;
    }

    const effectiveDbSetupOptions = mergeResolvedDbSetupOptions(
      config.dbSetup,
      config.dbSetupOptions,
      {
        manualDb: cliInput.manualDb ?? input.manualDb,
        dbSetupOptions: cliInput.dbSetupOptions ?? input.dbSetupOptions,
      },
    );

    if (effectiveDbSetupOptions) {
      config = {
        ...config,
        dbSetupOptions: effectiveDbSetupOptions,
      };
    }

    if (!input.yolo) {
      const addonsValidationResult = validateAddonsAgainstFrontends(
        config.addons,
        config.frontend,
        config.auth,
        config.backend,
        config.runtime,
      );
      if (addonsValidationResult.isErr()) {
        return Result.err(new CLIError({ message: addonsValidationResult.error.message }));
      }
    }

    const reproducibleCommand = generateReproducibleCommand(config);

    if (input.dryRun) {
      const elapsedTimeMs = Date.now() - startTime;

      if (!isSilent()) {
        if (shouldClearDirectory) {
          log.warn(
            pc.yellow(
              `Dry run: directory "${finalPathInput}" would be cleared due to overwrite strategy.`,
            ),
          );
        }
        log.success(pc.green("Dry run validation passed. No files were written."));
        log.message(pc.dim(`Target directory: ${finalResolvedPath}`));
        log.message(pc.dim(`Run without --dry-run to create the project.`));
        outro(pc.magenta("Dry run complete."));
      }

      return Result.ok({
        success: true,
        projectConfig: config,
        reproducibleCommand,
        timeScaffolded,
        elapsedTimeMs,
        projectDirectory: config.projectDir,
        relativePath: config.relativePath,
      });
    }

    // Create the project
    yield* Result.await(
      createProject(config, {
        manualDb: cliInput.manualDb ?? input.manualDb,
        dbSetupOptions: effectiveDbSetupOptions,
      }),
    );

    if (!isSilent()) {
      log.success(
        pc.blue(`You can reproduce this setup with the following command:\n${reproducibleCommand}`),
      );
    }

    await trackProjectCreation(config, input.disableAnalytics);

    // Track locally in history.json (non-fatal)
    const historyResult = await addToHistory(config, reproducibleCommand);
    if (historyResult.isErr() && !isSilent()) {
      log.warn(pc.yellow(historyResult.error.message));
    }

    const elapsedTimeMs = Date.now() - startTime;
    if (!isSilent()) {
      const elapsedTimeInSeconds = (elapsedTimeMs / 1000).toFixed(2);
      outro(
        pc.magenta(`Project created successfully in ${pc.bold(elapsedTimeInSeconds)} seconds!`),
      );
    }

    return Result.ok({
      success: true,
      projectConfig: config,
      reproducibleCommand,
      timeScaffolded,
      elapsedTimeMs,
      projectDirectory: config.projectDir,
      relativePath: config.relativePath,
    });
  });
}

interface DirectoryConflictResult {
  finalPathInput: string;
  shouldClearDirectory: boolean;
}

function isPathWithinCwd(targetPath: string) {
  const resolved = path.resolve(targetPath);
  const rel = path.relative(process.cwd(), resolved);
  return !rel.startsWith("..") && !path.isAbsolute(rel);
}

function validateResolvedProjectPathInput(candidate: string): Result<void, CLIError> {
  const hardeningResult = validateAgentSafePathInput(candidate, "projectName");
  if (hardeningResult.isErr()) {
    return Result.err(
      new CLIError({
        message: hardeningResult.error.message,
        cause: hardeningResult.error,
      }),
    );
  }

  if (candidate === ".") {
    return Result.ok(undefined);
  }

  const finalDirName = path.basename(candidate);
  const validationResult = validateProjectName(finalDirName);
  if (validationResult.isErr()) {
    return Result.err(
      new CLIError({
        message: validationResult.error.message,
        cause: validationResult.error,
      }),
    );
  }

  if (!isPathWithinCwd(candidate)) {
    return Result.err(
      new CLIError({
        message: "Project path must be within current directory",
      }),
    );
  }

  return Result.ok(undefined);
}

async function resolveProjectNameForSilent(
  input: CreateInput & { projectName?: string },
): Promise<Result<string, CLIError>> {
  const defaultConfig = getDefaultConfig();
  const rawProjectName = input.projectName?.trim() || undefined;
  const candidate = rawProjectName ?? defaultConfig.relativePath;
  return Result.ok(candidate);
}

async function handleDirectoryConflictResult(
  currentPathInput: string,
  strategy?: DirectoryConflict,
): Promise<
  Result<DirectoryConflictResult, UserCancelledError | CLIError | DirectoryConflictError>
> {
  if (strategy) {
    return handleDirectoryConflictProgrammatically(currentPathInput, strategy);
  }

  // Use interactive handler
  return Result.tryPromise({
    try: async () => handleDirectoryConflict(currentPathInput),
    catch: (e: unknown) => {
      if (e instanceof UserCancelledError) return e;
      if (e instanceof CLIError) return e;
      return new CLIError({
        message: e instanceof Error ? e.message : String(e),
        cause: e,
      });
    },
  });
}

async function handleDirectoryConflictProgrammatically(
  currentPathInput: string,
  strategy: DirectoryConflict,
): Promise<Result<DirectoryConflictResult, DirectoryConflictError>> {
  const currentPath = path.resolve(process.cwd(), currentPathInput);

  if (!(await fs.pathExists(currentPath))) {
    return Result.ok({ finalPathInput: currentPathInput, shouldClearDirectory: false });
  }

  const dirContents = await fs.readdir(currentPath);
  const isNotEmpty = dirContents.length > 0;

  if (!isNotEmpty) {
    return Result.ok({ finalPathInput: currentPathInput, shouldClearDirectory: false });
  }

  switch (strategy) {
    case "overwrite":
      return Result.ok({ finalPathInput: currentPathInput, shouldClearDirectory: true });

    case "merge":
      return Result.ok({ finalPathInput: currentPathInput, shouldClearDirectory: false });

    case "increment": {
      let counter = 1;
      const baseName = currentPathInput;
      let finalPathInput = `${baseName}-${counter}`;

      while (
        (await fs.pathExists(path.resolve(process.cwd(), finalPathInput))) &&
        (await fs.readdir(path.resolve(process.cwd(), finalPathInput))).length > 0
      ) {
        counter++;
        finalPathInput = `${baseName}-${counter}`;
      }

      return Result.ok({ finalPathInput, shouldClearDirectory: false });
    }

    case "error":
      return Result.err(new DirectoryConflictError({ directory: currentPathInput }));

    default:
      return Result.err(new DirectoryConflictError({ directory: currentPathInput }));
  }
}


================================================
FILE: apps/cli/src/helpers/core/convex-codegen.ts
================================================
import path from "node:path";

import { $ } from "execa";

import type { PackageManager } from "../../types";
import { getPackageExecutionArgs } from "../../utils/package-runner";

// having problems running this in convex + better-auth
export async function runConvexCodegen(
  projectDir: string,
  packageManager: PackageManager | null | undefined,
) {
  const backendDir = path.join(projectDir, "packages/backend");
  const args = getPackageExecutionArgs(packageManager, "convex codegen");
  await $({ cwd: backendDir })`${args}`;
}


================================================
FILE: apps/cli/src/helpers/core/create-project.ts
================================================
import os from "node:os";
import path from "node:path";

import { generate, EMBEDDED_TEMPLATES } from "@better-t-stack/template-generator";
import { writeTree } from "@better-t-stack/template-generator/fs-writer";
import { log } from "@clack/prompts";
import { Result } from "better-result";
import { $ } from "execa";
import fs from "fs-extra";

import type { DbSetupOptions, ProjectConfig } from "../../types";
import { isSilent } from "../../utils/context";
import { ProjectCreationError } from "../../utils/errors";
import { formatProject } from "../../utils/file-formatter";
import { getLatestCLIVersion } from "../../utils/get-latest-cli-version";
import { setupAddons } from "../addons/addons-setup";
import { setupDatabase } from "../core/db-setup";
import { initializeGit } from "./git";
import { installDependencies } from "./install-dependencies";
import { displayPostInstallInstructions } from "./post-installation";

export interface CreateProjectOptions {
  manualDb?: boolean;
  dbSetupOptions?: DbSetupOptions;
}

/**
 * Creates a new project with the given configuration.
 * Returns a Result with the project directory path on success, or an error on failure.
 */
export async function createProject(
  options: ProjectConfig,
  cliInput: CreateProjectOptions = {},
): Promise<Result<string, ProjectCreationError>> {
  return Result.gen(async function* () {
    const projectDir = options.projectDir;
    const isConvex = options.backend === "convex";

    // Ensure project directory exists
    yield* Result.await(
      Result.tryPromise({
        try: () => fs.ensureDir(projectDir),
        catch: (e) =>
          new ProjectCreationError({
            phase: "directory-setup",
            message: `Failed to create project directory: ${e instanceof Error ? e.message : String(e)}`,
            cause: e,
          }),
      }),
    );

    // Generate virtual project using Result-based API
    const tree = yield* Result.await(
      generate({
        config: options,
        templates: EMBEDDED_TEMPLATES,
        version: getLatestCLIVersion(),
      }).then((result) =>
        result.mapError(
          (e) =>
            new ProjectCreationError({
              phase: e.phase || "template-generation",
              message: e.message,
              cause: e,
            }),
        ),
      ),
    );

    // Write tree to filesystem using Result-based API
    yield* Result.await(
      writeTree(tree, projectDir).then((result) =>
        result.mapError(
          (e) =>
            new ProjectCreationError({
              phase: "file-writing",
              message: e.message,
              cause: e,
            }),
        ),
      ),
    );

    // Set package manager version
    yield* Result.await(setPackageManagerVersion(projectDir, options.packageManager));

    // Setup database if needed
    if (!isConvex && options.database !== "none") {
      yield* Result.await(
        Result.tryPromise({
          try: () => setupDatabase(options, cliInput),
          catch: (e) =>
            new ProjectCreationError({
              phase: "database-setup",
              message: `Failed to setup database: ${e instanceof Error ? e.message : String(e)}`,
              cause: e,
            }),
        }),
      );
    }

    // Setup addons if any
    if (options.addons.length > 0 && options.addons[0] !== "none") {
      yield* Result.await(
        Result.tryPromise({
          try: () => setupAddons(options),
          catch: (e) =>
            new ProjectCreationError({
              phase: "addons-setup",
              message: `Failed to setup addons: ${e instanceof Error ? e.message : String(e)}`,
              cause: e,
            }),
        }),
      );
    }

    // Format project
    yield* Result.await(formatProject(projectDir));

    if (!isSilent()) log.success("Project template successfully scaffolded!");

    // Install dependencies if requested
    if (options.install) {
      yield* Result.await(
        installDependencies({
          projectDir,
          packageManager: options.packageManager,
        }),
      );
    }

    // Initialize git if requested
    yield* Result.await(initializeGit(projectDir, options.git));

    // Display post-install instructions
    if (!isSilent()) {
      await displayPostInstallInstructions({
        ...options,
        depsInstalled: options.install,
      });
    }

    return Result.ok(projectDir);
  });
}

async function setPackageManagerVersion(
  projectDir: string,
  packageManager: ProjectConfig["packageManager"],
): Promise<Result<void, ProjectCreationError>> {
  const pkgJsonPath = path.join(projectDir, "package.json");

  if (!(await fs.pathExists(pkgJsonPath))) {
    return Result.ok(undefined);
  }

  // First, try to get the version
  const versionResult = await Result.tryPromise({
    try: async () => {
      // Run in a neutral directory to avoid local package manager shims affecting lookup.
      const { stdout } = await $({ cwd: os.tmpdir() })`${packageManager} -v`;
      return stdout.trim();
    },
    catch: () => null, // Return null if we can't get version
  });

  // Now update the package.json
  return Result.tryPromise({
    try: async () => {
      const pkgJson = await fs.readJson(pkgJsonPath);

      if (versionResult.isOk() && versionResult.value) {
        pkgJson.packageManager = `${packageManager}@${versionResult.value}`;
      } else {
        // If we can't get the version, just remove the packageManager field
        delete pkgJson.packageManager;
      }

      await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
    },
    catch: (e) =>
      new ProjectCreationError({
        phase: "package-manager-version",
        message: `Failed to set package manager version: ${e instanceof Error ? e.message : String(e)}`,
        cause: e,
      }),
  });
}


================================================
FILE: apps/cli/src/helpers/core/db-setup-options.ts
================================================
import type { DatabaseSetup, DbSetupOptions } from "../../types";
import { isSilent } from "
Download .txt
gitextract_1fybze6m/

├── .github/
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   └── workflows/
│       ├── pr-preview.yaml
│       ├── release.yaml
│       └── test.yaml
├── .gitignore
├── .oxfmtrc.json
├── AGENTS.md
├── LICENSE
├── README.md
├── apps/
│   ├── cli/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── bunfig.toml
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── cli.ts
│   │   │   ├── commands/
│   │   │   │   ├── history.ts
│   │   │   │   └── meta.ts
│   │   │   ├── constants.ts
│   │   │   ├── helpers/
│   │   │   │   ├── addons/
│   │   │   │   │   ├── addons-setup.ts
│   │   │   │   │   ├── evlog-setup.ts
│   │   │   │   │   ├── fumadocs-setup.ts
│   │   │   │   │   ├── mcp-setup.ts
│   │   │   │   │   ├── oxlint-setup.ts
│   │   │   │   │   ├── skills-setup.ts
│   │   │   │   │   ├── starlight-setup.ts
│   │   │   │   │   ├── tauri-setup.ts
│   │   │   │   │   ├── tui-setup.ts
│   │   │   │   │   ├── ultracite-setup.ts
│   │   │   │   │   └── wxt-setup.ts
│   │   │   │   ├── core/
│   │   │   │   │   ├── add-handler.ts
│   │   │   │   │   ├── command-handlers.ts
│   │   │   │   │   ├── convex-codegen.ts
│   │   │   │   │   ├── create-project.ts
│   │   │   │   │   ├── db-setup-options.ts
│   │   │   │   │   ├── db-setup.ts
│   │   │   │   │   ├── detect-project-config.ts
│   │   │   │   │   ├── git.ts
│   │   │   │   │   ├── install-dependencies.ts
│   │   │   │   │   └── post-installation.ts
│   │   │   │   └── database-providers/
│   │   │   │       ├── d1-setup.ts
│   │   │   │       ├── docker-compose-setup.ts
│   │   │   │       ├── mongodb-atlas-setup.ts
│   │   │   │       ├── neon-setup.ts
│   │   │   │       ├── planetscale-setup.ts
│   │   │   │       ├── prisma-postgres-setup.ts
│   │   │   │       ├── supabase-setup.ts
│   │   │   │       └── turso-setup.ts
│   │   │   ├── index.ts
│   │   │   ├── mcp.ts
│   │   │   ├── prompts/
│   │   │   │   ├── addons.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── auth.ts
│   │   │   │   ├── backend.ts
│   │   │   │   ├── config-prompts.ts
│   │   │   │   ├── database-setup.ts
│   │   │   │   ├── database.ts
│   │   │   │   ├── examples.ts
│   │   │   │   ├── frontend.ts
│   │   │   │   ├── git.ts
│   │   │   │   ├── install.ts
│   │   │   │   ├── navigable-group.ts
│   │   │   │   ├── navigable.ts
│   │   │   │   ├── orm.ts
│   │   │   │   ├── package-manager.ts
│   │   │   │   ├── payments.ts
│   │   │   │   ├── project-name.ts
│   │   │   │   ├── runtime.ts
│   │   │   │   ├── server-deploy.ts
│   │   │   │   └── web-deploy.ts
│   │   │   ├── types.ts
│   │   │   ├── utils/
│   │   │   │   ├── add-package-deps.ts
│   │   │   │   ├── analytics.ts
│   │   │   │   ├── bts-config.ts
│   │   │   │   ├── command-exists.ts
│   │   │   │   ├── compatibility-rules.ts
│   │   │   │   ├── compatibility.ts
│   │   │   │   ├── config-processing.ts
│   │   │   │   ├── config-validation.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── display-config.ts
│   │   │   │   ├── docker-utils.ts
│   │   │   │   ├── env-utils.ts
│   │   │   │   ├── errors.ts
│   │   │   │   ├── external-commands.ts
│   │   │   │   ├── file-formatter.ts
│   │   │   │   ├── get-latest-cli-version.ts
│   │   │   │   ├── get-package-manager.ts
│   │   │   │   ├── input-hardening.ts
│   │   │   │   ├── navigation.ts
│   │   │   │   ├── open-url.ts
│   │   │   │   ├── package-runner.ts
│   │   │   │   ├── project-directory.ts
│   │   │   │   ├── project-history.ts
│   │   │   │   ├── project-name-validation.ts
│   │   │   │   ├── render-title.ts
│   │   │   │   ├── sponsors.ts
│   │   │   │   ├── telemetry.ts
│   │   │   │   ├── templates.ts
│   │   │   │   ├── terminal-output.ts
│   │   │   │   └── ts-morph.ts
│   │   │   ├── validation.ts
│   │   │   └── virtual.ts
│   │   ├── test/
│   │   │   ├── add-handler.test.ts
│   │   │   ├── addon-options.test.ts
│   │   │   ├── addon-setup-regressions.test.ts
│   │   │   ├── addons.test.ts
│   │   │   ├── api.test.ts
│   │   │   ├── auth.test.ts
│   │   │   ├── backend-runtime.test.ts
│   │   │   ├── basic-configurations.test.ts
│   │   │   ├── benchmark.test.ts
│   │   │   ├── clerk-matrix.test.ts
│   │   │   ├── cli-validation.test.ts
│   │   │   ├── cloudflare-db-clients.test.ts
│   │   │   ├── database-orm.test.ts
│   │   │   ├── database-setup.test.ts
│   │   │   ├── db-setup-mode-resolution.test.ts
│   │   │   ├── db-setup-options.test.ts
│   │   │   ├── deployment.test.ts
│   │   │   ├── dry-run.test.ts
│   │   │   ├── electrobun-addon.test.ts
│   │   │   ├── examples.test.ts
│   │   │   ├── external-commands.test.ts
│   │   │   ├── frontend.test.ts
│   │   │   ├── index.test.ts
│   │   │   ├── input-schemas.test.ts
│   │   │   ├── integration.test.ts
│   │   │   ├── mcp.test.ts
│   │   │   ├── project-name-validation.test.ts
│   │   │   ├── readme.test.ts
│   │   │   ├── schema-command.test.ts
│   │   │   ├── setup.ts
│   │   │   ├── silent-create-output.test.ts
│   │   │   ├── sponsors.test.ts
│   │   │   ├── tauri-setup.test.ts
│   │   │   ├── test-utils.ts
│   │   │   ├── tui-setup.test.ts
│   │   │   └── ultracite-setup.test.ts
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   └── web/
│       ├── .eslintrc.json
│       ├── .gitignore
│       ├── .vercelignore
│       ├── README.md
│       ├── cli.json
│       ├── components.json
│       ├── content/
│       │   └── docs/
│       │       ├── analytics.mdx
│       │       ├── bts-config.mdx
│       │       ├── cli/
│       │       │   ├── agent-workflows.mdx
│       │       │   ├── compatibility.mdx
│       │       │   ├── index.mdx
│       │       │   ├── meta.json
│       │       │   ├── options.mdx
│       │       │   ├── programmatic-api.mdx
│       │       │   └── prompts.mdx
│       │       ├── contributing.mdx
│       │       ├── faq.mdx
│       │       ├── guides/
│       │       │   ├── cloudflare-alchemy.mdx
│       │       │   ├── index.mdx
│       │       │   └── meta.json
│       │       ├── index.mdx
│       │       ├── meta.json
│       │       └── project-structure.mdx
│       ├── next.config.ts
│       ├── package.json
│       ├── postcss.config.mjs
│       ├── public/
│       │   ├── _headers
│       │   ├── favicon/
│       │   │   └── site.webmanifest
│       │   └── robots.txt
│       ├── scripts/
│       │   └── generate-schema.ts
│       ├── source.config.ts
│       ├── src/
│       │   ├── app/
│       │   │   ├── (home)/
│       │   │   │   ├── _components/
│       │   │   │   │   ├── FeatureCard.tsx
│       │   │   │   │   ├── code-container.tsx
│       │   │   │   │   ├── command-section.tsx
│       │   │   │   │   ├── footer.tsx
│       │   │   │   │   ├── hero-section.tsx
│       │   │   │   │   ├── icons.tsx
│       │   │   │   │   ├── npm-package.tsx
│       │   │   │   │   ├── shiny-text.tsx
│       │   │   │   │   ├── sponsors-section.tsx
│       │   │   │   │   ├── stats-section.tsx
│       │   │   │   │   └── testimonials.tsx
│       │   │   │   ├── analytics/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── analytics-header.tsx
│       │   │   │   │   │   ├── analytics-helpers.ts
│       │   │   │   │   │   ├── analytics-page.tsx
│       │   │   │   │   │   ├── analytics-sources.tsx
│       │   │   │   │   │   ├── chart-card.tsx
│       │   │   │   │   │   ├── dev-environment-charts.tsx
│       │   │   │   │   │   ├── evil-chart-utils.ts
│       │   │   │   │   │   ├── live-logs.tsx
│       │   │   │   │   │   ├── metrics-cards.tsx
│       │   │   │   │   │   ├── preference-chart-card.tsx
│       │   │   │   │   │   ├── section-header.tsx
│       │   │   │   │   │   ├── stack-configuration-charts.tsx
│       │   │   │   │   │   ├── timeline-charts.tsx
│       │   │   │   │   │   └── types.ts
│       │   │   │   │   ├── analytics-client.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── layout.tsx
│       │   │   │   ├── new/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── action-buttons.tsx
│       │   │   │   │   │   ├── code-viewer.tsx
│       │   │   │   │   │   ├── file-explorer.tsx
│       │   │   │   │   │   ├── get-badge-color.ts
│       │   │   │   │   │   ├── preset-dropdown.tsx
│       │   │   │   │   │   ├── preview-panel.tsx
│       │   │   │   │   │   ├── share-button.tsx
│       │   │   │   │   │   ├── special-sponsors-panel.tsx
│       │   │   │   │   │   ├── stack-builder/
│       │   │   │   │   │   │   ├── index.tsx
│       │   │   │   │   │   │   ├── selected-stack-badges.tsx
│       │   │   │   │   │   │   ├── tech-categories.tsx
│       │   │   │   │   │   │   └── use-stack-builder.ts
│       │   │   │   │   │   ├── tech-icon.tsx
│       │   │   │   │   │   ├── utils.ts
│       │   │   │   │   │   └── yolo-toggle.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   ├── page.tsx
│       │   │   │   ├── showcase/
│       │   │   │   │   ├── _components/
│       │   │   │   │   │   ├── ShowcaseItem.tsx
│       │   │   │   │   │   └── showcase-page.tsx
│       │   │   │   │   └── page.tsx
│       │   │   │   └── stack/
│       │   │   │       ├── _components/
│       │   │   │       │   └── stack-display.tsx
│       │   │   │       └── page.tsx
│       │   │   ├── api/
│       │   │   │   ├── preview/
│       │   │   │   │   └── route.ts
│       │   │   │   └── search/
│       │   │   │       └── route.ts
│       │   │   ├── docs/
│       │   │   │   ├── [[...slug]]/
│       │   │   │   │   └── page.tsx
│       │   │   │   └── layout.tsx
│       │   │   ├── global.css
│       │   │   ├── layout.config.tsx
│       │   │   ├── layout.tsx
│       │   │   ├── llms-full.txt/
│       │   │   │   └── route.ts
│       │   │   ├── llms.mdx/
│       │   │   │   └── [[...slug]]/
│       │   │   │       └── route.ts
│       │   │   ├── manifest.ts
│       │   │   ├── not-found.tsx
│       │   │   ├── og/
│       │   │   │   └── docs/
│       │   │   │       └── [...slug]/
│       │   │   │           └── route.tsx
│       │   │   └── sitemap.ts
│       │   ├── components/
│       │   │   ├── ai/
│       │   │   │   └── page-actions.tsx
│       │   │   ├── evilcharts/
│       │   │   │   ├── charts/
│       │   │   │   │   ├── area-chart.tsx
│       │   │   │   │   ├── bar-chart.tsx
│       │   │   │   │   ├── line-chart.tsx
│       │   │   │   │   ├── pie-chart.tsx
│       │   │   │   │   ├── radar-chart.tsx
│       │   │   │   │   └── radial-chart.tsx
│       │   │   │   └── ui/
│       │   │   │       ├── background.tsx
│       │   │   │       ├── chart.tsx
│       │   │   │       ├── dot.tsx
│       │   │   │       ├── evil-brush.tsx
│       │   │   │       ├── legend.tsx
│       │   │   │       └── tooltip.tsx
│       │   │   ├── providers.tsx
│       │   │   ├── special-sponsor-banner.tsx
│       │   │   ├── theme-toggle.tsx
│       │   │   └── ui/
│       │   │       ├── accordion.tsx
│       │   │       ├── button.tsx
│       │   │       ├── card.tsx
│       │   │       ├── dialog.tsx
│       │   │       ├── dropdown-menu.tsx
│       │   │       ├── file-tree.tsx
│       │   │       ├── hover-card.tsx
│       │   │       ├── input.tsx
│       │   │       ├── kibo-ui/
│       │   │       │   ├── code-block/
│       │   │       │   │   ├── index.tsx
│       │   │       │   │   └── server.tsx
│       │   │       │   └── qr-code/
│       │   │       │       ├── index.tsx
│       │   │       │       └── server.tsx
│       │   │       ├── scroll-area.tsx
│       │   │       ├── select.tsx
│       │   │       ├── share-dialog.tsx
│       │   │       ├── skeleton.tsx
│       │   │       ├── sonner.tsx
│       │   │       ├── spinner.tsx
│       │   │       ├── switch.tsx
│       │   │       ├── tabs.tsx
│       │   │       ├── tech-badge.tsx
│       │   │       ├── toggle.tsx
│       │   │       └── tooltip.tsx
│       │   └── lib/
│       │       ├── constant.ts
│       │       ├── get-llm-text.ts
│       │       ├── sanitize-stack-addons.ts
│       │       ├── search-config.ts
│       │       ├── source.ts
│       │       ├── sponsor-utils.ts
│       │       ├── sponsors.ts
│       │       ├── stack-url-keys.ts
│       │       ├── stack-url-state.client.ts
│       │       ├── stack-url-state.ts
│       │       ├── stack-utils.ts
│       │       ├── types.ts
│       │       └── utils.ts
│       ├── test/
│       │   └── stack-builder-compatibility.test.ts
│       └── tsconfig.json
├── bunfig.toml
├── changelogithub.config.ts
├── lefthook.yml
├── package.json
├── packages/
│   ├── backend/
│   │   ├── .gitignore
│   │   ├── convex/
│   │   │   ├── README.md
│   │   │   ├── _generated/
│   │   │   │   ├── api.d.ts
│   │   │   │   ├── api.js
│   │   │   │   ├── dataModel.d.ts
│   │   │   │   ├── server.d.ts
│   │   │   │   └── server.js
│   │   │   ├── analytics.ts
│   │   │   ├── analytics_date_utils.ts
│   │   │   ├── convex.config.ts
│   │   │   ├── healthCheck.ts
│   │   │   ├── hooks.ts
│   │   │   ├── http.ts
│   │   │   ├── schema.ts
│   │   │   ├── showcase.ts
│   │   │   ├── stats.ts
│   │   │   ├── testimonials.ts
│   │   │   └── tsconfig.json
│   │   └── package.json
│   ├── create-bts/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── cli.js
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   └── package.json
│   ├── template-generator/
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   └── generate-templates.ts
│   │   ├── src/
│   │   │   ├── bts-config.ts
│   │   │   ├── core/
│   │   │   │   ├── template-processor.ts
│   │   │   │   ├── template-reader.ts
│   │   │   │   └── virtual-fs.ts
│   │   │   ├── fs-writer.ts
│   │   │   ├── generator.ts
│   │   │   ├── index.ts
│   │   │   ├── post-process/
│   │   │   │   ├── catalogs.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── package-configs.ts
│   │   │   ├── processors/
│   │   │   │   ├── addons-deps.ts
│   │   │   │   ├── alchemy-plugins.ts
│   │   │   │   ├── api-deps.ts
│   │   │   │   ├── auth-deps.ts
│   │   │   │   ├── auth-plugins.ts
│   │   │   │   ├── backend-deps.ts
│   │   │   │   ├── db-deps.ts
│   │   │   │   ├── deploy-deps.ts
│   │   │   │   ├── env-deps.ts
│   │   │   │   ├── env-vars.ts
│   │   │   │   ├── examples-deps.ts
│   │   │   │   ├── frontend-deps.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── infra-deps.ts
│   │   │   │   ├── nx-generator.ts
│   │   │   │   ├── payments-deps.ts
│   │   │   │   ├── pwa-plugins.ts
│   │   │   │   ├── readme-generator.ts
│   │   │   │   ├── runtime-deps.ts
│   │   │   │   ├── turbo-generator.ts
│   │   │   │   └── workspace-deps.ts
│   │   │   ├── template-handlers/
│   │   │   │   ├── addons.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── auth.ts
│   │   │   │   ├── backend.ts
│   │   │   │   ├── base.ts
│   │   │   │   ├── database.ts
│   │   │   │   ├── deploy.ts
│   │   │   │   ├── examples.ts
│   │   │   │   ├── extras.ts
│   │   │   │   ├── frontend.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── packages.ts
│   │   │   │   ├── payments.ts
│   │   │   │   └── utils.ts
│   │   │   ├── templates.generated.ts
│   │   │   ├── types.ts
│   │   │   └── utils/
│   │   │       ├── add-deps.ts
│   │   │       ├── db-scripts.ts
│   │   │       └── reproducible-command.ts
│   │   ├── templates/
│   │   │   ├── addons/
│   │   │   │   ├── biome/
│   │   │   │   │   └── biome.json.hbs
│   │   │   │   ├── electrobun/
│   │   │   │   │   └── apps/
│   │   │   │   │       └── desktop/
│   │   │   │   │           ├── .gitignore
│   │   │   │   │           ├── electrobun.config.ts.hbs
│   │   │   │   │           ├── package.json.hbs
│   │   │   │   │           ├── src/
│   │   │   │   │           │   └── bun/
│   │   │   │   │           │       └── index.ts.hbs
│   │   │   │   │           └── tsconfig.json.hbs
│   │   │   │   ├── husky/
│   │   │   │   │   └── .husky/
│   │   │   │   │       └── pre-commit
│   │   │   │   ├── lefthook/
│   │   │   │   │   └── lefthook.yml.hbs
│   │   │   │   └── pwa/
│   │   │   │       └── apps/
│   │   │   │           └── web/
│   │   │   │               ├── next/
│   │   │   │               │   ├── public/
│   │   │   │               │   │   └── favicon/
│   │   │   │               │   │       └── site.webmanifest.hbs
│   │   │   │               │   └── src/
│   │   │   │               │       └── app/
│   │   │   │               │           └── manifest.ts.hbs
│   │   │   │               └── vite/
│   │   │   │                   └── pwa-assets.config.ts.hbs
│   │   │   ├── api/
│   │   │   │   ├── orpc/
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── astro/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── pages/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               └── [...rest].ts.hbs
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── rpc/
│   │   │   │   │   │   │                   └── [[...rest]]/
│   │   │   │   │   │   │                       └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── plugins/
│   │   │   │   │   │   │   │       ├── orpc.client.ts.hbs
│   │   │   │   │   │   │   │       └── orpc.server.ts.hbs
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               ├── [...].ts.hbs
│   │   │   │   │   │   │               └── index.ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       ├── lib/
│   │   │   │   │   │   │       │   └── orpc.server.ts.hbs
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── rpc/
│   │   │   │   │   │   │               └── [...rest]/
│   │   │   │   │   │   │                   └── +server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── rpc/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   └── utils/
│   │   │   │   │   │       └── orpc.ts.hbs
│   │   │   │   │   ├── server/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── context.ts.hbs
│   │   │   │   │   │   │   ├── index.ts.hbs
│   │   │   │   │   │   │   └── routers/
│   │   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   └── web/
│   │   │   │   │       ├── astro/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       └── lib/
│   │   │   │   │       │           └── orpc.ts.hbs
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       └── plugins/
│   │   │   │   │       │           ├── orpc.ts.hbs
│   │   │   │   │       │           └── vue-query.ts.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   └── base/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           └── utils/
│   │   │   │   │       │               └── orpc.ts.hbs
│   │   │   │   │       ├── solid/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       └── utils/
│   │   │   │   │       │           └── orpc.ts.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               └── lib/
│   │   │   │   │                   └── orpc.ts.hbs
│   │   │   │   └── trpc/
│   │   │   │       ├── fullstack/
│   │   │   │       │   ├── next/
│   │   │   │       │   │   └── src/
│   │   │   │       │   │       └── app/
│   │   │   │       │   │           └── api/
│   │   │   │       │   │               └── trpc/
│   │   │   │       │   │                   └── [trpc]/
│   │   │   │       │   │                       └── route.ts.hbs
│   │   │   │       │   └── tanstack-start/
│   │   │   │       │       └── src/
│   │   │   │       │           └── routes/
│   │   │   │       │               └── api/
│   │   │   │       │                   └── trpc/
│   │   │   │       │                       └── $.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   └── utils/
│   │   │   │       │       └── trpc.ts.hbs
│   │   │   │       ├── server/
│   │   │   │       │   ├── _gitignore
│   │   │   │       │   ├── package.json.hbs
│   │   │   │       │   ├── src/
│   │   │   │       │   │   ├── context.ts.hbs
│   │   │   │       │   │   ├── index.ts.hbs
│   │   │   │       │   │   └── routers/
│   │   │   │       │   │       └── index.ts.hbs
│   │   │   │       │   └── tsconfig.json.hbs
│   │   │   │       └── web/
│   │   │   │           └── react/
│   │   │   │               └── base/
│   │   │   │                   └── src/
│   │   │   │                       └── utils/
│   │   │   │                           └── trpc.ts.hbs
│   │   │   ├── auth/
│   │   │   │   ├── better-auth/
│   │   │   │   │   ├── convex/
│   │   │   │   │   │   ├── backend/
│   │   │   │   │   │   │   └── convex/
│   │   │   │   │   │   │       ├── auth.config.ts.hbs
│   │   │   │   │   │   │       ├── auth.ts.hbs
│   │   │   │   │   │   │       ├── http.ts.hbs
│   │   │   │   │   │   │       └── privateData.ts.hbs
│   │   │   │   │   │   ├── native/
│   │   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   │   └── lib/
│   │   │   │   │   │   │   │       └── auth-client.ts.hbs
│   │   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │   │       └── components/
│   │   │   │   │   │   │           ├── sign-in.tsx.hbs
│   │   │   │   │   │   │           └── sign-up.tsx.hbs
│   │   │   │   │   │   └── web/
│   │   │   │   │   │       └── react/
│   │   │   │   │   │           ├── next/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── app/
│   │   │   │   │   │           │       │   ├── api/
│   │   │   │   │   │           │       │   │   └── auth/
│   │   │   │   │   │           │       │   │       └── [...all]/
│   │   │   │   │   │           │       │   │           └── route.ts.hbs
│   │   │   │   │   │           │       │   └── dashboard/
│   │   │   │   │   │           │       │       └── page.tsx.hbs
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       └── lib/
│   │   │   │   │   │           │           ├── auth-client.ts.hbs
│   │   │   │   │   │           │           └── auth-server.ts.hbs
│   │   │   │   │   │           ├── react-router/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       ├── lib/
│   │   │   │   │   │           │       │   └── auth-client.ts.hbs
│   │   │   │   │   │           │       └── routes/
│   │   │   │   │   │           │           └── dashboard.tsx.hbs
│   │   │   │   │   │           ├── tanstack-router/
│   │   │   │   │   │           │   └── src/
│   │   │   │   │   │           │       ├── components/
│   │   │   │   │   │           │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │           │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │           │       │   └── user-menu.tsx.hbs
│   │   │   │   │   │           │       ├── lib/
│   │   │   │   │   │           │       │   └── auth-client.ts.hbs
│   │   │   │   │   │           │       └── routes/
│   │   │   │   │   │           │           └── dashboard.tsx.hbs
│   │   │   │   │   │           └── tanstack-start/
│   │   │   │   │   │               └── src/
│   │   │   │   │   │                   ├── components/
│   │   │   │   │   │                   │   ├── sign-in-form.tsx.hbs
│   │   │   │   │   │                   │   ├── sign-up-form.tsx.hbs
│   │   │   │   │   │                   │   └── user-menu.tsx.hbs
│   │   │   │   │   │                   ├── lib/
│   │   │   │   │   │                   │   ├── auth-client.ts.hbs
│   │   │   │   │   │                   │   └── auth-server.ts.hbs
│   │   │   │   │   │                   └── routes/
│   │   │   │   │   │                       ├── api/
│   │   │   │   │   │                       │   └── auth/
│   │   │   │   │   │                       │       └── $.ts.hbs
│   │   │   │   │   │                       └── dashboard.tsx.hbs
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── astro/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       ├── env.d.ts.hbs
│   │   │   │   │   │   │       ├── middleware.ts.hbs
│   │   │   │   │   │   │       └── pages/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── auth/
│   │   │   │   │   │   │                   └── [...all].ts.hbs
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── auth/
│   │   │   │   │   │   │                   └── [...all]/
│   │   │   │   │   │   │                       └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── api/
│   │   │   │   │   │   │           └── auth/
│   │   │   │   │   │   │               └── [...all].ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── hooks.server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── auth/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   └── lib/
│   │   │   │   │   │   │       └── auth-client.ts.hbs
│   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── sign-in.tsx.hbs
│   │   │   │   │   │   │       └── sign-up.tsx.hbs
│   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   └── (drawer)/
│   │   │   │   │   │       │       └── index.tsx.hbs
│   │   │   │   │   │       └── components/
│   │   │   │   │   │           ├── sign-in.tsx.hbs
│   │   │   │   │   │           └── sign-up.tsx.hbs
│   │   │   │   │   ├── server/
│   │   │   │   │   │   ├── base/
│   │   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   │   └── index.ts.hbs
│   │   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   │   └── db/
│   │   │   │   │   │       ├── drizzle/
│   │   │   │   │   │       │   ├── mysql/
│   │   │   │   │   │       │   │   └── src/
│   │   │   │   │   │       │   │       └── schema/
│   │   │   │   │   │       │   │           └── auth.ts.hbs
│   │   │   │   │   │       │   ├── postgres/
│   │   │   │   │   │       │   │   └── src/
│   │   │   │   │   │       │   │       └── schema/
│   │   │   │   │   │       │   │           └── auth.ts.hbs
│   │   │   │   │   │       │   └── sqlite/
│   │   │   │   │   │       │       └── src/
│   │   │   │   │   │       │           └── schema/
│   │   │   │   │   │       │               └── auth.ts.hbs
│   │   │   │   │   │       ├── mongoose/
│   │   │   │   │   │       │   └── mongodb/
│   │   │   │   │   │       │       └── src/
│   │   │   │   │   │       │           └── models/
│   │   │   │   │   │       │               └── auth.model.ts.hbs
│   │   │   │   │   │       └── prisma/
│   │   │   │   │   │           ├── mongodb/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           ├── mysql/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           ├── postgres/
│   │   │   │   │   │           │   └── prisma/
│   │   │   │   │   │           │       └── schema/
│   │   │   │   │   │           │           └── auth.prisma.hbs
│   │   │   │   │   │           └── sqlite/
│   │   │   │   │   │               └── prisma/
│   │   │   │   │   │                   └── schema/
│   │   │   │   │   │                       └── auth.prisma.hbs
│   │   │   │   │   └── web/
│   │   │   │   │       ├── astro/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── SignInForm.astro.hbs
│   │   │   │   │       │       │   └── SignUpForm.astro.hbs
│   │   │   │   │       │       ├── lib/
│   │   │   │   │       │       │   └── auth-client.ts.hbs
│   │   │   │   │       │       └── pages/
│   │   │   │   │       │           ├── dashboard.astro.hbs
│   │   │   │   │       │           ├── login.astro.hbs
│   │   │   │   │       │           └── signup.astro.hbs
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── SignInForm.vue.hbs
│   │   │   │   │       │       │   ├── SignUpForm.vue.hbs
│   │   │   │   │       │       │   └── UserMenu.vue.hbs
│   │   │   │   │       │       ├── middleware/
│   │   │   │   │       │       │   └── auth.ts.hbs
│   │   │   │   │       │       ├── pages/
│   │   │   │   │       │       │   ├── dashboard.vue.hbs
│   │   │   │   │       │       │   └── login.vue.hbs
│   │   │   │   │       │       └── plugins/
│   │   │   │   │       │           └── auth-client.ts.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   ├── base/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── lib/
│   │   │   │   │       │   │           └── auth-client.ts.hbs
│   │   │   │   │       │   ├── next/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── app/
│   │   │   │   │       │   │       │   ├── dashboard/
│   │   │   │   │       │   │       │   │   ├── dashboard.tsx.hbs
│   │   │   │   │       │   │       │   │   └── page.tsx.hbs
│   │   │   │   │       │   │       │   └── login/
│   │   │   │   │       │   │       │       └── page.tsx.hbs
│   │   │   │   │       │   │       └── components/
│   │   │   │   │       │   │           ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │           ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │           └── user-menu.tsx.hbs
│   │   │   │   │       │   ├── react-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── components/
│   │   │   │   │       │   │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           ├── dashboard.tsx.hbs
│   │   │   │   │       │   │           └── login.tsx.hbs
│   │   │   │   │       │   ├── tanstack-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       ├── components/
│   │   │   │   │       │   │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │   │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │   │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           ├── dashboard.tsx.hbs
│   │   │   │   │       │   │           └── login.tsx.hbs
│   │   │   │   │       │   └── tanstack-start/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           ├── components/
│   │   │   │   │       │           │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │           │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │           │   └── user-menu.tsx.hbs
│   │   │   │   │       │           ├── functions/
│   │   │   │   │       │           │   └── get-user.ts.hbs
│   │   │   │   │       │           ├── middleware/
│   │   │   │   │       │           │   └── auth.ts.hbs
│   │   │   │   │       │           └── routes/
│   │   │   │   │       │               ├── dashboard.tsx.hbs
│   │   │   │   │       │               └── login.tsx.hbs
│   │   │   │   │       ├── solid/
│   │   │   │   │       │   └── src/
│   │   │   │   │       │       ├── components/
│   │   │   │   │       │       │   ├── sign-in-form.tsx.hbs
│   │   │   │   │       │       │   ├── sign-up-form.tsx.hbs
│   │   │   │   │       │       │   └── user-menu.tsx.hbs
│   │   │   │   │       │       ├── lib/
│   │   │   │   │       │       │   └── auth-client.ts.hbs
│   │   │   │   │       │       └── routes/
│   │   │   │   │       │           ├── dashboard.tsx.hbs
│   │   │   │   │       │           └── login.tsx.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               ├── components/
│   │   │   │   │               │   ├── SignInForm.svelte.hbs
│   │   │   │   │               │   ├── SignUpForm.svelte.hbs
│   │   │   │   │               │   └── UserMenu.svelte.hbs
│   │   │   │   │               ├── lib/
│   │   │   │   │               │   └── auth-client.ts.hbs
│   │   │   │   │               └── routes/
│   │   │   │   │                   ├── dashboard/
│   │   │   │   │                   │   └── +page.svelte.hbs
│   │   │   │   │                   └── login/
│   │   │   │   │                       └── +page.svelte.hbs
│   │   │   │   └── clerk/
│   │   │   │       ├── convex/
│   │   │   │       │   ├── backend/
│   │   │   │       │   │   └── convex/
│   │   │   │       │   │       ├── auth.config.ts.hbs
│   │   │   │       │   │       └── privateData.ts.hbs
│   │   │   │       │   ├── native/
│   │   │   │       │   │   └── base/
│   │   │   │       │   │       ├── app/
│   │   │   │       │   │       │   └── (auth)/
│   │   │   │       │   │       │       ├── _layout.tsx.hbs
│   │   │   │       │   │       │       ├── sign-in.tsx.hbs
│   │   │   │       │   │       │       └── sign-up.tsx.hbs
│   │   │   │       │   │       └── components/
│   │   │   │       │   │           └── sign-out-button.tsx.hbs
│   │   │   │       │   └── web/
│   │   │   │       │       └── react/
│   │   │   │       │           ├── next/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       ├── app/
│   │   │   │       │           │       │   └── dashboard/
│   │   │   │       │           │       │       └── page.tsx.hbs
│   │   │   │       │           │       └── proxy.ts.hbs
│   │   │   │       │           ├── react-router/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       └── routes/
│   │   │   │       │           │           └── dashboard.tsx.hbs
│   │   │   │       │           ├── tanstack-router/
│   │   │   │       │           │   └── src/
│   │   │   │       │           │       └── routes/
│   │   │   │       │           │           └── dashboard.tsx.hbs
│   │   │   │       │           └── tanstack-start/
│   │   │   │       │               └── src/
│   │   │   │       │                   ├── routes/
│   │   │   │       │                   │   └── dashboard.tsx.hbs
│   │   │   │       │                   └── start.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   └── base/
│   │   │   │       │       ├── app/
│   │   │   │       │       │   └── (auth)/
│   │   │   │       │       │       ├── _layout.tsx.hbs
│   │   │   │       │       │       ├── sign-in.tsx.hbs
│   │   │   │       │       │       └── sign-up.tsx.hbs
│   │   │   │       │       ├── components/
│   │   │   │       │       │   └── sign-out-button.tsx.hbs
│   │   │   │       │       └── utils/
│   │   │   │       │           └── clerk-auth.ts.hbs
│   │   │   │       └── web/
│   │   │   │           └── react/
│   │   │   │               ├── base/
│   │   │   │               │   └── src/
│   │   │   │               │       └── utils/
│   │   │   │               │           └── clerk-auth.ts.hbs
│   │   │   │               ├── next/
│   │   │   │               │   └── src/
│   │   │   │               │       ├── app/
│   │   │   │               │       │   └── dashboard/
│   │   │   │               │       │       └── page.tsx.hbs
│   │   │   │               │       └── proxy.ts.hbs
│   │   │   │               ├── react-router/
│   │   │   │               │   └── src/
│   │   │   │               │       └── routes/
│   │   │   │               │           └── dashboard.tsx.hbs
│   │   │   │               ├── tanstack-router/
│   │   │   │               │   └── src/
│   │   │   │               │       └── routes/
│   │   │   │               │           └── dashboard.tsx.hbs
│   │   │   │               └── tanstack-start/
│   │   │   │                   └── src/
│   │   │   │                       ├── routes/
│   │   │   │                       │   └── dashboard.tsx.hbs
│   │   │   │                       └── start.ts.hbs
│   │   │   ├── backend/
│   │   │   │   ├── convex/
│   │   │   │   │   └── packages/
│   │   │   │   │       └── backend/
│   │   │   │   │           ├── _gitignore
│   │   │   │   │           ├── convex/
│   │   │   │   │           │   ├── README.md
│   │   │   │   │           │   ├── convex.config.ts.hbs
│   │   │   │   │           │   ├── healthCheck.ts.hbs
│   │   │   │   │           │   ├── schema.ts.hbs
│   │   │   │   │           │   └── tsconfig.json.hbs
│   │   │   │   │           └── package.json.hbs
│   │   │   │   └── server/
│   │   │   │       ├── base/
│   │   │   │       │   ├── _gitignore
│   │   │   │       │   ├── package.json.hbs
│   │   │   │       │   ├── tsconfig.json.hbs
│   │   │   │       │   └── tsdown.config.ts.hbs
│   │   │   │       ├── elysia/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── express/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── fastify/
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       └── hono/
│   │   │   │           └── src/
│   │   │   │               └── index.ts.hbs
│   │   │   ├── base/
│   │   │   │   ├── _gitignore
│   │   │   │   ├── package.json.hbs
│   │   │   │   └── tsconfig.json.hbs
│   │   │   ├── db/
│   │   │   │   ├── base/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── drizzle/
│   │   │   │   │   ├── base/
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── schema/
│   │   │   │   │   │           └── index.ts.hbs
│   │   │   │   │   ├── mysql/
│   │   │   │   │   │   ├── drizzle.config.ts.hbs
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   ├── postgres/
│   │   │   │   │   │   ├── drizzle.config.ts.hbs
│   │   │   │   │   │   └── src/
│   │   │   │   │   │       └── index.ts.hbs
│   │   │   │   │   └── sqlite/
│   │   │   │   │       ├── drizzle.config.ts.hbs
│   │   │   │   │       └── src/
│   │   │   │   │           └── index.ts.hbs
│   │   │   │   ├── mongoose/
│   │   │   │   │   └── mongodb/
│   │   │   │   │       └── src/
│   │   │   │   │           └── index.ts.hbs
│   │   │   │   └── prisma/
│   │   │   │       ├── mongodb/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── mysql/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       ├── postgres/
│   │   │   │       │   ├── prisma/
│   │   │   │       │   │   └── schema/
│   │   │   │       │   │       └── schema.prisma.hbs
│   │   │   │       │   ├── prisma.config.ts.hbs
│   │   │   │       │   └── src/
│   │   │   │       │       └── index.ts.hbs
│   │   │   │       └── sqlite/
│   │   │   │           ├── prisma/
│   │   │   │           │   └── schema/
│   │   │   │           │       └── schema.prisma.hbs
│   │   │   │           ├── prisma.config.ts.hbs
│   │   │   │           └── src/
│   │   │   │               └── index.ts.hbs
│   │   │   ├── db-setup/
│   │   │   │   └── docker-compose/
│   │   │   │       ├── mongodb/
│   │   │   │       │   └── docker-compose.yml.hbs
│   │   │   │       ├── mysql/
│   │   │   │       │   └── docker-compose.yml.hbs
│   │   │   │       └── postgres/
│   │   │   │           └── docker-compose.yml.hbs
│   │   │   ├── examples/
│   │   │   │   ├── ai/
│   │   │   │   │   ├── convex/
│   │   │   │   │   │   └── packages/
│   │   │   │   │   │       └── backend/
│   │   │   │   │   │           └── convex/
│   │   │   │   │   │               ├── agent.ts.hbs
│   │   │   │   │   │               └── chat.ts.hbs
│   │   │   │   │   ├── fullstack/
│   │   │   │   │   │   ├── next/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── app/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── ai/
│   │   │   │   │   │   │                   └── route.ts.hbs
│   │   │   │   │   │   ├── nuxt/
│   │   │   │   │   │   │   └── server/
│   │   │   │   │   │   │       └── api/
│   │   │   │   │   │   │           └── ai.post.ts.hbs
│   │   │   │   │   │   ├── svelte/
│   │   │   │   │   │   │   └── src/
│   │   │   │   │   │   │       └── routes/
│   │   │   │   │   │   │           └── api/
│   │   │   │   │   │   │               └── ai/
│   │   │   │   │   │   │                   └── +server.ts.hbs
│   │   │   │   │   │   └── tanstack-start/
│   │   │   │   │   │       └── src/
│   │   │   │   │   │           └── routes/
│   │   │   │   │   │               └── api/
│   │   │   │   │   │                   └── ai/
│   │   │   │   │   │                       └── $.ts.hbs
│   │   │   │   │   ├── native/
│   │   │   │   │   │   ├── bare/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── ai.tsx.hbs
│   │   │   │   │   │   │   └── polyfills.js
│   │   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   └── (drawer)/
│   │   │   │   │   │   │   │       └── ai.tsx.hbs
│   │   │   │   │   │   │   └── polyfills.js
│   │   │   │   │   │   └── uniwind/
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   └── (drawer)/
│   │   │   │   │   │       │       └── ai.tsx.hbs
│   │   │   │   │   │       └── polyfills.js
│   │   │   │   │   └── web/
│   │   │   │   │       ├── nuxt/
│   │   │   │   │       │   └── app/
│   │   │   │   │       │       └── pages/
│   │   │   │   │       │           └── ai.vue.hbs
│   │   │   │   │       ├── react/
│   │   │   │   │       │   ├── next/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── app/
│   │   │   │   │       │   │           └── ai/
│   │   │   │   │       │   │               └── page.tsx.hbs
│   │   │   │   │       │   ├── react-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           └── ai.tsx.hbs
│   │   │   │   │       │   ├── tanstack-router/
│   │   │   │   │       │   │   └── src/
│   │   │   │   │       │   │       └── routes/
│   │   │   │   │       │   │           └── ai.tsx.hbs
│   │   │   │   │       │   └── tanstack-start/
│   │   │   │   │       │       └── src/
│   │   │   │   │       │           └── routes/
│   │   │   │   │       │               └── ai.tsx.hbs
│   │   │   │   │       └── svelte/
│   │   │   │   │           └── src/
│   │   │   │   │               └── routes/
│   │   │   │   │                   └── ai/
│   │   │   │   │                       └── +page.svelte.hbs
│   │   │   │   └── todo/
│   │   │   │       ├── convex/
│   │   │   │       │   └── packages/
│   │   │   │       │       └── backend/
│   │   │   │       │           └── convex/
│   │   │   │       │               └── todos.ts.hbs
│   │   │   │       ├── native/
│   │   │   │       │   ├── bare/
│   │   │   │       │   │   └── app/
│   │   │   │       │   │       └── (drawer)/
│   │   │   │       │   │           └── todos.tsx.hbs
│   │   │   │       │   ├── unistyles/
│   │   │   │       │   │   └── app/
│   │   │   │       │   │       └── (drawer)/
│   │   │   │       │   │           └── todos.tsx.hbs
│   │   │   │       │   └── uniwind/
│   │   │   │       │       └── app/
│   │   │   │       │           └── (drawer)/
│   │   │   │       │               └── todos.tsx.hbs
│   │   │   │       ├── server/
│   │   │   │       │   ├── drizzle/
│   │   │   │       │   │   ├── base/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── routers/
│   │   │   │       │   │   │           └── todo.ts.hbs
│   │   │   │       │   │   ├── mysql/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── schema/
│   │   │   │       │   │   │           └── todo.ts
│   │   │   │       │   │   ├── postgres/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── schema/
│   │   │   │       │   │   │           └── todo.ts
│   │   │   │       │   │   └── sqlite/
│   │   │   │       │   │       └── src/
│   │   │   │       │   │           └── schema/
│   │   │   │       │   │               └── todo.ts
│   │   │   │       │   ├── mongoose/
│   │   │   │       │   │   ├── base/
│   │   │   │       │   │   │   └── src/
│   │   │   │       │   │   │       └── routers/
│   │   │   │       │   │   │           └── todo.ts.hbs
│   │   │   │       │   │   └── mongodb/
│   │   │   │       │   │       └── src/
│   │   │   │       │   │           └── models/
│   │   │   │       │   │               └── todo.model.ts.hbs
│   │   │   │       │   └── prisma/
│   │   │   │       │       ├── base/
│   │   │   │       │       │   └── src/
│   │   │   │       │       │       └── routers/
│   │   │   │       │       │           └── todo.ts.hbs
│   │   │   │       │       ├── mongodb/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       ├── mysql/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       ├── postgres/
│   │   │   │       │       │   └── prisma/
│   │   │   │       │       │       └── schema/
│   │   │   │       │       │           └── todo.prisma.hbs
│   │   │   │       │       └── sqlite/
│   │   │   │       │           └── prisma/
│   │   │   │       │               └── schema/
│   │   │   │       │                   └── todo.prisma.hbs
│   │   │   │       └── web/
│   │   │   │           ├── astro/
│   │   │   │           │   └── src/
│   │   │   │           │       └── pages/
│   │   │   │           │           └── todos.astro.hbs
│   │   │   │           ├── nuxt/
│   │   │   │           │   └── app/
│   │   │   │           │       └── pages/
│   │   │   │           │           └── todos.vue.hbs
│   │   │   │           ├── react/
│   │   │   │           │   ├── next/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── app/
│   │   │   │           │   │           └── todos/
│   │   │   │           │   │               └── page.tsx.hbs
│   │   │   │           │   ├── react-router/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── routes/
│   │   │   │           │   │           └── todos.tsx.hbs
│   │   │   │           │   ├── tanstack-router/
│   │   │   │           │   │   └── src/
│   │   │   │           │   │       └── routes/
│   │   │   │           │   │           └── todos.tsx.hbs
│   │   │   │           │   └── tanstack-start/
│   │   │   │           │       └── src/
│   │   │   │           │           └── routes/
│   │   │   │           │               └── todos.tsx.hbs
│   │   │   │           ├── solid/
│   │   │   │           │   └── src/
│   │   │   │           │       └── routes/
│   │   │   │           │           └── todos.tsx.hbs
│   │   │   │           └── svelte/
│   │   │   │               └── src/
│   │   │   │                   └── routes/
│   │   │   │                       └── todos/
│   │   │   │                           └── +page.svelte.hbs
│   │   │   ├── extras/
│   │   │   │   ├── _npmrc.hbs
│   │   │   │   ├── bunfig.toml.hbs
│   │   │   │   ├── env.d.ts.hbs
│   │   │   │   └── pnpm-workspace.yaml
│   │   │   ├── frontend/
│   │   │   │   ├── astro/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── astro.config.mjs.hbs
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── Header.astro.hbs
│   │   │   │   │   │   ├── layouts/
│   │   │   │   │   │   │   └── Layout.astro.hbs
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   └── index.astro.hbs
│   │   │   │   │   │   └── styles/
│   │   │   │   │   │       └── global.css
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── native/
│   │   │   │   │   ├── bare/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── (drawer)/
│   │   │   │   │   │   │   │   ├── (tabs)/
│   │   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   │   ├── index.tsx.hbs
│   │   │   │   │   │   │   │   │   └── two.tsx.hbs
│   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   │   ├── +not-found.tsx.hbs
│   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   └── modal.tsx.hbs
│   │   │   │   │   │   ├── app.json.hbs
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── container.tsx.hbs
│   │   │   │   │   │   │   ├── header-button.tsx.hbs
│   │   │   │   │   │   │   └── tabbar-icon.tsx.hbs
│   │   │   │   │   │   ├── lib/
│   │   │   │   │   │   │   ├── constants.ts.hbs
│   │   │   │   │   │   │   └── use-color-scheme.ts.hbs
│   │   │   │   │   │   ├── metro.config.js.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   ├── unistyles/
│   │   │   │   │   │   ├── _gitignore
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── (drawer)/
│   │   │   │   │   │   │   │   ├── (tabs)/
│   │   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   │   ├── index.tsx.hbs
│   │   │   │   │   │   │   │   │   └── two.tsx.hbs
│   │   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   │   ├── +html.tsx.hbs
│   │   │   │   │   │   │   ├── +not-found.tsx.hbs
│   │   │   │   │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │   │   │   └── modal.tsx.hbs
│   │   │   │   │   │   ├── app.json.hbs
│   │   │   │   │   │   ├── babel.config.js.hbs
│   │   │   │   │   │   ├── breakpoints.ts.hbs
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── container.tsx.hbs
│   │   │   │   │   │   │   ├── header-button.tsx.hbs
│   │   │   │   │   │   │   └── tabbar-icon.tsx.hbs
│   │   │   │   │   │   ├── index.js.hbs
│   │   │   │   │   │   ├── metro.config.js.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── theme.ts.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── unistyles.ts.hbs
│   │   │   │   │   └── uniwind/
│   │   │   │   │       ├── _gitignore
│   │   │   │   │       ├── app/
│   │   │   │   │       │   ├── (drawer)/
│   │   │   │   │       │   │   ├── (tabs)/
│   │   │   │   │       │   │   │   ├── _layout.tsx.hbs
│   │   │   │   │       │   │   │   ├── index.tsx.hbs
│   │   │   │   │       │   │   │   └── two.tsx.hbs
│   │   │   │   │       │   │   ├── _layout.tsx.hbs
│   │   │   │   │       │   │   └── index.tsx.hbs
│   │   │   │   │       │   ├── +not-found.tsx.hbs
│   │   │   │   │       │   ├── _layout.tsx.hbs
│   │   │   │   │       │   └── modal.tsx.hbs
│   │   │   │   │       ├── app.json.hbs
│   │   │   │   │       ├── components/
│   │   │   │   │       │   ├── container.tsx.hbs
│   │   │   │   │       │   └── theme-toggle.tsx.hbs
│   │   │   │   │       ├── contexts/
│   │   │   │   │       │   └── app-theme-context.tsx.hbs
│   │   │   │   │       ├── global.css
│   │   │   │   │       ├── metro.config.js.hbs
│   │   │   │   │       ├── package.json.hbs
│   │   │   │   │       ├── tsconfig.json.hbs
│   │   │   │   │       └── uniwind-env.d.ts
│   │   │   │   ├── nuxt/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── app/
│   │   │   │   │   │   ├── app.config.ts.hbs
│   │   │   │   │   │   ├── app.vue.hbs
│   │   │   │   │   │   ├── assets/
│   │   │   │   │   │   │   └── css/
│   │   │   │   │   │   │       └── main.css
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── Header.vue.hbs
│   │   │   │   │   │   ├── layouts/
│   │   │   │   │   │   │   └── default.vue.hbs
│   │   │   │   │   │   └── pages/
│   │   │   │   │   │       └── index.vue.hbs
│   │   │   │   │   ├── nuxt.config.ts.hbs
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── public/
│   │   │   │   │   │   └── robots.txt
│   │   │   │   │   ├── server/
│   │   │   │   │   │   └── tsconfig.json
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── react/
│   │   │   │   │   ├── next/
│   │   │   │   │   │   ├── next-env.d.ts.hbs
│   │   │   │   │   │   ├── next.config.ts.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── postcss.config.mjs.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   │   ├── layout.tsx.hbs
│   │   │   │   │   │   │   │   └── page.tsx.hbs
│   │   │   │   │   │   │   └── components/
│   │   │   │   │   │   │       ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │       ├── providers.tsx.hbs
│   │   │   │   │   │   │       └── theme-provider.tsx.hbs
│   │   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   │   ├── react-router/
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── react-router.config.ts
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │   │   └── theme-provider.tsx.hbs
│   │   │   │   │   │   │   ├── root.tsx.hbs
│   │   │   │   │   │   │   ├── routes/
│   │   │   │   │   │   │   │   └── _index.tsx.hbs
│   │   │   │   │   │   │   └── routes.ts
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   ├── tanstack-router/
│   │   │   │   │   │   ├── index.html.hbs
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── mode-toggle.tsx.hbs
│   │   │   │   │   │   │   │   └── theme-provider.tsx.hbs
│   │   │   │   │   │   │   ├── main.tsx.hbs
│   │   │   │   │   │   │   └── routes/
│   │   │   │   │   │   │       ├── __root.tsx.hbs
│   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   ├── tanstack-start/
│   │   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   │   ├── public/
│   │   │   │   │   │   │   └── robots.txt
│   │   │   │   │   │   ├── src/
│   │   │   │   │   │   │   ├── router.tsx.hbs
│   │   │   │   │   │   │   └── routes/
│   │   │   │   │   │   │       ├── __root.tsx.hbs
│   │   │   │   │   │   │       └── index.tsx.hbs
│   │   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   │   └── web-base/
│   │   │   │   │       ├── _gitignore
│   │   │   │   │       ├── components.json.hbs
│   │   │   │   │       └── src/
│   │   │   │   │           ├── components/
│   │   │   │   │           │   ├── header.tsx.hbs
│   │   │   │   │           │   └── loader.tsx.hbs
│   │   │   │   │           └── index.css.hbs
│   │   │   │   ├── solid/
│   │   │   │   │   ├── _gitignore
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── public/
│   │   │   │   │   │   └── robots.txt
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── header.tsx.hbs
│   │   │   │   │   │   │   └── loader.tsx
│   │   │   │   │   │   ├── main.tsx.hbs
│   │   │   │   │   │   ├── routes/
│   │   │   │   │   │   │   ├── __root.tsx.hbs
│   │   │   │   │   │   │   └── index.tsx.hbs
│   │   │   │   │   │   └── styles.css
│   │   │   │   │   ├── tsconfig.json.hbs
│   │   │   │   │   └── vite.config.ts.hbs
│   │   │   │   └── svelte/
│   │   │   │       ├── _gitignore
│   │   │   │       ├── _npmrc
│   │   │   │       ├── package.json.hbs
│   │   │   │       ├── src/
│   │   │   │       │   ├── app.css
│   │   │   │       │   ├── app.d.ts.hbs
│   │   │   │       │   ├── app.html
│   │   │   │       │   ├── components/
│   │   │   │       │   │   └── Header.svelte.hbs
│   │   │   │       │   ├── lib/
│   │   │   │       │   │   └── index.ts
│   │   │   │       │   └── routes/
│   │   │   │       │       ├── +layout.svelte.hbs
│   │   │   │       │       └── +page.svelte.hbs
│   │   │   │       ├── svelte.config.js.hbs
│   │   │   │       ├── tsconfig.json.hbs
│   │   │   │       └── vite.config.ts.hbs
│   │   │   ├── packages/
│   │   │   │   ├── config/
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   └── tsconfig.base.json.hbs
│   │   │   │   ├── env/
│   │   │   │   │   ├── package.json.hbs
│   │   │   │   │   ├── src/
│   │   │   │   │   │   ├── cloudflare-local.ts.hbs
│   │   │   │   │   │   ├── native.ts.hbs
│   │   │   │   │   │   ├── server.ts.hbs
│   │   │   │   │   │   └── web.ts.hbs
│   │   │   │   │   └── tsconfig.json.hbs
│   │   │   │   ├── infra/
│   │   │   │   │   ├── alchemy.run.ts.hbs
│   │   │   │   │   └── package.json.hbs
│   │   │   │   └── ui/
│   │   │   │       ├── components.json.hbs
│   │   │   │       ├── package.json.hbs
│   │   │   │       ├── postcss.config.mjs.hbs
│   │   │   │       ├── src/
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── button.tsx.hbs
│   │   │   │       │   │   ├── card.tsx.hbs
│   │   │   │       │   │   ├── checkbox.tsx.hbs
│   │   │   │       │   │   ├── dropdown-menu.tsx.hbs
│   │   │   │       │   │   ├── input.tsx.hbs
│   │   │   │       │   │   ├── label.tsx.hbs
│   │   │   │       │   │   ├── skeleton.tsx.hbs
│   │   │   │       │   │   └── sonner.tsx.hbs
│   │   │   │       │   ├── hooks/
│   │   │   │       │   │   └── .gitkeep
│   │   │   │       │   ├── lib/
│   │   │   │       │   │   └── utils.ts.hbs
│   │   │   │       │   └── styles/
│   │   │   │       │       └── globals.css.hbs
│   │   │   │       └── tsconfig.json.hbs
│   │   │   └── payments/
│   │   │       └── polar/
│   │   │           ├── server/
│   │   │           │   └── base/
│   │   │           │       └── src/
│   │   │           │           └── lib/
│   │   │           │               └── payments.ts.hbs
│   │   │           └── web/
│   │   │               ├── nuxt/
│   │   │               │   └── app/
│   │   │               │       └── pages/
│   │   │               │           └── success.vue.hbs
│   │   │               ├── react/
│   │   │               │   ├── next/
│   │   │               │   │   └── src/
│   │   │               │   │       └── app/
│   │   │               │   │           └── success/
│   │   │               │   │               └── page.tsx.hbs
│   │   │               │   ├── react-router/
│   │   │               │   │   └── src/
│   │   │               │   │       └── routes/
│   │   │               │   │           └── success.tsx.hbs
│   │   │               │   ├── tanstack-router/
│   │   │               │   │   └── src/
│   │   │               │   │       └── routes/
│   │   │               │   │           └── success.tsx.hbs
│   │   │               │   └── tanstack-start/
│   │   │               │       └── src/
│   │   │               │           ├── functions/
│   │   │               │           │   └── get-payment.ts.hbs
│   │   │               │           └── routes/
│   │   │               │               └── success.tsx.hbs
│   │   │               ├── solid/
│   │   │               │   └── src/
│   │   │               │       └── routes/
│   │   │               │           └── success.tsx.hbs
│   │   │               └── svelte/
│   │   │                   └── src/
│   │   │                       └── routes/
│   │   │                           └── success/
│   │   │                               └── +page.svelte.hbs
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   └── types/
│       ├── package.json
│       ├── src/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── json-schema.ts
│       │   ├── schemas.ts
│       │   └── types.ts
│       ├── tsconfig.json
│       └── tsdown.config.ts
├── scripts/
│   ├── bump-version.ts
│   ├── canary-release.ts
│   ├── cleanup-previews.ts
│   ├── publish-smoke.ts
│   └── release.ts
├── tsconfig.json
└── turbo.json
Download .txt
SYMBOL INDEX (1357 symbols across 267 files)

FILE: apps/cli/src/commands/history.ts
  type HistoryCommandInput (line 7) | type HistoryCommandInput = {
  function formatStackSummary (line 13) | function formatStackSummary(entry: ProjectHistoryEntry): string {
  function formatDate (line 35) | function formatDate(isoString: string): string {
  function historyHandler (line 46) | async function historyHandler(input: HistoryCommandInput): Promise<void> {

FILE: apps/cli/src/commands/meta.ts
  constant DOCS_URL (line 10) | const DOCS_URL = "https://better-t-stack.dev/docs";
  constant BUILDER_URL (line 11) | const BUILDER_URL = "https://better-t-stack.dev/new";
  function openExternalUrl (line 13) | async function openExternalUrl(url: string, successMessage: string) {
  function showSponsorsCommand (line 26) | async function showSponsorsCommand() {
  function openDocsCommand (line 40) | async function openDocsCommand() {
  function openBuilderCommand (line 44) | async function openBuilderCommand() {

FILE: apps/cli/src/constants.ts
  constant PKG_ROOT (line 16) | const PKG_ROOT = path.join(distPath, "../");
  constant DEFAULT_CONFIG_BASE (line 18) | const DEFAULT_CONFIG_BASE = {
  function getDefaultConfig (line 38) | function getDefaultConfig() {
  constant DEFAULT_CONFIG (line 49) | const DEFAULT_CONFIG = getDefaultConfig();
  constant ADDON_COMPATIBILITY (line 53) | const ADDON_COMPATIBILITY = {

FILE: apps/cli/src/helpers/addons/addons-setup.ts
  function runSetup (line 23) | async function runSetup<T, E extends AddonSetupError | UserCancelledError>(
  function runAddonStep (line 37) | async function runAddonStep(addon: string, step: () => Promise<void>): P...
  function setupAddons (line 53) | async function setupAddons(config: ProjectConfig) {
  function setupBiome (line 128) | async function setupBiome(projectDir: string) {
  function setupHusky (line 147) | async function setupHusky(projectDir: string, linter?: "biome" | "oxlint...
  function setupLefthook (line 180) | async function setupLefthook(projectDir: string) {

FILE: apps/cli/src/helpers/addons/evlog-setup.ts
  type EvlogBackend (line 9) | type EvlogBackend = Extract<Backend, "hono" | "express" | "fastify" | "e...
  type EvlogWebFrontend (line 10) | type EvlogWebFrontend = Extract<Frontend, "next" | "nuxt" | "svelte" | "...
  function isEvlogBackend (line 15) | function isEvlogBackend(backend: Backend): backend is EvlogBackend {
  function getEvlogWebFrontend (line 19) | function getEvlogWebFrontend(frontends: Frontend[]): EvlogWebFrontend | ...
  function shouldIdentifyWebAuth (line 25) | function shouldIdentifyWebAuth(config: ProjectConfig) {
  function prependMissingImports (line 29) | function prependMissingImports(content: string, imports: string[]) {
  function addNamedImport (line 42) | function addNamedImport(content: string, moduleName: string, names: stri...
  function insertBeforeOnce (line 67) | function insertBeforeOnce(
  function insertAfterOnce (line 78) | function insertAfterOnce(content: string, marker: string, snippet: strin...
  function writeFileIfChanged (line 84) | async function writeFileIfChanged(filePath: string, content: string) {
  function updateFileIfExists (line 93) | async function updateFileIfExists(filePath: string, update: (content: st...
  function usesCreateAuthFactory (line 102) | function usesCreateAuthFactory(config: ProjectConfig) {
  function getAuthImportLine (line 110) | function getAuthImportLine(config: ProjectConfig) {
  function getAuthExpression (line 116) | function getAuthExpression(config: ProjectConfig) {
  function addAiSdkEvlogTelemetry (line 120) | function addAiSdkEvlogTelemetry(content: string, loggerExpression: strin...
  function addEvlogBetterAuthServerSetup (line 152) | function addEvlogBetterAuthServerSetup(
  function addEvlogServerSetup (line 231) | function addEvlogServerSetup(content: string, backend: EvlogBackend, ser...
  function addNuxtEvlogSetup (line 309) | function addNuxtEvlogSetup(content: string, serviceName: string) {
  function addSvelteViteEvlogSetup (line 326) | function addSvelteViteEvlogSetup(content: string, serviceName: string) {
  function addSvelteHooksEvlogSetup (line 336) | function addSvelteHooksEvlogSetup(content: string) {
  function addSvelteLocalsType (line 370) | function addSvelteLocalsType(content: string) {
  function addTanstackStartRootEvlogSetup (line 388) | function addTanstackStartRootEvlogSetup(content: string) {
  function addAstroMiddlewareEvlogSetup (line 416) | function addAstroMiddlewareEvlogSetup(content: string, serviceName: stri...
  function addAstroLocalsType (line 465) | function addAstroLocalsType(content: string) {
  function addNextRouteWrappers (line 484) | function addNextRouteWrappers(content: string) {
  function addNextAiEvlogSetup (line 508) | function addNextAiEvlogSetup(content: string) {
  function addNuxtAiEvlogSetup (line 526) | function addNuxtAiEvlogSetup(content: string) {
  function addSvelteAiEvlogSetup (line 530) | function addSvelteAiEvlogSetup(content: string) {
  function addTanstackStartAiEvlogSetup (line 539) | function addTanstackStartAiEvlogSetup(content: string) {
  function addBackendAiEvlogSetup (line 548) | function addBackendAiEvlogSetup(content: string, backend: EvlogBackend) {
  function addNextBetterAuthToRoute (line 565) | function addNextBetterAuthToRoute(content: string) {
  function addSvelteBetterAuthEvlogSetup (line 586) | function addSvelteBetterAuthEvlogSetup(content: string, config: ProjectC...
  function addAstroBetterAuthEvlogSetup (line 632) | function addAstroBetterAuthEvlogSetup(content: string, config: ProjectCo...
  function getNextEvlogFile (line 668) | function getNextEvlogFile(serviceName: string) {
  function getNextInstrumentationFile (line 682) | function getNextInstrumentationFile() {
  function getNextProxyFile (line 689) | function getNextProxyFile() {
  function getNextEvlogAuthFile (line 700) | function getNextEvlogAuthFile(config: ProjectConfig) {
  function getNitroEvlogAuthPluginFile (line 731) | function getNitroEvlogAuthPluginFile(config: ProjectConfig) {
  function getNuxtEvlogAuthMiddlewareFile (line 763) | function getNuxtEvlogAuthMiddlewareFile(config: ProjectConfig) {
  function getTanstackNitroConfigFile (line 794) | function getTanstackNitroConfigFile(serviceName: string) {
  function getAstroMiddlewareFile (line 811) | function getAstroMiddlewareFile(serviceName: string) {
  function getAstroEnvFile (line 841) | function getAstroEnvFile() {
  function setupNextEvlog (line 854) | async function setupNextEvlog(config: ProjectConfig, serviceName: string) {
  function setupNuxtEvlog (line 910) | async function setupNuxtEvlog(config: ProjectConfig, serviceName: string) {
  function setupSvelteEvlog (line 936) | async function setupSvelteEvlog(config: ProjectConfig, serviceName: stri...
  function setupTanstackStartEvlog (line 971) | async function setupTanstackStartEvlog(config: ProjectConfig, serviceNam...
  function setupAstroEvlog (line 997) | async function setupAstroEvlog(config: ProjectConfig, serviceName: strin...
  function setupEvlogWeb (line 1022) | async function setupEvlogWeb(config: ProjectConfig) {
  function setupEvlog (line 1041) | async function setupEvlog(config: ProjectConfig): Promise<Result<void, A...

FILE: apps/cli/src/helpers/addons/fumadocs-setup.ts
  type FumadocsTemplate (line 16) | type FumadocsTemplate =
  type FumadocsSearch (line 25) | type FumadocsSearch = "orama" | "orama-cloud";
  type FumadocsOgImage (line 26) | type FumadocsOgImage = "next-og" | "takumi";
  type FumadocsAiChat (line 27) | type FumadocsAiChat = "openrouter" | "inkeep";
  constant TEMPLATES (line 29) | const TEMPLATES = {
  constant DEFAULT_TEMPLATE (line 63) | const DEFAULT_TEMPLATE: FumadocsTemplate = "next-mdx";
  constant DEFAULT_DEV_PORT (line 64) | const DEFAULT_DEV_PORT = 4000;
  function aiChatDisabledForTemplate (line 66) | function aiChatDisabledForTemplate(template: FumadocsTemplate): boolean {
  function setupFumadocs (line 70) | async function setupFumadocs(

FILE: apps/cli/src/helpers/addons/mcp-setup.ts
  type McpTransport (line 14) | type McpTransport = "http" | "sse";
  type McpOptions (line 16) | type McpOptions = NonNullable<AddonOptions["mcp"]>;
  type McpServerKey (line 17) | type McpServerKey = NonNullable<McpOptions["servers"]>[number];
  type McpAgent (line 18) | type McpAgent = NonNullable<McpOptions["agents"]>[number];
  type InstallScope (line 19) | type InstallScope = NonNullable<McpOptions["scope"]>;
  type McpServerDef (line 21) | type McpServerDef = {
  type AgentScope (line 30) | type AgentScope = "project" | "global" | "both";
  type AgentOption (line 32) | type AgentOption = {
  constant MCP_AGENTS (line 38) | const MCP_AGENTS: AgentOption[] = [
  constant DEFAULT_SCOPE (line 55) | const DEFAULT_SCOPE: InstallScope = "project";
  constant DEFAULT_AGENTS (line 56) | const DEFAULT_AGENTS: McpAgent[] = ["cursor", "claude-code", "vscode"];
  function uniqueValues (line 58) | function uniqueValues<T>(values: T[]): T[] {
  function hasReactBasedFrontend (line 62) | function hasReactBasedFrontend(frontend: ProjectConfig["frontend"]): boo...
  function hasNativeFrontend (line 71) | function hasNativeFrontend(frontend: ProjectConfig["frontend"]): boolean {
  function getAllMcpServers (line 79) | function getAllMcpServers(config: ProjectConfig): McpServerDef[] {
  function getRecommendedMcpServers (line 193) | function getRecommendedMcpServers(
  function filterAgentsForScope (line 269) | function filterAgentsForScope(scope: InstallScope): AgentOption[] {
  function setupMcp (line 273) | async function setupMcp(

FILE: apps/cli/src/helpers/addons/oxlint-setup.ts
  function setupOxlint (line 14) | async function setupOxlint(

FILE: apps/cli/src/helpers/addons/skills-setup.ts
  type SkillSource (line 15) | type SkillSource = {
  type AgentOption (line 19) | type AgentOption = {
  type SkillsOptions (line 24) | type SkillsOptions = NonNullable<AddonOptions["skills"]>;
  type SkillAgent (line 25) | type SkillAgent = NonNullable<SkillsOptions["agents"]>[number];
  type InstallScope (line 26) | type InstallScope = NonNullable<SkillsOptions["scope"]>;
  constant SKILL_SOURCES (line 29) | const SKILL_SOURCES = {
  type SourceKey (line 92) | type SourceKey = keyof typeof SKILL_SOURCES;
  constant AVAILABLE_AGENTS (line 95) | const AVAILABLE_AGENTS: AgentOption[] = [
  constant DEFAULT_SCOPE (line 123) | const DEFAULT_SCOPE: InstallScope = "project";
  constant DEFAULT_AGENTS (line 124) | const DEFAULT_AGENTS: SkillAgent[] = ["cursor", "claude-code", "github-c...
  function hasReactBasedFrontend (line 126) | function hasReactBasedFrontend(frontend: ProjectConfig["frontend"]): boo...
  function hasNativeFrontend (line 135) | function hasNativeFrontend(frontend: ProjectConfig["frontend"]): boolean {
  function getRecommendedSourceKeys (line 143) | function getRecommendedSourceKeys(config: ProjectConfig): SourceKey[] {
  constant CURATED_SKILLS_BY_SOURCE (line 227) | const CURATED_SKILLS_BY_SOURCE: Record<SourceKey, (config: ProjectConfig...
  function getCuratedSkillNamesForSourceKey (line 323) | function getCuratedSkillNamesForSourceKey(sourceKey: SourceKey, config: ...
  function uniqueValues (line 327) | function uniqueValues<T>(values: T[]): T[] {
  function setupSkills (line 331) | async function setupSkills(

FILE: apps/cli/src/helpers/addons/starlight-setup.ts
  function setupStarlight (line 13) | async function setupStarlight(

FILE: apps/cli/src/helpers/addons/tauri-setup.ts
  function getWebFrontend (line 13) | function getWebFrontend(frontend: Pick<ProjectConfig, "frontend">["front...
  function getTauriDevUrl (line 17) | function getTauriDevUrl(frontend: Pick<ProjectConfig, "frontend">["front...
  function getTauriFrontendDist (line 31) | function getTauriFrontendDist(frontend: Pick<ProjectConfig, "frontend">[...
  function getTauriBeforeBuildCommand (line 50) | function getTauriBeforeBuildCommand(
  function buildTauriInitArgs (line 59) | function buildTauriInitArgs(
  function setupTauri (line 84) | async function setupTauri(config: ProjectConfig): Promise<Result<void, A...

FILE: apps/cli/src/helpers/addons/tui-setup.ts
  type TuiTemplate (line 16) | type TuiTemplate = "core" | "react" | "solid";
  type TuiSetupResult (line 18) | type TuiSetupResult = Result<void, AddonSetupError | UserCancelledError>;
  constant TEMPLATES (line 20) | const TEMPLATES = {
  constant DEFAULT_TEMPLATE (line 35) | const DEFAULT_TEMPLATE: TuiTemplate = "core";
  constant TUI_LOCKFILES (line 36) | const TUI_LOCKFILES = ["bun.lock", "package-lock.json", "pnpm-lock.yaml"...
  function resolveTuiTemplate (line 38) | function resolveTuiTemplate(config: ProjectConfig): TuiTemplate | undefi...
  function setupTui (line 52) | async function setupTui(config: ProjectConfig): Promise<TuiSetupResult> {
  function postProcessTuiWorkspace (line 134) | async function postProcessTuiWorkspace(

FILE: apps/cli/src/helpers/addons/ultracite-setup.ts
  type UltraciteLinter (line 14) | type UltraciteLinter = "biome" | "eslint" | "oxlint";
  type UltraciteEditor (line 16) | type UltraciteEditor =
  type UltraciteAgent (line 28) | type UltraciteAgent =
  type UltraciteHook (line 72) | type UltraciteHook = "cursor" | "windsurf" | "codebuddy" | "claude" | "c...
  type UltraciteSetupResult (line 74) | type UltraciteSetupResult = Result<void, AddonSetupError | UserCancelled...
  type UltraciteInitArgsInput (line 75) | type UltraciteInitArgsInput = {
  constant LINTERS (line 85) | const LINTERS = {
  constant AGENTS (line 91) | const AGENTS = {
  constant HOOKS (line 136) | const HOOKS = {
  constant DEFAULT_LINTER (line 144) | const DEFAULT_LINTER: UltraciteLinter = "biome";
  constant DEFAULT_EDITORS (line 145) | const DEFAULT_EDITORS: UltraciteEditor[] = ["vscode"];
  constant DEFAULT_AGENTS (line 146) | const DEFAULT_AGENTS: UltraciteAgent[] = ["universal"];
  constant DEFAULT_HOOKS (line 147) | const DEFAULT_HOOKS: UltraciteHook[] = [];
  function getFrameworksFromFrontend (line 149) | function getFrameworksFromFrontend(frontend: string[]): string[] {
  function buildUltraciteInitArgs (line 175) | function buildUltraciteInitArgs({
  function setupUltracite (line 215) | async function setupUltracite(

FILE: apps/cli/src/helpers/addons/wxt-setup.ts
  type WxtTemplate (line 16) | type WxtTemplate = "vanilla" | "vue" | "react" | "solid" | "svelte";
  type WxtSetupResult (line 18) | type WxtSetupResult = Result<void, AddonSetupError | UserCancelledError>;
  constant TEMPLATES (line 20) | const TEMPLATES = {
  constant DEFAULT_TEMPLATE (line 43) | const DEFAULT_TEMPLATE: WxtTemplate = "react";
  constant DEFAULT_DEV_PORT (line 44) | const DEFAULT_DEV_PORT = 5555;
  function setupWxt (line 46) | async function setupWxt(config: ProjectConfig): Promise<WxtSetupResult> {

FILE: apps/cli/src/helpers/core/add-handler.ts
  type AddHandlerOptions (line 27) | interface AddHandlerOptions {
  type AddResult (line 31) | interface AddResult {
  function mergeAddonOptions (line 40) | function mergeAddonOptions(
  function addHandler (line 73) | async function addHandler(
  function addHandlerInternal (line 114) | async function addHandlerInternal(

FILE: apps/cli/src/helpers/core/command-handlers.ts
  type CreateHandlerOptions (line 41) | interface CreateHandlerOptions {
  type CreateProjectResult (line 48) | interface CreateProjectResult {
  function createEmptyResult (line 62) | function createEmptyResult(
  type CreateHandlerError (line 99) | type CreateHandlerError =
  function createProjectHandler (line 106) | async function createProjectHandler(
  function createProjectHandlerInternal (line 147) | async function createProjectHandlerInternal(
  type DirectoryConflictResult (line 436) | interface DirectoryConflictResult {
  function isPathWithinCwd (line 441) | function isPathWithinCwd(targetPath: string) {
  function validateResolvedProjectPathInput (line 447) | function validateResolvedProjectPathInput(candidate: string): Result<voi...
  function resolveProjectNameForSilent (line 484) | async function resolveProjectNameForSilent(
  function handleDirectoryConflictResult (line 493) | async function handleDirectoryConflictResult(
  function handleDirectoryConflictProgrammatically (line 517) | async function handleDirectoryConflictProgrammatically(

FILE: apps/cli/src/helpers/core/convex-codegen.ts
  function runConvexCodegen (line 9) | async function runConvexCodegen(

FILE: apps/cli/src/helpers/core/create-project.ts
  type CreateProjectOptions (line 22) | interface CreateProjectOptions {
  function createProject (line 31) | async function createProject(
  function setPackageManagerVersion (line 147) | async function setPackageManagerVersion(

FILE: apps/cli/src/helpers/core/db-setup-options.ts
  type DatabaseSetupCliOptions (line 4) | interface DatabaseSetupCliOptions {
  type DbSetupMode (line 9) | type DbSetupMode = NonNullable<DbSetupOptions["mode"]>;
  constant REMOTE_PROVISIONING_DB_SETUPS (line 11) | const REMOTE_PROVISIONING_DB_SETUPS: DatabaseSetup[] = [
  function requiresProvisioningGuardrails (line 19) | function requiresProvisioningGuardrails(dbSetup: DatabaseSetup): boolean {
  function resolveDbSetupMode (line 23) | function resolveDbSetupMode(
  function mergeResolvedDbSetupOptions (line 47) | function mergeResolvedDbSetupOptions(

FILE: apps/cli/src/helpers/core/db-setup.ts
  function setupDatabase (line 26) | async function setupDatabase(config: ProjectConfig, cliInput?: DatabaseS...

FILE: apps/cli/src/helpers/core/detect-project-config.ts
  function detectProjectConfig (line 8) | async function detectProjectConfig(projectDir: string) {
  function isBetterTStackProject (line 43) | async function isBetterTStackProject(projectDir: string): Promise<boolea...

FILE: apps/cli/src/helpers/core/git.ts
  function initializeGit (line 8) | async function initializeGit(

FILE: apps/cli/src/helpers/core/install-dependencies.ts
  function installDependencies (line 10) | async function installDependencies({

FILE: apps/cli/src/helpers/core/post-installation.ts
  function getDesktopStaticBuildNote (line 22) | function getDesktopStaticBuildNote(frontend: Frontend[]): string {
  function displayPostInstallInstructions (line 43) | async function displayPostInstallInstructions(
  function getNativeInstructions (line 254) | function getNativeInstructions(
  function getHuskyInstructions (line 295) | function getHuskyInstructions(runCmd: string) {
  function getLintingInstructions (line 301) | function getLintingInstructions(runCmd: string) {
  function getLefthookInstructions (line 307) | function getLefthookInstructions(packageManager: string) {
  function getDatabaseInstructions (line 314) | async function getDatabaseInstructions(
  function getTauriInstructions (line 407) | function getTauriInstructions(runCmd: string, frontend: Frontend[]) {
  function getElectrobunInstructions (line 421) | function getElectrobunInstructions(runCmd: string, frontend: Frontend[]) {
  function getPwaInstructions (line 437) | function getPwaInstructions() {
  function getStarlightInstructions (line 443) | function getStarlightInstructions(runCmd: string) {
  function getNoOrmWarning (line 451) | function getNoOrmWarning() {
  function getBunWebNativeWarning (line 457) | function getBunWebNativeWarning() {
  function getClerkQuickstartUrl (line 463) | function getClerkQuickstartUrl(frontend: Frontend[]) {
  function getClerkInstructionLines (line 485) | function getClerkInstructionLines(
  function getClerkInstructions (line 554) | function getClerkInstructions(frontend: Frontend[], backend: Backend, ap...
  function getBetterAuthConvexInstructions (line 564) | function getBetterAuthConvexInstructions(hasWeb: boolean, webPort: strin...
  function getPolarInstructions (line 575) | function getPolarInstructions(backend: Backend) {
  function getAlchemyDeployInstructions (line 580) | function getAlchemyDeployInstructions(

FILE: apps/cli/src/helpers/database-providers/d1-setup.ts
  function setupCloudflareD1 (line 10) | async function setupCloudflareD1(

FILE: apps/cli/src/helpers/database-providers/docker-compose-setup.ts
  function setupDockerCompose (line 9) | async function setupDockerCompose(
  function writeEnvFile (line 33) | async function writeEnvFile(
  function getDatabaseUrl (line 51) | function getDatabaseUrl(database: Database, projectName: string) {

FILE: apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  type MongoDBConfig (line 26) | type MongoDBConfig = {
  type MongoDBSetupResult (line 30) | type MongoDBSetupResult = Result<void, DatabaseSetupError | UserCancelle...
  function checkAtlasCLI (line 32) | async function checkAtlasCLI(): Promise<boolean> {
  function initMongoDBAtlas (line 42) | async function initMongoDBAtlas(
  function writeEnvFile (line 96) | async function writeEnvFile(
  function displayManualSetupInstructions (line 123) | function displayManualSetupInstructions() {
  function setupMongoDBAtlas (line 141) | async function setupMongoDBAtlas(

FILE: apps/cli/src/helpers/database-providers/neon-setup.ts
  type NeonConfig (line 26) | type NeonConfig = {
  type NeonRegion (line 33) | type NeonRegion = {
  type NeonSetupResult (line 38) | type NeonSetupResult = Result<void, DatabaseSetupError | UserCancelledEr...
  constant NEON_REGIONS (line 40) | const NEON_REGIONS: NeonRegion[] = [
  function executeNeonCommand (line 51) | async function executeNeonCommand(
  function createNeonProject (line 79) | async function createNeonProject(
  function writeEnvFile (line 127) | async function writeEnvFile(
  function setupWithNeonDb (line 156) | async function setupWithNeonDb(
  function displayManualSetupInstructions (line 203) | function displayManualSetupInstructions(target: "apps/web" | "apps/serve...
  function setupNeonPostgres (line 214) | async function setupNeonPostgres(

FILE: apps/cli/src/helpers/database-providers/planetscale-setup.ts
  function setupPlanetScale (line 10) | async function setupPlanetScale(

FILE: apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  type PrismaConfig (line 21) | type PrismaConfig = {
  type CreateDbResponse (line 26) | type CreateDbResponse = {
  type PrismaSetupResult (line 36) | type PrismaSetupResult = Result<void, DatabaseSetupError | UserCancelled...
  constant AVAILABLE_REGIONS (line 38) | const AVAILABLE_REGIONS = [
  constant CREATE_DB_USER_AGENT (line 47) | const CREATE_DB_USER_AGENT = "aman/better-t-stack";
  function setupWithCreateDb (line 49) | async function setupWithCreateDb(
  function writeEnvFile (line 132) | async function writeEnvFile(
  function displayManualSetupInstructions (line 170) | function displayManualSetupInstructions(target: "apps/web" | "apps/serve...
  function setupPrismaPostgres (line 181) | async function setupPrismaPostgres(

FILE: apps/cli/src/helpers/database-providers/supabase-setup.ts
  type SupabaseSetupResult (line 26) | type SupabaseSetupResult = Result<void, DatabaseSetupError | UserCancell...
  function writeSupabaseEnvFile (line 28) | async function writeSupabaseEnvFile(
  function extractDbUrl (line 61) | function extractDbUrl(output: string): string | null {
  function initializeSupabase (line 66) | async function initializeSupabase(
  function startSupabase (line 96) | async function startSupabase(
  function displayManualSupabaseInstructions (line 146) | function displayManualSupabaseInstructions(
  function setupSupabase (line 168) | async function setupSupabase(

FILE: apps/cli/src/helpers/database-providers/turso-setup.ts
  type TursoConfig (line 21) | type TursoConfig = {
  type TursoSetupResult (line 26) | type TursoSetupResult = Result<void, DatabaseSetupError | UserCancelledE...
  function isTursoInstalled (line 28) | async function isTursoInstalled(): Promise<boolean> {
  function isTursoLoggedIn (line 32) | async function isTursoLoggedIn(): Promise<boolean> {
  function loginToTurso (line 43) | async function loginToTurso(): Promise<Result<void, DatabaseSetupError>> {
  function installTursoCLI (line 63) | async function installTursoCLI(isMac: boolean): Promise<Result<void, Dat...
  type TursoGroup (line 95) | type TursoGroup = {
  function getTursoGroups (line 102) | async function getTursoGroups(): Promise<TursoGroup[]> {
  function selectTursoGroup (line 133) | async function selectTursoGroup(): Promise<Result<string | null, UserCan...
  function createTursoDatabase (line 162) | async function createTursoDatabase(
  function writeEnvFile (line 227) | async function writeEnvFile(
  function displayManualSetupInstructions (line 259) | function displayManualSetupInstructions(targetApp: "apps/web" | "apps/se...
  function setupTurso (line 271) | async function setupTurso(

FILE: apps/cli/src/index.ts
  type SchemaName (line 90) | type SchemaName = z.infer<typeof SchemaNameSchema>;
  function getCliSchemaJson (line 94) | function getCliSchemaJson(): unknown {
  function getSchemaResult (line 102) | function getSchemaResult(name: SchemaName): unknown {
  function createBtsCli (line 270) | function createBtsCli(): ReturnType<typeof createCli> {
  type CreateError (line 284) | type CreateError = UserCancelledError | CLIError | ProjectCreationError;
  function create (line 311) | async function create(
  function sponsors (line 350) | async function sponsors() {
  function docs (line 354) | async function docs() {
  function builder (line 358) | async function builder() {
  function createVirtual (line 407) | async function createVirtual(
  function add (line 513) | async function add(

FILE: apps/cli/src/mcp.ts
  function formatToolSuccess (line 64) | function formatToolSuccess(data: unknown) {
  function formatToolError (line 79) | function formatToolError(error: unknown) {
  function getProjectToolAnnotations (line 96) | function getProjectToolAnnotations() {
  function getMcpInstallTimeoutMessage (line 104) | function getMcpInstallTimeoutMessage(packageManager: string) {
  function getStackGuidance (line 112) | function getStackGuidance() {
  function createBtsMcpServer (line 170) | function createBtsMcpServer() {
  function startBtsMcpServer (line 383) | async function startBtsMcpServer() {

FILE: apps/cli/src/prompts/addons.ts
  type AddonOption (line 15) | type AddonOption = {
  type AddonProjectConfig (line 21) | type AddonProjectConfig = Pick<
  function getAddonDisplay (line 26) | function getAddonDisplay(addon: Addons): { label: string; hint: string } {
  constant ADDON_GROUPS (line 107) | const ADDON_GROUPS = {
  function createGroupedOptions (line 116) | function createGroupedOptions(): Record<string, AddonOption[]> {
  function addOptionToGroup (line 120) | function addOptionToGroup(groupedOptions: Record<string, AddonOption[]>,...
  function sortAndPruneGroupedOptions (line 129) | function sortAndPruneGroupedOptions(groupedOptions: Record<string, Addon...
  function validateAddonSelection (line 145) | function validateAddonSelection(selected: Addons[] | undefined) {
  function getAddonsChoice (line 151) | async function getAddonsChoice(
  function getAddonsToAdd (line 201) | async function getAddonsToAdd(config: AddonProjectConfig) {

FILE: apps/cli/src/prompts/api.ts
  function getApiChoice (line 9) | async function getApiChoice(

FILE: apps/cli/src/prompts/auth.ts
  function getAvailableAuthProviders (line 7) | function getAvailableAuthProviders(
  function getAuthChoice (line 48) | async function getAuthChoice(

FILE: apps/cli/src/prompts/backend.ts
  constant FULLSTACK_FRONTENDS (line 7) | const FULLSTACK_FRONTENDS: readonly Frontend[] = [
  function getBackendFrameworkChoice (line 15) | async function getBackendFrameworkChoice(

FILE: apps/cli/src/prompts/config-prompts.ts
  type PromptGroupResults (line 39) | type PromptGroupResults = {
  function gatherConfig (line 58) | async function gatherConfig(

FILE: apps/cli/src/prompts/database-setup.ts
  function getDBSetupChoice (line 5) | async function getDBSetupChoice(

FILE: apps/cli/src/prompts/database.ts
  function getDatabaseChoice (line 6) | async function getDatabaseChoice(database?: Database, backend?: Backend,...

FILE: apps/cli/src/prompts/examples.ts
  function getExamplesChoice (line 7) | async function getExamplesChoice(

FILE: apps/cli/src/prompts/frontend.ts
  function getFrontendChoice (line 15) | async function getFrontendChoice(

FILE: apps/cli/src/prompts/git.ts
  function getGitChoice (line 5) | async function getGitChoice(git?: boolean) {

FILE: apps/cli/src/prompts/install.ts
  function getinstallChoice (line 5) | async function getinstallChoice(install?: boolean) {

FILE: apps/cli/src/prompts/navigable-group.ts
  type Prettify (line 9) | type Prettify<T> = {
  type PromptGroupAwaitedReturn (line 13) | type PromptGroupAwaitedReturn<T> = {
  type NavigablePromptGroupOptions (line 17) | interface NavigablePromptGroupOptions<T> {
  type NavigablePromptGroup (line 25) | type NavigablePromptGroup<T> = {
  function navigableGroup (line 35) | async function navigableGroup<T>(

FILE: apps/cli/src/prompts/navigable.ts
  constant S_STEP_ACTIVE (line 26) | const S_STEP_ACTIVE = unicode ? "◆" : "*";
  constant S_STEP_CANCEL (line 27) | const S_STEP_CANCEL = unicode ? "■" : "x";
  constant S_STEP_ERROR (line 28) | const S_STEP_ERROR = unicode ? "▲" : "x";
  constant S_STEP_SUBMIT (line 29) | const S_STEP_SUBMIT = unicode ? "◇" : "o";
  constant S_BAR (line 30) | const S_BAR = unicode ? "│" : "|";
  constant S_BAR_END (line 31) | const S_BAR_END = unicode ? "└" : "—";
  constant S_RADIO_ACTIVE (line 32) | const S_RADIO_ACTIVE = unicode ? "●" : ">";
  constant S_RADIO_INACTIVE (line 33) | const S_RADIO_INACTIVE = unicode ? "○" : " ";
  constant S_CHECKBOX_ACTIVE (line 34) | const S_CHECKBOX_ACTIVE = unicode ? "◻" : "[•]";
  constant S_CHECKBOX_SELECTED (line 35) | const S_CHECKBOX_SELECTED = unicode ? "◼" : "[+]";
  constant S_CHECKBOX_INACTIVE (line 36) | const S_CHECKBOX_INACTIVE = unicode ? "◻" : "[ ]";
  function symbol (line 38) | function symbol(state: State) {
  constant KEYBOARD_HINT (line 52) | const KEYBOARD_HINT = pc.dim(
  constant KEYBOARD_HINT_FIRST (line 56) | const KEYBOARD_HINT_FIRST = pc.dim(
  constant KEYBOARD_HINT_MULTI (line 60) | const KEYBOARD_HINT_MULTI = pc.dim(
  constant KEYBOARD_HINT_MULTI_FIRST (line 64) | const KEYBOARD_HINT_MULTI_FIRST = pc.dim(
  function getHint (line 72) | function getHint(): string {
  function getMultiHint (line 76) | function getMultiHint(): string {
  function normalizeValidationMessage (line 80) | function normalizeValidationMessage(
  function runWithNavigation (line 86) | async function runWithNavigation<T>(prompt: any): Promise<T | symbol> {
  type SelectOption (line 102) | interface SelectOption<T> {
  type NavigableSelectOptions (line 109) | interface NavigableSelectOptions<T> {
  function navigableSelect (line 115) | async function navigableSelect<T>(opts: NavigableSelectOptions<T>): Prom...
  type NavigableMultiselectOptions (line 164) | interface NavigableMultiselectOptions<T> {
  function navigableMultiselect (line 172) | async function navigableMultiselect<T>(
  type NavigableConfirmOptions (line 278) | interface NavigableConfirmOptions {
  function navigableConfirm (line 285) | async function navigableConfirm(opts: NavigableConfirmOptions): Promise<...
  type NavigableTextOptions (line 321) | interface NavigableTextOptions {
  function navigableText (line 329) | async function navigableText(opts: NavigableTextOptions): Promise<string...
  type GroupMultiSelectOption (line 369) | interface GroupMultiSelectOption<T> {
  type NavigableGroupMultiselectOptions (line 376) | interface NavigableGroupMultiselectOptions<T> {
  function navigableGroupMultiselect (line 384) | async function navigableGroupMultiselect<T>(

FILE: apps/cli/src/prompts/orm.ts
  function getORMChoice (line 25) | async function getORMChoice(

FILE: apps/cli/src/prompts/package-manager.ts
  function getPackageManagerChoice (line 6) | async function getPackageManagerChoice(packageManager?: PackageManager) {

FILE: apps/cli/src/prompts/payments.ts
  function getPaymentsChoice (line 7) | async function getPaymentsChoice(

FILE: apps/cli/src/prompts/project-name.ts
  function isPathWithinCwd (line 12) | function isPathWithinCwd(targetPath: string) {
  function validateDirectoryName (line 18) | function validateDirectoryName(name: string) {
  function getProjectName (line 28) | async function getProjectName(initialName?: string): Promise<string> {

FILE: apps/cli/src/prompts/runtime.ts
  function getRuntimeChoice (line 6) | async function getRuntimeChoice(runtime?: Runtime, backend?: Backend) {

FILE: apps/cli/src/prompts/server-deploy.ts
  type DeploymentOption (line 6) | type DeploymentOption = {
  function getDeploymentDisplay (line 12) | function getDeploymentDisplay(deployment: ServerDeploy): {
  function getServerDeploymentChoice (line 28) | async function getServerDeploymentChoice(
  function getServerDeploymentToAdd (line 52) | async function getServerDeploymentToAdd(

FILE: apps/cli/src/prompts/web-deploy.ts
  function hasWebFrontend (line 7) | function hasWebFrontend(frontends: Frontend[]) {
  type DeploymentOption (line 11) | type DeploymentOption = {
  function getDeploymentDisplay (line 17) | function getDeploymentDisplay(deployment: WebDeploy): {
  function getDeploymentChoice (line 33) | async function getDeploymentChoice(
  function getDeploymentToAdd (line 71) | async function getDeploymentToAdd(frontend: Frontend[], existingDeployme...

FILE: apps/cli/src/utils/analytics.ts
  constant CONVEX_INGEST_URL (line 7) | const CONVEX_INGEST_URL = process.env.CONVEX_INGEST_URL;
  function sendConvexEvent (line 9) | async function sendConvexEvent(payload: Record<string, unknown>): Promis...
  function trackProjectCreation (line 25) | async function trackProjectCreation(

FILE: apps/cli/src/utils/bts-config.ts
  constant BTS_CONFIG_FILE (line 7) | const BTS_CONFIG_FILE = "bts.jsonc";
  function readBtsConfig (line 12) | async function readBtsConfig(projectDir: string): Promise<BetterTStackCo...
  function updateBtsConfig (line 31) | async function updateBtsConfig(

FILE: apps/cli/src/utils/command-exists.ts
  function commandExists (line 4) | async function commandExists(command: string): Promise<boolean> {

FILE: apps/cli/src/utils/compatibility-rules.ts
  type ValidationResult (line 20) | type ValidationResult = Result<void, ValidationError>;
  type AddonCompatibilityConfig (line 21) | type AddonCompatibilityConfig = Pick<ProjectConfig, "frontend" | "auth" ...
  constant CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS (line 23) | const CONVEX_BETTER_AUTH_INCOMPATIBLE_FRONTENDS = [
  constant CONVEX_BETTER_AUTH_SUPPORTED_FRONTENDS (line 30) | const CONVEX_BETTER_AUTH_SUPPORTED_FRONTENDS = [
  function validationErr (line 40) | function validationErr(message: string): ValidationResult {
  function isWebFrontend (line 44) | function isWebFrontend(value: Frontend) {
  function splitFrontends (line 48) | function splitFrontends(values: Frontend[] = []): {
  function ensureSingleWebAndNative (line 59) | function ensureSingleWebAndNative(frontends: Frontend[]): ValidationResu...
  constant FULLSTACK_FRONTENDS (line 75) | const FULLSTACK_FRONTENDS: readonly Frontend[] = [
  constant EVLOG_SERVER_BACKENDS (line 83) | const EVLOG_SERVER_BACKENDS: readonly Backend[] = ["hono", "express", "f...
  constant EVLOG_FULLSTACK_FRONTENDS (line 84) | const EVLOG_FULLSTACK_FRONTENDS: readonly Frontend[] = FULLSTACK_FRONTENDS;
  function supportsEvlogAddon (line 89) | function supportsEvlogAddon(
  function validateSelfBackendCompatibility (line 108) | function validateSelfBackendCompatibility(
  function validateWorkersCompatibility (line 143) | function validateWorkersCompatibility(
  function validateApiFrontendCompatibility (line 193) | function validateApiFrontendCompatibility(
  function isFrontendAllowedWithBackend (line 209) | function isFrontendAllowedWithBackend(
  function supportsConvexBetterAuth (line 235) | function supportsConvexBetterAuth(frontends: readonly Frontend[] = []) {
  function allowedApisForFrontends (line 243) | function allowedApisForFrontends(frontends: Frontend[] = []) {
  function isExampleTodoAllowed (line 255) | function isExampleTodoAllowed(
  function isExampleAIAllowed (line 267) | function isExampleAIAllowed(backend?: ProjectConfig["backend"], frontend...
  function validateWebDeployRequiresWebFrontend (line 282) | function validateWebDeployRequiresWebFrontend(
  function validateServerDeployRequiresBackend (line 294) | function validateServerDeployRequiresBackend(
  function validateAddonCompatibility (line 306) | function validateAddonCompatibility(
  function getCompatibleAddons (line 339) | function getCompatibleAddons(
  function validateAddonsAgainstFrontends (line 357) | function validateAddonsAgainstFrontends(
  function validateAddonsAgainstConfig (line 384) | function validateAddonsAgainstConfig(
  function validatePaymentsCompatibility (line 397) | function validatePaymentsCompatibility(
  function validateExamplesCompatibility (line 423) | function validateExamplesCompatibility(

FILE: apps/cli/src/utils/compatibility.ts
  constant WEB_FRAMEWORKS (line 3) | const WEB_FRAMEWORKS: readonly Frontend[] = [

FILE: apps/cli/src/utils/config-processing.ts
  function processArrayOption (line 22) | function processArrayOption<T>(options: (T | "none")[] | undefined) {
  function deriveProjectName (line 28) | function deriveProjectName(projectName?: string, projectDirectory?: stri...
  function processFlags (line 38) | function processFlags(options: CLIInput, projectName?: string) {
  function getProvidedFlags (line 121) | function getProvidedFlags(options: CLIInput) {
  function validateNoneExclusivity (line 127) | function validateNoneExclusivity<T>(
  function validateArrayOptions (line 143) | function validateArrayOptions(options: CLIInput): Result<void, Validatio...

FILE: apps/cli/src/utils/config-validation.ts
  type ValidationResult (line 21) | type ValidationResult = Result<void, ValidationError>;
  function validationErr (line 23) | function validationErr(message: string): ValidationResult {
  function hasResolvedWorkersD1Target (line 27) | function hasResolvedWorkersD1Target(config: Partial<ProjectConfig>) {
  function hasResolvedSelfCloudflareD1Target (line 35) | function hasResolvedSelfCloudflareD1Target(config: Partial<ProjectConfig...
  function canResolveWorkersD1Target (line 41) | function canResolveWorkersD1Target(config: Partial<ProjectConfig>) {
  function canResolveSelfCloudflareD1Target (line 49) | function canResolveSelfCloudflareD1Target(config: Partial<ProjectConfig>) {
  function validateOrmDatabaseCompat (line 63) | function validateOrmDatabaseCompat(
  function validateDatabaseOrmAuth (line 100) | function validateDatabaseOrmAuth(
  function validateDatabaseSetup (line 109) | function validateDatabaseSetup(
  function validateConvexConstraints (line 223) | function validateConvexConstraints(
  function validateBackendNoneConstraints (line 300) | function validateBackendNoneConstraints(
  function validateSelfBackendConstraints (line 363) | function validateSelfBackendConstraints(
  function validateBackendConstraints (line 384) | function validateBackendConstraints(
  function validateFrontendConstraints (line 432) | function validateFrontendConstraints(
  function validateApiConstraints (line 464) | function validateApiConstraints(
  function validateFullConfig (line 483) | function validateFullConfig(
  function validateConfigForProgrammaticUse (line 552) | function validateConfigForProgrammaticUse(config: Partial<ProjectConfig>...

FILE: apps/cli/src/utils/context.ts
  type NavigationState (line 5) | type NavigationState = {
  type CLIContext (line 10) | type CLIContext = {
  function defaultContext (line 21) | function defaultContext(): CLIContext {
  function getContext (line 32) | function getContext(): CLIContext {
  function tryGetContext (line 40) | function tryGetContext(): CLIContext | undefined {
  function isSilent (line 44) | function isSilent(): boolean {
  function isVerbose (line 48) | function isVerbose(): boolean {
  function getNavigation (line 52) | function getNavigation(): NavigationState {
  function isFirstPrompt (line 56) | function isFirstPrompt(): boolean {
  function didLastPromptShowUI (line 60) | function didLastPromptShowUI(): boolean {
  function getProjectDir (line 64) | function getProjectDir(): string | undefined {
  function getPackageManager (line 68) | function getPackageManager(): PackageManager | undefined {
  function setIsFirstPrompt (line 72) | function setIsFirstPrompt(value: boolean): void {
  function setLastPromptShownUI (line 79) | function setLastPromptShownUI(value: boolean): void {
  function setProjectInfo (line 86) | function setProjectInfo(info: {
  type ContextOptions (line 99) | type ContextOptions = {
  function runWithContext (line 107) | function runWithContext<T>(options: ContextOptions, fn: () => T): T {
  function runWithContextAsync (line 123) | async function runWithContextAsync<T>(

FILE: apps/cli/src/utils/display-config.ts
  function displayConfig (line 5) | function displayConfig(config: Partial<ProjectConfig>) {

FILE: apps/cli/src/utils/docker-utils.ts
  function isDockerInstalled (line 10) | async function isDockerInstalled() {
  function isDockerRunning (line 14) | async function isDockerRunning(): Promise<boolean> {
  function getDockerInstallInstructions (line 26) | function getDockerInstallInstructions(platform: string, database: Databa...
  function getDockerStatus (line 51) | async function getDockerStatus(database: Database) {

FILE: apps/cli/src/utils/env-utils.ts
  type EnvVariable (line 3) | interface EnvVariable {
  function addEnvVariablesToFile (line 9) | async function addEnvVariablesToFile(

FILE: apps/cli/src/utils/errors.ts
  class UserCancelledError (line 14) | class UserCancelledError extends TaggedError("UserCancelledError")<{
    method constructor (line 17) | constructor(args?: { message?: string }) {
  class CLIError (line 25) | class CLIError extends TaggedError("CLIError")<{
  class ValidationError (line 33) | class ValidationError extends TaggedError("ValidationError")<{
    method constructor (line 38) | constructor(args: { field?: string; value?: unknown; message: string }) {
  class CompatibilityError (line 46) | class CompatibilityError extends TaggedError("CompatibilityError")<{
    method constructor (line 50) | constructor(args: { options: string[]; message: string }) {
  class DirectoryConflictError (line 58) | class DirectoryConflictError extends TaggedError("DirectoryConflictError...
    method constructor (line 62) | constructor(args: { directory: string }) {
  class ProjectCreationError (line 73) | class ProjectCreationError extends TaggedError("ProjectCreationError")<{
    method constructor (line 78) | constructor(args: { phase: string; message: string; cause?: unknown }) {
  class DatabaseSetupError (line 86) | class DatabaseSetupError extends TaggedError("DatabaseSetupError")<{
    method constructor (line 91) | constructor(args: { provider: string; message: string; cause?: unknown...
  class AddonSetupError (line 99) | class AddonSetupError extends TaggedError("AddonSetupError")<{
    method constructor (line 104) | constructor(args: { addon: string; message: string; cause?: unknown }) {
  type AppError (line 116) | type AppError =
  function cliError (line 133) | function cliError(message: string): Result<never, CLIError> {
  function validationError (line 140) | function validationError(
  function compatibilityError (line 151) | function compatibilityError(
  function userCancelled (line 161) | function userCancelled(message?: string): Result<never, UserCancelledErr...
  function directoryConflict (line 168) | function directoryConflict(directory: string): Result<never, DirectoryCo...
  function projectCreationError (line 175) | function projectCreationError(
  function databaseSetupError (line 186) | function databaseSetupError(
  function addonSetupError (line 197) | function addonSetupError(
  function displayError (line 212) | function displayError(error: AppError): void {
  function handleResultError (line 223) | function handleResultError(error: AppError): never {

FILE: apps/cli/src/utils/external-commands.ts
  function shouldSkipExternalCommands (line 1) | function shouldSkipExternalCommands(): boolean {

FILE: apps/cli/src/utils/file-formatter.ts
  function formatCode (line 16) | async function formatCode(filePath: string, content: string): Promise<st...
  function formatProject (line 33) | async function formatProject(

FILE: apps/cli/src/utils/get-latest-cli-version.ts
  function getLatestCLIVersionResult (line 9) | function getLatestCLIVersionResult(): Result<string, CLIError> {
  function getLatestCLIVersion (line 25) | function getLatestCLIVersion(): string {

FILE: apps/cli/src/utils/input-hardening.ts
  type ValidationResult (line 5) | type ValidationResult = Result<void, ValidationError>;
  function hasControlCharacters (line 7) | function hasControlCharacters(value: string): boolean {
  function hardeningError (line 17) | function hardeningError(field: string, value: string, message: string): ...
  function validateAgentSafePathInput (line 27) | function validateAgentSafePathInput(value: string, field: string): Valid...

FILE: apps/cli/src/utils/navigation.ts
  constant GO_BACK_SYMBOL (line 1) | const GO_BACK_SYMBOL = Symbol("clack:goBack");
  function isGoBack (line 3) | function isGoBack(value: unknown): value is symbol {

FILE: apps/cli/src/utils/open-url.ts
  function openUrl (line 3) | async function openUrl(url: string): Promise<void> {

FILE: apps/cli/src/utils/package-runner.ts
  function splitCommandArgs (line 3) | function splitCommandArgs(commandWithArgs: string): string[] {
  function getPackageExecutionCommand (line 59) | function getPackageExecutionCommand(
  function getPackageExecutionArgs (line 81) | function getPackageExecutionArgs(
  function getPackageRunnerPrefix (line 108) | function getPackageRunnerPrefix(

FILE: apps/cli/src/utils/project-directory.ts
  function handleDirectoryConflict (line 12) | async function handleDirectoryConflict(currentPathInput: string): Promise<{
  function setupProjectDirectory (line 84) | async function setupProjectDirectory(

FILE: apps/cli/src/utils/project-history.ts
  constant HISTORY_FILE (line 11) | const HISTORY_FILE = "history.json";
  class HistoryError (line 13) | class HistoryError extends TaggedError("HistoryError")<{
  type ProjectHistoryEntry (line 18) | type ProjectHistoryEntry = {
  type HistoryData (line 41) | type HistoryData = {
  function getHistoryDir (line 46) | function getHistoryDir(): string {
  function getHistoryPath (line 50) | function getHistoryPath(): string {
  function generateId (line 54) | function generateId(): string {
  function emptyHistory (line 58) | function emptyHistory(): HistoryData {
  function ensureHistoryDir (line 62) | async function ensureHistoryDir(): Promise<Result<void, HistoryError>> {
  function readHistory (line 75) | async function readHistory(): Promise<Result<HistoryData, HistoryError>> {
  function writeHistory (line 112) | async function writeHistory(history: HistoryData): Promise<Result<void, ...
  function addToHistory (line 130) | async function addToHistory(
  function getHistory (line 174) | async function getHistory(limit = 10): Promise<Result<ProjectHistoryEntr...
  function clearHistory (line 182) | async function clearHistory(): Promise<Result<void, HistoryError>> {
  function removeFromHistory (line 199) | async function removeFromHistory(id: string): Promise<Result<boolean, Hi...

FILE: apps/cli/src/utils/project-name-validation.ts
  type ValidationResult (line 9) | type ValidationResult<T> = Result<T, ValidationError>;
  function validateProjectName (line 11) | function validateProjectName(name: string): ValidationResult<void> {
  function extractAndValidateProjectName (line 30) | function extractAndValidateProjectName(

FILE: apps/cli/src/utils/render-title.ts
  constant TITLE_TEXT (line 3) | const TITLE_TEXT = `

FILE: apps/cli/src/utils/sponsors.ts
  constant SPONSORS_JSON_URL (line 9) | const SPONSORS_JSON_URL = "https://sponsors.better-t-stack.dev/sponsors....
  constant GITHUB_SPONSOR_URL (line 10) | const GITHUB_SPONSOR_URL = "https://github.com/sponsors/AmanVarshney01";
  type SponsorSummary (line 12) | type SponsorSummary = {
  type Sponsor (line 26) | type Sponsor = {
  type SponsorEntry (line 39) | type SponsorEntry = {
  type FetchSponsorsOptions (line 48) | type FetchSponsorsOptions = {
  function fetchSponsors (line 102) | async function fetchSponsors(url: string = SPONSORS_JSON_URL) {
  function fetchSponsorsQuietly (line 106) | async function fetchSponsorsQuietly({
  function displaySponsors (line 113) | function displaySponsors(sponsors: SponsorEntry) {
  function displaySponsorsBox (line 131) | function displaySponsorsBox(sponsors: SponsorEntry) {
  function formatPostInstallSpecialSponsorsSection (line 158) | function formatPostInstallSpecialSponsorsSection(sponsors: SponsorEntry)...
  function getPostInstallSponsorLineWidth (line 176) | function getPostInstallSponsorLineWidth(): number {
  function wrapSponsorTokens (line 187) | function wrapSponsorTokens(tokens: string[], maxLineWidth: number): stri...
  function fetchSponsorsData (line 216) | async function fetchSponsorsData({
  function normalizeSponsorFetchError (line 273) | function normalizeSponsorFetchError(error: unknown): CLIError {

FILE: apps/cli/src/utils/telemetry.ts
  function isTelemetryEnabled (line 7) | function isTelemetryEnabled() {

FILE: apps/cli/src/utils/templates.ts
  constant TEMPLATE_PRESETS (line 3) | const TEMPLATE_PRESETS: Record<Template, CreateInput | null> = {
  function getTemplateConfig (line 67) | function getTemplateConfig(template: Template) {
  function getTemplateDescription (line 80) | function getTemplateDescription(template: Template) {
  function listAvailableTemplates (line 92) | function listAvailableTemplates() {

FILE: apps/cli/src/utils/terminal-output.ts
  type SpinnerLike (line 6) | type SpinnerLike = {
  method start (line 13) | start() {}
  method stop (line 14) | stop() {}
  method message (line 15) | message() {}
  function createSpinner (line 18) | function createSpinner(): SpinnerLike {
  method info (line 31) | info(message: string) {
  method warn (line 34) | warn(message: string) {
  method success (line 37) | success(message: string) {
  method error (line 40) | error(message: string) {
  method message (line 43) | message(message: string) {
  method error (line 49) | error(message: string) {
  method warn (line 52) | warn(message: string) {
  method info (line 55) | info(message: string) {
  method fatal (line 58) | fatal(message: string) {
  method box (line 61) | box(message: string) {

FILE: apps/cli/src/utils/ts-morph.ts
  function ensureArrayProperty (line 19) | function ensureArrayProperty(obj: ObjectLiteralExpression, name: string) {

FILE: apps/cli/src/validation.ts
  type ValidationResult (line 9) | type ValidationResult<T> = Result<T, ValidationError>;
  constant CORE_STACK_FLAGS (line 11) | const CORE_STACK_FLAGS = new Set([
  function validateYesFlagCombination (line 27) | function validateYesFlagCombination(
  function processAndValidateFlags (line 54) | function processAndValidateFlags(
  function processProvidedFlagsWithoutValidation (line 102) | function processProvidedFlagsWithoutValidation(
  function validateConfigCompatibility (line 130) | function validateConfigCompatibility(

FILE: apps/cli/test/addon-options.test.ts
  constant SMOKE_DIR_PATH (line 9) | const SMOKE_DIR_PATH = path.join(import.meta.dir, "..", ".smoke");

FILE: apps/cli/test/addon-setup-regressions.test.ts
  function createProjectConfig (line 12) | function createProjectConfig(overrides: Partial<ProjectConfig> = {}): Pr...
  function writeFakeBunx (line 37) | async function writeFakeBunx(binDir: string, markerFile: string, exitCod...
  function runWithFakeBunx (line 50) | async function runWithFakeBunx<T>(

FILE: apps/cli/test/addons.test.ts
  function readSourceFiles (line 18) | async function readSourceFiles(dir: string): Promise<{ path: string; con...
  function expectParseableTypeScript (line 34) | function expectParseableTypeScript(content: string) {
  function expectDocsShapedEvlogAuth (line 49) | function expectDocsShapedEvlogAuth(content: string) {

FILE: apps/cli/test/clerk-matrix.test.ts
  function buildFrontendCombos (line 29) | function buildFrontendCombos(
  function expectedContextImport (line 47) | function expectedContextImport(backend: string) {
  function usesBackendClerkClient (line 53) | function usesBackendClerkClient(backend: string, api: string) {
  function needsServerClerkPublishableKey (line 57) | function needsServerClerkPublishableKey(backend: string, api: string) {

FILE: apps/cli/test/cloudflare-db-clients.test.ts
  function createVirtualFiles (line 6) | async function createVirtualFiles(config: Parameters<typeof createVirtua...

FILE: apps/cli/test/db-setup-options.test.ts
  constant SMOKE_DIR_PATH (line 9) | const SMOKE_DIR_PATH = path.join(import.meta.dir, "..", ".smoke");

FILE: apps/cli/test/dry-run.test.ts
  constant SMOKE_DIR_PATH (line 8) | const SMOKE_DIR_PATH = path.join(import.meta.dir, "..", ".smoke");

FILE: apps/cli/test/mcp.test.ts
  function connectInMemoryClient (line 14) | async function connectInMemoryClient() {
  function getExplicitCreateInput (line 31) | function getExplicitCreateInput(projectPath: string) {

FILE: apps/cli/test/project-name-validation.test.ts
  constant SMOKE_DIR_PATH (line 12) | const SMOKE_DIR_PATH = path.join(import.meta.dir, "..", ".smoke");

FILE: apps/cli/test/readme.test.ts
  function generateReadme (line 6) | async function generateReadme(config: Parameters<typeof createVirtual>[0...

FILE: apps/cli/test/setup.ts
  constant SMOKE_DIR (line 5) | const SMOKE_DIR = join(import.meta.dir, "..", ".smoke");
  type VirtualFileNode (line 7) | type VirtualFileNode = {
  type VirtualDirectoryNode (line 13) | type VirtualDirectoryNode = {
  type VirtualNode (line 19) | type VirtualNode = VirtualFileNode | VirtualDirectoryNode;
  function ensureSmokeDirectory (line 21) | async function ensureSmokeDirectory() {
  function cleanupSmokeDirectory (line 25) | async function cleanupSmokeDirectory() {
  function collectFiles (line 29) | function collectFiles(

FILE: apps/cli/test/silent-create-output.test.ts
  constant CLI_INDEX_PATH (line 9) | const CLI_INDEX_PATH = path.join(import.meta.dir, "..", "src", "index.ts");
  type SilentCreateCase (line 11) | type SilentCreateCase = {
  function runSilentCreate (line 17) | async function runSilentCreate(testCase: SilentCreateCase) {

FILE: apps/cli/test/sponsors.test.ts
  function createSponsorsFixture (line 6) | function createSponsorsFixture(): SponsorEntry {

FILE: apps/cli/test/test-utils.ts
  constant SMOKE_DIR_PATH (line 41) | const SMOKE_DIR_PATH = join(import.meta.dir, "..", ".smoke");
  type TestResult (line 43) | interface TestResult {
  type TestConfig (line 51) | interface TestConfig extends CreateInput {
  function runTRPCTest (line 61) | async function runTRPCTest(config: TestConfig): Promise<TestResult> {
  function expectSuccess (line 167) | function expectSuccess(result: TestResult) {
  function expectError (line 179) | function expectError(result: TestResult, expectedMessage?: string) {
  function createTestConfig (line 187) | function createTestConfig(
  function extractEnumValues (line 196) | function extractEnumValues<T extends string>(schema: { options: readonly...
  constant PACKAGE_MANAGERS (line 201) | const PACKAGE_MANAGERS = extractEnumValues(PackageManagerSchema);
  constant DATABASES (line 202) | const DATABASES = extractEnumValues(DatabaseSchema);
  constant ORMS (line 203) | const ORMS = extractEnumValues(ORMSchema);
  constant BACKENDS (line 204) | const BACKENDS = extractEnumValues(BackendSchema);
  constant RUNTIMES (line 205) | const RUNTIMES = extractEnumValues(RuntimeSchema);
  constant FRONTENDS (line 206) | const FRONTENDS = extractEnumValues(FrontendSchema);
  constant ADDONS (line 207) | const ADDONS = extractEnumValues(AddonsSchema);
  constant EXAMPLES (line 208) | const EXAMPLES = extractEnumValues(ExamplesSchema);
  constant AUTH_PROVIDERS (line 209) | const AUTH_PROVIDERS = extractEnumValues(AuthSchema);
  constant PAYMENTS_PROVIDERS (line 210) | const PAYMENTS_PROVIDERS = extractEnumValues(PaymentsSchema);
  constant API_TYPES (line 211) | const API_TYPES = extractEnumValues(APISchema);
  constant WEB_DEPLOYS (line 212) | const WEB_DEPLOYS = extractEnumValues(WebDeploySchema);
  constant SERVER_DEPLOYS (line 213) | const SERVER_DEPLOYS = extractEnumValues(ServerDeploySchema);
  constant DB_SETUPS (line 214) | const DB_SETUPS = extractEnumValues(DatabaseSetupSchema);
  function createBasicConfig (line 217) | function createBasicConfig(overrides: Partial<TestConfig> = {}): TestCon...
  function createCustomConfig (line 227) | function createCustomConfig(config: Partial<TestConfig>): TestConfig {

FILE: apps/cli/test/tui-setup.test.ts
  function createTuiConfig (line 11) | function createTuiConfig(overrides: Partial<ProjectConfig> = {}): Projec...

FILE: apps/web/next.config.ts
  method rewrites (line 20) | async rewrites() {

FILE: apps/web/src/app/(home)/_components/FeatureCard.tsx
  type TechOption (line 10) | type TechOption = {
  type FeatureCardProps (line 16) | type FeatureCardProps = {
  function TechIcon (line 23) | function TechIcon({ icon, name, className }: { icon: string; name: strin...
  function FeatureCard (line 59) | function FeatureCard({ title, options, className }: FeatureCardProps) {

FILE: apps/web/src/app/(home)/_components/command-section.tsx
  function CommandSection (line 16) | function CommandSection() {

FILE: apps/web/src/app/(home)/_components/hero-section.tsx
  function HeroSection (line 3) | function HeroSection() {

FILE: apps/web/src/app/(home)/_components/shiny-text.tsx
  type ShinyTextProps (line 1) | interface ShinyTextProps {

FILE: apps/web/src/app/(home)/_components/sponsors-section.tsx
  function SponsorsSection (line 15) | function SponsorsSection({ sponsorsData }: { sponsorsData: SponsorsData ...

FILE: apps/web/src/app/(home)/_components/stats-section.tsx
  function StatsSection (line 10) | function StatsSection() {

FILE: apps/web/src/app/(home)/_components/testimonials.tsx
  function ArchiveToggleButton (line 33) | function ArchiveToggleButton({
  function Testimonials (line 129) | function Testimonials({

FILE: apps/web/src/app/(home)/analytics/_components/analytics-header.tsx
  function formatUtcDateTime (line 24) | function formatUtcDateTime(value: string) {
  function formatUtcDate (line 28) | function formatUtcDate(value: string) {
  function HeaderStat (line 32) | function HeaderStat({
  function AnalyticsHeader (line 52) | function AnalyticsHeader({

FILE: apps/web/src/app/(home)/analytics/_components/analytics-helpers.ts
  constant MILLISECONDS_PER_DAY (line 29) | const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
  function formatCompactNumber (line 31) | function formatCompactNumber(value: number): string {
  function formatCount (line 35) | function formatCount(value: number): string {
  function formatPercent (line 39) | function formatPercent(value: number, precise = value > 0 && value < 0.1...
  function formatDelta (line 43) | function formatDelta(value: number | null): string {
  function formatDateLabel (line 50) | function formatDateLabel(date: string): string {
  function formatMonthLabel (line 54) | function formatMonthLabel(month: string, pattern = "MMM yyyy"): string {
  function formatHourLabel (line 58) | function formatHourLabel(hour: string): string {
  function shortenLabel (line 62) | function shortenLabel(value: string, maxLength = 18): string {
  function shortenMiddleLabel (line 66) | function shortenMiddleLabel(value: string, maxLength = 18): string {
  function buildCompactCategoryLabels (line 76) | function buildCompactCategoryLabels(values: string[], maxLength = 12): s...
  function withShare (line 108) | function withShare(items: Distribution, total?: number): ShareDistributi...
  function versionWithShare (line 120) | function versionWithShare(
  function buildWeekdayDistribution (line 135) | function buildWeekdayDistribution(timeSeries: TimeSeriesPoint[]): Weekda...
  type MatrixOptions (line 180) | type MatrixOptions = {
  function buildComboMatrix (line 189) | function buildComboMatrix({
  function splitComboLabel (line 246) | function splitComboLabel(value: string): [string, string] {
  function getTrendTone (line 251) | function getTrendTone(deltaPercentage: number | null): "up" | "down" | "...

FILE: apps/web/src/app/(home)/analytics/_components/analytics-page.tsx
  function AnalyticsPage (line 13) | function AnalyticsPage({

FILE: apps/web/src/app/(home)/analytics/_components/analytics-sources.tsx
  function AnalyticsSources (line 4) | function AnalyticsSources() {

FILE: apps/web/src/app/(home)/analytics/_components/chart-card.tsx
  function ChartCard (line 5) | function ChartCard({

FILE: apps/web/src/app/(home)/analytics/_components/dev-environment-charts.tsx
  function SplitMeterCard (line 13) | function SplitMeterCard({
  function DevToolsSection (line 74) | function DevToolsSection({ data }: { data: AggregatedAnalyticsData }) {

FILE: apps/web/src/app/(home)/analytics/_components/evil-chart-utils.ts
  type EvilTone (line 5) | type EvilTone = "blue" | "teal" | "amber" | "rose" | "violet" | "slate";
  function seriesConfig (line 36) | function seriesConfig<TKey extends string>(
  function multiSeriesConfig (line 49) | function multiSeriesConfig<const TKey extends string>(
  function slugify (line 63) | function slugify(value: string): string {
  type KeyedShareItem (line 72) | type KeyedShareItem = ShareDistributionItem & {
  function toKeyedShareItems (line 76) | function toKeyedShareItems(
  function categoryConfig (line 94) | function categoryConfig(items: KeyedShareItem[], toneOffset = 0): ChartC...
  function getTone (line 110) | function getTone(index: number): EvilTone {

FILE: apps/web/src/app/(home)/analytics/_components/live-logs.tsx
  constant LOG_FIELD_ORDER (line 13) | const LOG_FIELD_ORDER = [
  function formatValue (line 43) | function formatValue(value: unknown): string {
  function hasLogValue (line 50) | function hasLogValue(value: unknown): boolean {
  function formatStackSummary (line 56) | function formatStackSummary(event: Record<string, unknown>) {
  function LiveLogs (line 69) | function LiveLogs() {

FILE: apps/web/src/app/(home)/analytics/_components/metrics-cards.tsx
  function MetricTile (line 20) | function MetricTile({
  function MetricsCards (line 53) | function MetricsCards({ data }: { data: AggregatedAnalyticsData }) {

FILE: apps/web/src/app/(home)/analytics/_components/preference-chart-card.tsx
  function chunkItems (line 16) | function chunkItems<T>(items: T[], chunkCount: number) {
  type PreferenceChartCardProps (line 27) | type PreferenceChartCardProps = {
  function PreferenceChartCard (line 48) | function PreferenceChartCard({

FILE: apps/web/src/app/(home)/analytics/_components/section-header.tsx
  function SectionHeader (line 3) | function SectionHeader({

FILE: apps/web/src/app/(home)/analytics/_components/stack-configuration-charts.tsx
  function StackSection (line 8) | function StackSection({ data }: { data: AggregatedAnalyticsData }) {

FILE: apps/web/src/app/(home)/analytics/_components/timeline-charts.tsx
  function TimelineSection (line 17) | function TimelineSection({ data }: { data: AggregatedAnalyticsData }) {

FILE: apps/web/src/app/(home)/analytics/_components/types.ts
  type DistributionItem (line 1) | type DistributionItem = { name: string; value: number };
  type Distribution (line 2) | type Distribution = DistributionItem[];
  type ShareDistributionItem (line 4) | type ShareDistributionItem = DistributionItem & {
  type VersionDistributionItem (line 8) | type VersionDistributionItem = {
  type VersionDistribution (line 14) | type VersionDistribution = VersionDistributionItem[];
  type TimeSeriesPoint (line 16) | type TimeSeriesPoint = {
  type MonthlyPoint (line 24) | type MonthlyPoint = {
  type HourlyPoint (line 31) | type HourlyPoint = {
  type WeekdayPoint (line 38) | type WeekdayPoint = {
  type ComboMatrixPoint (line 46) | type ComboMatrixPoint = {
  type ComboMatrix (line 53) | type ComboMatrix = {
  type MomentumSnapshot (line 60) | type MomentumSnapshot = {
  type AggregatedAnalyticsData (line 71) | type AggregatedAnalyticsData = {

FILE: apps/web/src/app/(home)/analytics/analytics-client.tsx
  type PrecomputedStats (line 17) | type PrecomputedStats = {
  type DailyStats (line 44) | type DailyStats = { date: string; count: number };
  type MonthlyStats (line 45) | type MonthlyStats = {
  type ConnectionStatus (line 50) | type ConnectionStatus = "online" | "connecting" | "reconnecting" | "offl...
  constant MILLISECONDS_PER_DAY (line 52) | const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
  function getConnectionStatus (line 54) | function getConnectionStatus({
  function recordToDistribution (line 69) | function recordToDistribution(record: Record<string, number>): Distribut...
  function getMostPopular (line 75) | function getMostPopular(dist: Distribution) {
  function getCalendarDaySpan (line 79) | function getCalendarDaySpan(timeSeries: DailyStats[]): number {
  function getCalendarDaySpanFromRange (line 96) | function getCalendarDaySpanFromRange(
  function buildTimeSeries (line 115) | function buildTimeSeries(dailyStats: DailyStats[]): TimeSeriesPoint[] {
  function buildMonthlyTimeSeries (line 135) | function buildMonthlyTimeSeries(monthlyStats: MonthlyStats["monthly"]) {
  function buildFromPrecomputed (line 151) | function buildFromPrecomputed(
  function AnalyticsClient (line 354) | function AnalyticsClient({

FILE: apps/web/src/app/(home)/analytics/page.tsx
  function Analytics (line 31) | async function Analytics() {

FILE: apps/web/src/app/(home)/layout.tsx
  function Layout (line 8) | function Layout({ children }: { children: ReactNode }) {

FILE: apps/web/src/app/(home)/new/_components/action-buttons.tsx
  type ActionButtonsProps (line 5) | type ActionButtonsProps = {
  function ActionButtons (line 13) | function ActionButtons({

FILE: apps/web/src/app/(home)/new/_components/code-viewer.tsx
  type CodeViewerProps (line 17) | interface CodeViewerProps {
  function getLanguage (line 24) | function getLanguage(extension: string): BundledLanguage {
  type EmptyStateProps (line 114) | interface EmptyStateProps {
  function CodeViewerEmpty (line 118) | function CodeViewerEmpty({

FILE: apps/web/src/app/(home)/new/_components/file-explorer.tsx
  type VirtualFile (line 7) | interface VirtualFile {
  type VirtualDirectory (line 15) | interface VirtualDirectory {
  type VirtualNode (line 22) | type VirtualNode = VirtualFile | VirtualDirectory;
  type FileExplorerProps (line 24) | interface FileExplorerProps {
  function collectInitialExpandedItems (line 30) | function collectInitialExpandedItems(node: VirtualDirectory, depth: numb...
  function FileExplorer (line 43) | function FileExplorer({ root, selectedPath, onSelectFile }: FileExplorer...
  type DirectoryContentsProps (line 60) | interface DirectoryContentsProps {
  function DirectoryContents (line 66) | function DirectoryContents({ node, selectedPath, onSelectFile }: Directo...

FILE: apps/web/src/app/(home)/new/_components/preset-dropdown.tsx
  type PresetDropdownProps (line 14) | type PresetDropdownProps = {
  function PresetDropdown (line 18) | function PresetDropdown({ onApplyPreset }: PresetDropdownProps) {

FILE: apps/web/src/app/(home)/new/_components/preview-panel.tsx
  type PreviewPanelProps (line 13) | interface PreviewPanelProps {
  type PreviewResponse (line 19) | interface PreviewResponse {
  function PreviewPanel (line 29) | function PreviewPanel({ stack, selectedFilePath, onSelectFile }: Preview...

FILE: apps/web/src/app/(home)/new/_components/share-button.tsx
  type ShareButtonProps (line 8) | interface ShareButtonProps {
  function ShareButton (line 13) | function ShareButton({ stackUrl, stackState }: ShareButtonProps) {

FILE: apps/web/src/app/(home)/new/_components/special-sponsors-panel.tsx
  type SpecialSponsorsPanelProps (line 12) | type SpecialSponsorsPanelProps = {
  constant SPONSOR_ME_URL (line 17) | const SPONSOR_ME_URL = "https://github.com/sponsors/AmanVarshney01";
  function SpecialSponsorsPanel (line 19) | function SpecialSponsorsPanel({ sponsors, compact = false }: SpecialSpon...

FILE: apps/web/src/app/(home)/new/_components/stack-builder/index.tsx
  type StackBuilderProps (line 36) | type StackBuilderProps = {
  function StackBuilder (line 40) | function StackBuilder({ specialSponsors = [] }: StackBuilderProps) {

FILE: apps/web/src/app/(home)/new/_components/stack-builder/selected-stack-badges.tsx
  type SelectedStackBadgesProps (line 13) | type SelectedStackBadgesProps = {
  function SelectedStackBadges (line 18) | function SelectedStackBadges({ stack, onRemove }: SelectedStackBadgesPro...

FILE: apps/web/src/app/(home)/new/_components/stack-builder/tech-categories.tsx
  type TechCategoriesProps (line 14) | type TechCategoriesProps = {
  function getIsSelected (line 22) | function getIsSelected(stack: StackState, category: keyof StackState, te...
  function TechCategories (line 37) | function TechCategories({

FILE: apps/web/src/app/(home)/new/_components/stack-builder/use-stack-builder.ts
  type MobileTab (line 12) | type MobileTab = "build" | "preview";
  type CategoryProgressItem (line 14) | type CategoryProgressItem = {
  constant CATEGORY_LIST (line 21) | const CATEGORY_LIST = CATEGORY_ORDER as TechCategory[];
  function formatProjectName (line 23) | function formatProjectName(name: string) {
  function withFormattedProjectName (line 27) | function withFormattedProjectName(stack: StackState) {
  function getCompatibilityAdjustmentKey (line 35) | function getCompatibilityAdjustmentKey(stack: StackState, adjustedStack:...
  function getCompatibilityAdjustmentState (line 39) | function getCompatibilityAdjustmentState(
  function useStackBuilder (line 58) | function useStackBuilder() {

FILE: apps/web/src/app/(home)/new/_components/tech-icon.tsx
  function TechIcon (line 6) | function TechIcon({

FILE: apps/web/src/app/(home)/new/_components/utils.ts
  function validateProjectName (line 6) | function validateProjectName(name: string): string | undefined {
  type CompatibilityResult (line 109) | interface CompatibilityResult {

FILE: apps/web/src/app/(home)/new/_components/yolo-toggle.tsx
  type YoloToggleProps (line 10) | interface YoloToggleProps {
  function YoloToggle (line 15) | function YoloToggle({ stack, onToggle }: YoloToggleProps) {

FILE: apps/web/src/app/(home)/new/page.tsx
  function FullScreenStackBuilder (line 32) | async function FullScreenStackBuilder() {

FILE: apps/web/src/app/(home)/page.tsx
  function HomePage (line 15) | async function HomePage() {

FILE: apps/web/src/app/(home)/showcase/_components/ShowcaseItem.tsx
  type ShowcaseItemProps (line 8) | interface ShowcaseItemProps {
  function ShowcaseItem (line 18) | function ShowcaseItem({

FILE: apps/web/src/app/(home)/showcase/_components/showcase-page.tsx
  type ShowcaseProject (line 8) | type ShowcaseProject = {
  function ShowcasePage (line 18) | function ShowcasePage({ showcaseProjects }: { showcaseProjects: Array<Sh...

FILE: apps/web/src/app/(home)/showcase/page.tsx
  function Showcase (line 33) | async function Showcase() {

FILE: apps/web/src/app/(home)/stack/_components/stack-display.tsx
  type StackDisplayProps (line 20) | type StackDisplayProps = {
  function StackDisplay (line 24) | function StackDisplay({ stackState }: StackDisplayProps) {

FILE: apps/web/src/app/(home)/stack/page.tsx
  type StackPageProps (line 8) | interface StackPageProps {
  function generateMetadata (line 12) | async function generateMetadata({ searchParams }: StackPageProps): Promi...
  function StackPage (line 44) | async function StackPage({ searchParams }: StackPageProps) {

FILE: apps/web/src/app/api/preview/route.ts
  function POST (line 9) | async function POST(request: Request) {
  function transformTree (line 55) | function transformTree(node: VirtualNode): Record<string, unknown> {
  function normalizeBoolean (line 74) | function normalizeBoolean(value: boolean | string | undefined, fallback:...
  function normalizeBackend (line 80) | function normalizeBackend(value?: string): ProjectConfig["backend"] {
  function stackStateToConfig (line 86) | function stackStateToConfig(state: StackState): ProjectConfig {

FILE: apps/web/src/app/docs/[[...slug]]/page.tsx
  function Page (line 12) | async function Page(props: PageProps<"/docs/[[...slug]]">) {
  function generateStaticParams (line 60) | async function generateStaticParams() {
  function generateMetadata (line 64) | async function generateMetadata({

FILE: apps/web/src/app/docs/layout.tsx
  function Layout (line 17) | function Layout({ children }: { children: ReactNode }) {

FILE: apps/web/src/app/layout.tsx
  function Layout (line 113) | function Layout({ children }: { children: ReactNode }) {

FILE: apps/web/src/app/llms-full.txt/route.ts
  function GET (line 7) | async function GET() {

FILE: apps/web/src/app/llms.mdx/[[...slug]]/route.ts
  function GET (line 8) | async function GET(_req: Request, { params }: RouteContext<"/llms.mdx/[[...
  function generateStaticParams (line 20) | function generateStaticParams() {

FILE: apps/web/src/app/manifest.ts
  function manifest (line 5) | function manifest(): MetadataRoute.Manifest {

FILE: apps/web/src/app/not-found.tsx
  function NotFound (line 6) | function NotFound() {

FILE: apps/web/src/app/og/docs/[...slug]/route.tsx
  function GET (line 8) | async function GET(_req: Request, { params }: RouteContext<"/og/docs/[.....
  function generateStaticParams (line 174) | function generateStaticParams() {

FILE: apps/web/src/app/sitemap.ts
  function sitemap (line 5) | function sitemap(): MetadataRoute.Sitemap {

FILE: apps/web/src/components/ai/page-actions.tsx
  function LLMCopyButton (line 13) | function LLMCopyButton({
  function ViewOptions (line 67) | function ViewOptions({

FILE: apps/web/src/components/evilcharts/charts/area-chart.tsx
  constant STROKE_WIDTH (line 35) | const STROKE_WIDTH = 0.8;
  constant LOADING_AREA_DATA_KEY (line 36) | const LOADING_AREA_DATA_KEY = "loading";
  constant LOADING_ANIMATION_DURATION (line 37) | const LOADING_ANIMATION_DURATION = 2000;
  type ChartProps (line 39) | type ChartProps = ComponentProps<typeof AreaChart>;
  type XAxisProps (line 40) | type XAxisProps = ComponentProps<typeof XAxis>;
  type YAxisProps (line 41) | type YAxisProps = ComponentProps<typeof YAxis>;
  type AreaType (line 42) | type AreaType = ComponentProps<typeof Area>["type"];
  type AreaVariant (line 43) | type AreaVariant = "gradient" | "gradient-reverse" | "solid" | "dotted" ...
  type StrokeVariant (line 44) | type StrokeVariant = "solid" | "dashed" | "animated-dashed";
  type StackType (line 45) | type StackType = "default" | "expanded" | "stacked";
  type ValidateConfigKeys (line 48) | type ValidateConfigKeys<TData, TConfig> = {
  type BaseEvilAreaChartProps (line 52) | type BaseEvilAreaChartProps<
  type EvilAreaChartClickable (line 94) | type EvilAreaChartClickable = {
  type EvilAreaChartNotClickable (line 99) | type EvilAreaChartNotClickable = {
  type EvilAreaChartProps (line 104) | type EvilAreaChartProps<
  function EvilAreaChart (line 109) | function EvilAreaChart<
  function useLoadingData (line 867) | function useLoadingData(isLoading: boolean, loadingPoints: number = 14) {

FILE: apps/web/src/components/evilcharts/charts/bar-chart.tsx
  constant DEFAULT_BAR_RADIUS (line 34) | const DEFAULT_BAR_RADIUS = 2;
  constant LOADING_BAR_DATA_KEY (line 35) | const LOADING_BAR_DATA_KEY = "loading";
  constant LOADING_ANIMATION_DURATION (line 36) | const LOADING_ANIMATION_DURATION = 2000;
  type ChartProps (line 38) | type ChartProps = ComponentProps<typeof BarChart>;
  type XAxisProps (line 39) | type XAxisProps = ComponentProps<typeof XAxis>;
  type YAxisProps (line 40) | type YAxisProps = ComponentProps<typeof YAxis>;
  type BarVariant (line 41) | type BarVariant = "default" | "hatched" | "duotone" | "duotone-reverse" ...
  type StackType (line 42) | type StackType = "default" | "stacked" | "percent";
  type BarLayout (line 43) | type BarLayout = "vertical" | "horizontal";
  type ValidateConfigKeys (line 46) | type ValidateConfigKeys<TData, TConfig> = {
  type NumericDataKeys (line 51) | type NumericDataKeys<T> = {
  type EvilBarChartProps (line 55) | type EvilBarChartProps<
  type EvilBarChartClickable (line 101) | type EvilBarChartClickable = {
  type EvilBarChartNotClickable (line 106) | type EvilBarChartNotClickable = {
  type EvilBarChartPropsWithCallback (line 111) | type EvilBarChartPropsWithCallback<
  function EvilBarChart (line 116) | function EvilBarChart<
  type BarShapeProps (line 374) | type BarShapeProps = {
  type CustomBarProps (line 386) | type CustomBarProps = {
  function useLoadingData (line 970) | function useLoadingData(isLoading: boolean, loadingBars: number = 12) {

FILE: apps/web/src/components/evilcharts/charts/line-chart.tsx
  constant STROKE_WIDTH (line 43) | const STROKE_WIDTH = 1;
  constant LOADING_LINE_DATA_KEY (line 44) | const LOADING_LINE_DATA_KEY = "loading";
  constant LOADING_ANIMATION_DURATION (line 45) | const LOADING_ANIMATION_DURATION = 2000;
  type ChartProps (line 47) | type ChartProps = ComponentProps<typeof LineChart>;
  type XAxisProps (line 48) | type XAxisProps = ComponentProps<typeof XAxis>;
  type YAxisProps (line 49) | type YAxisProps = ComponentProps<typeof YAxis>;
  type LineType (line 50) | type LineType = ComponentProps<typeof Line>["type"];
  type StrokeVariant (line 51) | type StrokeVariant = "solid" | "dashed" | "animated-dashed";
  type ValidateConfigKeys (line 54) | type ValidateConfigKeys<TData, TConfig> = {
  type NumericDataKeys (line 59) | type NumericDataKeys<T> = {
  type EvilLineChartProps (line 63) | type EvilLineChartProps<
  type EvilLineChartClickable (line 108) | type EvilLineChartClickable = {
  type EvilLineChartNotClickable (line 113) | type EvilLineChartNotClickable = {
  type EvilLineChartPropsWithCallback (line 118) | type EvilLineChartPropsWithCallback<
  function EvilLineChart (line 123) | function EvilLineChart<
  type CurvePoint (line 391) | type CurvePoint = NonNullable<NonNullable<CurveProps["points"]>[number]>;
  type DrawableCurvePoint (line 392) | type DrawableCurvePoint = CurvePoint & { x: number; y: number };
  constant BUFFER_DASH_SIZE (line 398) | const BUFFER_DASH_SIZE = 4;
  constant BUFFER_GAP_SIZE (line 399) | const BUFFER_GAP_SIZE = 3;
  function useLoadingData (line 617) | function useLoadingData(isLoading: boolean, loadingPoints: number = 14) {

FILE: apps/web/src/components/evilcharts/charts/pie-chart.tsx
  constant LOADING_SECTORS (line 27) | const LOADING_SECTORS = 5;
  constant LOADING_ANIMATION_DURATION (line 28) | const LOADING_ANIMATION_DURATION = 2000;
  constant DEFAULT_INNER_RADIUS (line 31) | const DEFAULT_INNER_RADIUS = 0;
  constant DEFAULT_OUTER_RADIUS (line 32) | const DEFAULT_OUTER_RADIUS = "80%";
  constant DEFAULT_CORNER_RADIUS (line 33) | const DEFAULT_CORNER_RADIUS = 0;
  constant DEFAULT_PADDING_ANGLE (line 34) | const DEFAULT_PADDING_ANGLE = 0;
  type ChartProps (line 36) | type ChartProps = ComponentProps<typeof PieChart>;
  type PieProps (line 37) | type PieProps = ComponentProps<typeof Pie>;
  type LabelListProps (line 38) | type LabelListProps = ComponentProps<typeof LabelList>;
  type EvilPieChartProps (line 40) | type EvilPieChartProps<TData extends Record<string, unknown>> = {
  type EvilPieChartClickable (line 81) | type EvilPieChartClickable = {
  type EvilPieChartNotClickable (line 86) | type EvilPieChartNotClickable = {
  type EvilPieChartPropsWithCallback (line 91) | type EvilPieChartPropsWithCallback<TData extends Record<string, unknown>> =
  function EvilPieChart (line 94) | function EvilPieChart<TData extends Record<string, unknown>>({
  constant LOADING_PIE_DATA (line 280) | const LOADING_PIE_DATA = Array.from({ length: LOADING_SECTORS }, (_, i) ...

FILE: apps/web/src/components/evilcharts/charts/radar-chart.tsx
  constant LOADING_POINTS (line 28) | const LOADING_POINTS = 6;
  constant LOADING_ANIMATION_DURATION (line 29) | const LOADING_ANIMATION_DURATION = 1500;
  constant DEFAULT_FILL_OPACITY (line 32) | const DEFAULT_FILL_OPACITY = 0.3;
  type ChartProps (line 34) | type ChartProps = ComponentProps<typeof RadarChart>;
  type RadarProps (line 35) | type RadarProps = ComponentProps<typeof Radar>;
  type PolarGridProps (line 36) | type PolarGridProps = ComponentProps<typeof PolarGrid>;
  type RadarVariant (line 38) | type RadarVariant = "filled" | "lines";
  type NumericDataKeys (line 41) | type NumericDataKeys<T> = {
  type EvilRadarChartProps (line 45) | type EvilRadarChartProps<
  type EvilRadarChartClickable (line 89) | type EvilRadarChartClickable = {
  type EvilRadarChartNotClickable (line 94) | type EvilRadarChartNotClickable = {
  type EvilRadarChartPropsWithCallback (line 99) | type EvilRadarChartPropsWithCallback<
  function EvilRadarChart (line 104) | function EvilRadarChart<
  function generateLoadingData (line 316) | function generateLoadingData(dataKey: string) {
  function useLoadingData (line 324) | function useLoadingData(isLoading: boolean, dataKey: string) {

FILE: apps/web/src/components/evilcharts/charts/radial-chart.tsx
  constant LOADING_BARS (line 27) | const LOADING_BARS = 5;
  constant LOADING_ANIMATION_DURATION (line 28) | const LOADING_ANIMATION_DURATION = 1500;
  constant DEFAULT_INNER_RADIUS (line 31) | const DEFAULT_INNER_RADIUS = "30%";
  constant DEFAULT_OUTER_RADIUS (line 32) | const DEFAULT_OUTER_RADIUS = "100%";
  constant DEFAULT_CORNER_RADIUS (line 33) | const DEFAULT_CORNER_RADIUS = 5;
  constant DEFAULT_BAR_SIZE (line 34) | const DEFAULT_BAR_SIZE = 14;
  type ChartProps (line 36) | type ChartProps = ComponentProps<typeof RadialBarChart>;
  type RadialBarProps (line 37) | type RadialBarProps = ComponentProps<typeof RadialBar>;
  type RadialVariant (line 39) | type RadialVariant = "full" | "semi";
  type EvilRadialChartProps (line 41) | type EvilRadialChartProps<TData extends Record<string, unknown>> = {
  type EvilRadialChartClickable (line 79) | type EvilRadialChartClickable = {
  type EvilRadialChartNotClickable (line 84) | type EvilRadialChartNotClickable = {
  type EvilRadialChartPropsWithCallback (line 89) | type EvilRadialChartPropsWithCallback<TData extends Record<string, unkno...
  function EvilRadialChart (line 92) | function EvilRadialChart<TData extends Record<string, unknown>>({
  function getVariantConfig (line 270) | function getVariantConfig(variant: RadialVariant) {
  function generateLoadingData (line 291) | function generateLoadingData() {
  function useLoadingData (line 299) | function useLoadingData(isLoading: boolean) {

FILE: apps/web/src/components/evilcharts/ui/background.tsx
  type BackgroundVariant (line 12) | type BackgroundVariant =
  type PatternProps (line 27) | type PatternProps = { id: string };
  constant PATTERN_MAP (line 184) | const PATTERN_MAP: Record<BackgroundVariant, React.FC<PatternProps>> = {
  type ChartBackgroundProps (line 202) | interface ChartBackgroundProps {
  function ChartBackground (line 206) | function ChartBackground({ variant }: ChartBackgroundProps) {

FILE: apps/web/src/components/evilcharts/ui/chart.tsx
  constant THEMES (line 9) | const THEMES = { light: "", dark: ".dark" } as const;
  type ThemeKey (line 11) | type ThemeKey = keyof typeof THEMES;
  type ThemeColorsBase (line 14) | type ThemeColorsBase = {
  type AtLeastOneThemeColor (line 19) | type AtLeastOneThemeColor = {
  constant VALID_THEME_KEYS (line 23) | const VALID_THEME_KEYS = Object.keys(THEMES) as ThemeKey[];
  function validateChartConfigColors (line 26) | function validateChartConfigColors(config: ChartConfig): void {
  type ChartConfig (line 42) | type ChartConfig = Record<
  type ChartContextProps (line 51) | interface ChartContextProps {
  function useChart (line 57) | function useChart() {
  type ChartContainerProps (line 67) | interface ChartContainerProps
  function ChartContainer (line 91) | function ChartContainer({
  function LoadingIndicator (line 133) | function LoadingIndicator({ isLoading }: { isLoading: boolean }) {
  function distributeColors (line 151) | function distributeColors(colorsArray: string[], maxCount: number): stri...
  function getPayloadConfigFromPayload (line 211) | function getPayloadConfigFromPayload(config: ChartConfig, payload: unkno...
  function axisValueToPercentFormatter (line 237) | function axisValueToPercentFormatter(value: number) {
  function getColorsCount (line 242) | function getColorsCount(config: ChartConfig[string]): number {

FILE: apps/web/src/components/evilcharts/ui/dot.tsx
  type DotVariant (line 5) | type DotVariant = "default" | "border" | "colored-border";
  type ChartDotProps (line 7) | type ChartDotProps = {
  type DotVariantProps (line 68) | type DotVariantProps = {

FILE: apps/web/src/components/evilcharts/ui/evil-brush.tsx
  type EvilBrushVariant (line 14) | type EvilBrushVariant = "line" | "area" | "bar";
  type CurveType (line 15) | type CurveType = ComponentProps<typeof Area>["type"];
  type EvilBrushRange (line 17) | interface EvilBrushRange {
  type EvilBrushProps (line 22) | interface EvilBrushProps {
  constant SPRING_CONFIG (line 74) | const SPRING_CONFIG = { stiffness: 300, damping: 35, mass: 0.8 };
  type DragType (line 81) | type DragType = "left" | "right" | "middle";
  type DragState (line 83) | interface DragState {
  function useBrushDrag (line 89) | function useBrushDrag({
  function EvilBrush (line 174) | function EvilBrush({
  function BrushHandle (line 409) | function BrushHandle({
  function MiniChart (line 465) | function MiniChart({
  function useEvilBrush (line 644) | function useEvilBrush<TData extends Record<string, unknown>>({

FILE: apps/web/src/components/evilcharts/ui/legend.tsx
  type ChartLegendVariant (line 11) | type ChartLegendVariant =
  function ChartLegendContent (line 20) | function ChartLegendContent({
  function LegendIndicator (line 105) | function LegendIndicator({
  function getLegendFillStyle (line 147) | function getLegendFillStyle(dataKey: string, colorsCount: number): React...
  function getLegendOutlineStyle (line 166) | function getLegendOutlineStyle(dataKey: string, colorsCount: number): Re...

FILE: apps/web/src/components/evilcharts/ui/tooltip.tsx
  type TooltipRoundness (line 12) | type TooltipRoundness = "sm" | "md" | "lg" | "xl";
  type TooltipVariant (line 13) | type TooltipVariant = "default" | "frosted-glass";
  function ChartTooltipContent (line 27) | function ChartTooltipContent({
  function getIndicatorColorStyle (line 176) | function getIndicatorColorStyle(dataKey: string, colorsCount: number): R...

FILE: apps/web/src/components/providers.tsx
  function Providers (line 10) | function Providers({ children }: { children: React.ReactNode }) {

FILE: apps/web/src/components/special-sponsor-banner.tsx
  function SpecialSponsorBanner (line 9) | async function SpecialSponsorBanner() {

FILE: apps/web/src/components/theme-toggle.tsx
  function ThemeToggle (line 10) | function ThemeToggle({ className }: { className?: string }) {

FILE: apps/web/src/components/ui/accordion.tsx
  function Accordion (line 8) | function Accordion({ className, ...props }: AccordionPrimitive.Root.Prop...
  function AccordionItem (line 18) | function AccordionItem({ className, ...props }: AccordionPrimitive.Item....
  function AccordionTrigger (line 28) | function AccordionTrigger({ className, children, ...props }: AccordionPr...
  function AccordionContent (line 53) | function AccordionContent({ className, children, ...props }: AccordionPr...

FILE: apps/web/src/components/ui/button.tsx
  function Button (line 41) | function Button({

FILE: apps/web/src/components/ui/card.tsx
  function Card (line 5) | function Card({
  function CardHeader (line 23) | function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
  function CardTitle (line 36) | function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
  function CardDescription (line 46) | function CardDescription({ className, ...props }: React.ComponentProps<"...
  function CardAction (line 56) | function CardAction({ className, ...props }: React.ComponentProps<"div">) {
  function CardContent (line 66) | function CardContent({ className, ...props }: React.ComponentProps<"div"...
  function CardFooter (line 76) | function CardFooter({ className, ...props }: React.ComponentProps<"div">) {

FILE: apps/web/src/components/ui/dialog.tsx
  function Dialog (line 10) | function Dialog({ ...props }: DialogPrimitive.Root.Props) {
  function DialogTrigger (line 14) | function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
  function DialogPortal (line 18) | function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
  function DialogClose (line 22) | function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
  function DialogOverlay (line 26) | function DialogOverlay({ className, ...props }: DialogPrimitive.Backdrop...
  function DialogContent (line 39) | function DialogContent({
  function DialogHeader (line 73) | function DialogHeader({ className, ...props }: React.ComponentProps<"div...
  function DialogFooter (line 83) | function DialogFooter({
  function DialogTitle (line 105) | function DialogTitle({ className, ...props }: DialogPrimitive.Title.Prop...
  function DialogDescription (line 115) | function DialogDescription({ className, ...props }: DialogPrimitive.Desc...

FILE: apps/web/src/components/ui/dropdown-menu.tsx
  function DropdownMenu (line 9) | function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
  function DropdownMenuPortal (line 13) | function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
  function DropdownMenuTrigger (line 17) | function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
  function DropdownMenuContent (line 21) | function DropdownMenuContent({
  function DropdownMenuGroup (line 52) | function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
  function DropdownMenuLabel (line 56) | function DropdownMenuLabel({
  function DropdownMenuItem (line 73) | function DropdownMenuItem({
  function DropdownMenuSub (line 96) | function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
  function DropdownMenuSubTrigger (line 100) | function DropdownMenuSubTrigger({
  function DropdownMenuSubContent (line 124) | function DropdownMenuSubContent({
  function DropdownMenuCheckboxItem (line 148) | function DropdownMenuCheckboxItem({
  function DropdownMenuRadioGroup (line 177) | function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.P...
  function DropdownMenuRadioItem (line 181) | function DropdownMenuRadioItem({ className, children, ...props }: MenuPr...
  function DropdownMenuSeparator (line 204) | function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Se...
  function DropdownMenuShortcut (line 214) | function DropdownMenuShortcut({ className, ...props }: React.ComponentPr...

FILE: apps/web/src/components/ui/file-tree.tsx
  type TreeViewElement (line 11) | type TreeViewElement = {
  type TreeContextProps (line 18) | type TreeContextProps = {
  type Direction (line 40) | type Direction = "rtl" | "ltr" | undefined;
  type TreeViewProps (line 42) | type TreeViewProps = {
  function Tree (line 52) | function Tree({
  function TreeIndicator (line 143) | function TreeIndicator({ className, ...props }: React.HTMLAttributes<HTM...
  type FolderProps (line 160) | type FolderProps = {
  function Folder (line 168) | function Folder({
  type FileProps (line 219) | type FileProps = {
  function File (line 228) | function File({
  type CollapseButtonProps (line 264) | type CollapseButtonProps = {
  function CollapseButton (line 270) | function CollapseButton({ elements, expandAll = false, children, ...prop...

FILE: apps/web/src/components/ui/hover-card.tsx
  function HoverCard (line 7) | function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {
  function HoverCardTrigger (line 11) | function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Pro...
  function HoverCardContent (line 15) | function HoverCardContent({

FILE: apps/web/src/components/ui/input.tsx
  function Input (line 6) | function Input({ className, type, ...props }: React.ComponentProps<"inpu...

FILE: apps/web/src/components/ui/kibo-ui/code-block/index.tsx
  type CodeBlockData (line 281) | type CodeBlockData = {
  type CodeBlockContextType (line 287) | type CodeBlockContextType = {
  type CodeBlockProps (line 299) | type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
  type CodeBlockHeaderProps (line 333) | type CodeBlockHeaderProps = HTMLAttributes<HTMLDivElement>;
  type CodeBlockFilesProps (line 339) | type CodeBlockFilesProps = Omit<HTMLAttributes<HTMLDivElement>, "childre...
  type CodeBlockFilenameProps (line 353) | type CodeBlockFilenameProps = HTMLAttributes<HTMLDivElement> & {
  type CodeBlockSelectProps (line 386) | type CodeBlockSelectProps = ComponentProps<typeof Select>;
  type CodeBlockSelectTriggerProps (line 406) | type CodeBlockSelectTriggerProps = ComponentProps<typeof SelectTrigger>;
  type CodeBlockSelectValueProps (line 415) | type CodeBlockSelectValueProps = ComponentProps<typeof SelectValue>;
  type CodeBlockSelectContentProps (line 421) | type CodeBlockSelectContentProps = Omit<ComponentProps<typeof SelectCont...
  type CodeBlockSelectItemProps (line 431) | type CodeBlockSelectItemProps = ComponentProps<typeof SelectItem>;
  type CodeBlockCopyButtonProps (line 437) | type CodeBlockCopyButtonProps = Omit<ComponentProps<typeof Button>, "onC...
  type CodeBlockFallbackProps (line 483) | type CodeBlockFallbackProps = HTMLAttributes<HTMLDivElement> & {
  type CodeBlockBodyProps (line 504) | type CodeBlockBodyProps = Omit<HTMLAttributes<HTMLDivElement>, "children...
  type CodeBlockItemProps (line 514) | type CodeBlockItemProps = HTMLAttributes<HTMLDivElement> & {
  type CodeBlockContentProps (line 551) | type CodeBlockContentProps = HTMLAttributes<HTMLDivElement> & {

FILE: apps/web/src/components/ui/kibo-ui/code-block/server.tsx
  type CodeBlockContentProps (line 11) | type CodeBlockContentProps = HTMLAttributes<HTMLDivElement> & {

FILE: apps/web/src/components/ui/kibo-ui/qr-code/index.tsx
  type QRCodeProps (line 9) | type QRCodeProps = HTMLAttributes<HTMLDivElement> & {

FILE: apps/web/src/components/ui/kibo-ui/qr-code/server.tsx
  type QRCodeProps (line 6) | type QRCodeProps = HTMLAttributes<HTMLDivElement> & {

FILE: apps/web/src/components/ui/scroll-area.tsx
  function ScrollArea (line 8) | function ScrollArea({ className, children, ...props }: ScrollAreaPrimiti...
  function ScrollBar (line 28) | function ScrollBar({

FILE: apps/web/src/components/ui/select.tsx
  function SelectGroup (line 11) | function SelectGroup({ className, ...props }: SelectPrimitive.Group.Prop...
  function SelectValue (line 21) | function SelectValue({ className, ...props }: SelectPrimitive.Value.Prop...
  function SelectTrigger (line 31) | function SelectTrigger({
  function SelectContent (line 57) | function SelectContent({
  function SelectLabel (line 98) | function SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel...
  function SelectItem (line 108) | function SelectItem({ className, children, ...props }: SelectPrimitive.I...
  function SelectSeparator (line 132) | function SelectSeparator({ className, ...props }: SelectPrimitive.Separa...
  function SelectScrollUpButton (line 142) | function SelectScrollUpButton({
  function SelectScrollDownButton (line 160) | function SelectScrollDownButton({

FILE: apps/web/src/components/ui/share-dialog.tsx
  type ShareDialogProps (line 25) | interface ShareDialogProps {
  function ShareDialog (line 31) | function ShareDialog({ children, stackUrl, stackState }: ShareDialogProp...

FILE: apps/web/src/components/ui/skeleton.tsx
  function Skeleton (line 3) | function Skeleton({ className, ...props }: React.ComponentProps<"div">) {

FILE: apps/web/src/components/ui/spinner.tsx
  function Spinner (line 5) | function Spinner({ className, ...props }: React.ComponentProps<"svg">) {

FILE: apps/web/src/components/ui/switch.tsx
  function Switch (line 7) | function Switch({

FILE: apps/web/src/components/ui/tabs.tsx
  function Tabs (line 8) | function Tabs({ className, orientation = "horizontal", ...props }: TabsP...
  function TabsList (line 34) | function TabsList({
  function TabsTrigger (line 49) | function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
  function TabsContent (line 65) | function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {

FILE: apps/web/src/components/ui/tech-badge.tsx
  type TechBadgeProps (line 8) | interface TechBadgeProps {
  function TechIcon (line 50) | function TechIcon({ icon, name, className }: { icon: string; name: strin...
  function TechBadge (line 87) | function TechBadge({ icon, name, category, className }: TechBadgeProps) {

FILE: apps/web/src/components/ui/toggle.tsx
  function Toggle (line 29) | function Toggle({

FILE: apps/web/src/components/ui/tooltip.tsx
  function TooltipProvider (line 7) | function TooltipProvider({ delay = 0, ...props }: TooltipPrimitive.Provi...
  function Tooltip (line 11) | function Tooltip({ delay, ...props }: TooltipPrimitive.Root.Props & { de...
  function TooltipTrigger (line 19) | function TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {
  function TooltipContent (line 23) | function TooltipContent({

FILE: apps/web/src/lib/constant.ts
  constant ICON_BASE_URL (line 3) | const ICON_BASE_URL = "https://r2.better-t-stack.dev/icons";
  constant TECH_OPTIONS (line 5) | const TECH_OPTIONS: Record<
  constant PRESET_TEMPLATES (line 692) | const PRESET_TEMPLATES = [
  type StackState (line 799) | type StackState = {
  constant DEFAULT_STACK (line 821) | const DEFAULT_STACK: StackState = {

FILE: apps/web/src/lib/get-llm-text.ts
  function getLLMText (line 5) | async function getLLMText(page: InferPageType<typeof source>) {

FILE: apps/web/src/lib/sanitize-stack-addons.ts
  function sanitizeSingleSelection (line 8) | function sanitizeSingleSelection(
  function sanitizeMultiSelection (line 21) | function sanitizeMultiSelection(
  function resolveMonorepoAddonConflicts (line 38) | function resolveMonorepoAddonConflicts(addons: readonly string[]): strin...
  function sanitizeAddons (line 60) | function sanitizeAddons(addons: readonly string[] | null | undefined): s...
  function sanitizeExamples (line 65) | function sanitizeExamples(examples: readonly string[] | null | undefined...
  function sanitizeWebFrontends (line 69) | function sanitizeWebFrontends(webFrontend: readonly string[] | null | un...
  function sanitizeNativeFrontends (line 73) | function sanitizeNativeFrontends(
  function sanitizeStackState (line 83) | function sanitizeStackState(stack: StackState): StackState {
  function sanitizeStackAddons (line 93) | function sanitizeStackAddons(stack: StackState): StackState {

FILE: apps/web/src/lib/search-config.ts
  type CustomSearchItem (line 1) | interface CustomSearchItem {
  function filterCustomItems (line 53) | function filterCustomItems(

FILE: apps/web/src/lib/source.ts
  function getPageImage (line 9) | function getPageImage(page: InferPageType<typeof source>) {

FILE: apps/web/src/lib/sponsor-utils.ts
  constant SPECIAL_SPONSOR_THRESHOLD (line 3) | const SPECIAL_SPONSOR_THRESHOLD = 100;

FILE: apps/web/src/lib/sponsors.ts
  constant SPONSORS_URL (line 3) | const SPONSORS_URL = "https://sponsors.better-t-stack.dev/sponsors.json";
  function fetchSponsors (line 5) | async function fetchSponsors() {

FILE: apps/web/src/lib/stack-url-state.client.ts
  function useStackState (line 64) | function useStackState() {

FILE: apps/web/src/lib/stack-url-state.ts
  function loadStackParams (line 76) | async function loadStackParams(
  type LoadedStackState (line 83) | type LoadedStackState = Awaited<ReturnType<typeof loadStackParams>>;

FILE: apps/web/src/lib/stack-utils.ts
  constant CATEGORY_ORDER (line 4) | const CATEGORY_ORDER: Array<keyof typeof TECH_OPTIONS> = [
  function generateStackSummary (line 37) | function generateStackSummary(stack: StackState) {
  function getDesktopBuildNote (line 63) | function getDesktopBuildNote(stack: Pick<StackState, "addons" | "webFron...
  function generateStackCommand (line 89) | function generateStackCommand(stack: StackState) {
  function generateStackUrlFromState (line 181) | function generateStackUrlFromState(stack: StackState, baseUrl?: string) {
  function generateStackSharingUrl (line 196) | function generateStackSharingUrl(stack: StackState, baseUrl?: string) {

FILE: apps/web/src/lib/types.ts
  type TechCategory (line 2) | type TechCategory =
  type TechEdge (line 21) | type TechEdge = {
  type Sponsor (line 29) | type Sponsor = {
  type SponsorsData (line 42) | type SponsorsData = {

FILE: apps/web/src/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: apps/web/test/stack-builder-compatibility.test.ts
  function createStack (line 13) | function createStack(overrides: Partial<StackState> = {}): StackState {

FILE: packages/backend/convex/_generated/dataModel.d.ts
  type TableNames (line 23) | type TableNames = TableNamesInDataModel<DataModel>;
  type Doc (line 30) | type Doc<TableName extends TableNames> = DocumentByName<
  type Id (line 48) | type Id<TableName extends TableNames | SystemTableNames> =
  type DataModel (line 60) | type DataModel = DataModelFromSchemaDefinition<typeof schema>;

FILE: packages/backend/convex/_generated/server.d.ts
  type QueryCtx (line 107) | type QueryCtx = GenericQueryCtx<DataModel>;
  type MutationCtx (line 115) | type MutationCtx = GenericMutationCtx<DataModel>;
  type ActionCtx (line 123) | type ActionCtx = GenericActionCtx<DataModel>;
  type DatabaseReader (line 132) | type DatabaseReader = GenericDatabaseReader<DataModel>;
  type DatabaseWriter (line 143) | type DatabaseWriter = GenericDatabaseWriter<DataModel>;

FILE: packages/backend/convex/analytics.ts
  constant MAX_DAILY_STATS_WINDOW (line 6) | const MAX_DAILY_STATS_WINDOW = 366;
  function incrementKey (line 8) | function incrementKey(
  function incrementKeys (line 16) | function incrementKeys(
  function incrementBool (line 28) | function incrementBool(
  function getMajorVersion (line 37) | function getMajorVersion(version: string | undefined): string | undefined {

FILE: packages/backend/convex/analytics_date_utils.ts
  type DailyCount (line 1) | type DailyCount = {
  constant MILLISECONDS_PER_DAY (line 6) | const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
  function parseUtcDate (line 8) | function parseUtcDate(date: string): number | null {
  function formatUtcDate (line 13) | function formatUtcDate(timestamp: number): string {
  function buildDailyWindow (line 17) | function buildDailyWindow(

FILE: packages/template-generator/scripts/generate-templates.ts
  constant TEMPLATES_DIR (line 11) | const TEMPLATES_DIR = path.join(__dirname, "../templates");
  constant OUTPUT_FILE (line 12) | const OUTPUT_FILE = path.join(__dirname, "../src/templates.generated.ts");
  constant BINARY_OUTPUT_DIR (line 13) | const BINARY_OUTPUT_DIR = path.join(__dirname, "../templates-binary");
  function generateTemplates (line 15) | async function generateTemplates() {
  function copyBinaryFiles (line 66) | async function copyBinaryFiles(binaryFiles: string[]) {

FILE: packages/template-generator/src/bts-config.ts
  constant BTS_CONFIG_FILE (line 5) | const BTS_CONFIG_FILE = "bts.jsonc";
  function writeBtsConfigToVfs (line 11) | function writeBtsConfigToVfs(

FILE: packages/template-generator/src/core/template-processor.ts
  function processTemplateString (line 11) | function processTemplateString(content: string, context: ProjectConfig):...
  function isBinaryFile (line 15) | function isBinaryFile(filePath: string): boolean {
  function transformFilename (line 19) | function transformFilename(filename: string): string {
  function processFileContent (line 29) | function processFileContent(

FILE: packages/template-generator/src/core/template-reader.ts
  function getTemplatesRoot (line 11) | function getTemplatesRoot(): string {
  function getBinaryTemplatesRoot (line 25) | function getBinaryTemplatesRoot(): string {
  function loadTemplates (line 39) | async function loadTemplates(prefix?: string): Promise<Map<string, strin...
  function loadTemplate (line 66) | function loadTemplate(relativePath: string): string | undefined {
  function listTemplates (line 73) | async function listTemplates(prefix?: string): Promise<string[]> {

FILE: packages/template-generator/src/core/virtual-fs.ts
  class VirtualFileSystem (line 8) | class VirtualFileSystem {
    method constructor (line 13) | constructor() {
    method writeFile (line 19) | writeFile(filePath: string, content: string, sourcePath?: string): void {
    method readFile (line 31) | readFile(filePath: string): string | undefined {
    method exists (line 39) | exists(path: string): boolean {
    method fileExists (line 48) | fileExists(filePath: string): boolean {
    method directoryExists (line 56) | directoryExists(dirPath: string): boolean {
    method mkdir (line 64) | mkdir(dirPath: string): void {
    method deleteFile (line 68) | deleteFile(filePath: string): boolean {
    method listDir (line 77) | listDir(dirPath: string): string[] {
    method readJson (line 85) | readJson<T = unknown>(filePath: string): T | undefined {
    method writeJson (line 95) | writeJson(filePath: string, data: unknown, spaces = 2): void {
    method getAllFiles (line 99) | getAllFiles(): string[] {
    method getAllDirectories (line 105) | getAllDirectories(): string[] {
    method getFileCount (line 111) | getFileCount(): number {
    method getDirectoryCount (line 115) | getDirectoryCount(): number {
    method toTree (line 119) | toTree(rootName = "project"): VirtualDirectory {
    method clear (line 126) | clear(): void {
    method getVolume (line 133) | getVolume() {
    method getFs (line 136) | getFs() {
    method walkDir (line 140) | private walkDir(dir: string, results: string[], filesOnly: boolean): v...
    method buildTree (line 155) | private buildTree(dir: string, parent: VirtualDirectory): void {
    method sortChildren (line 188) | private sortChildren(node: VirtualDirectory): void {
    method normalizePath (line 199) | private normalizePath(p: string): string {

FILE: packages/template-generator/src/fs-writer.ts
  constant BINARY_FILE_MARKER (line 9) | const BINARY_FILE_MARKER = "[Binary file]";
  class FileWriteError (line 14) | class FileWriteError extends TaggedError("FileWriteError")<{
  function writeTree (line 24) | async function writeTree(
  function writeNodeInternal (line 44) | async function writeNodeInternal(
  function writeSelected (line 73) | async function writeSelected(
  function writeSelectedNodeInternal (line 94) | async function writeSelectedNodeInternal(
  function copyBinaryFile (line 122) | async function copyBinaryFile(templatePath: string, destPath: string): P...

FILE: packages/template-generator/src/generator.ts
  function generate (line 50) | async function generate(

FILE: packages/template-generator/src/post-process/catalogs.ts
  type PackageJson (line 11) | type PackageJson = {
  type CatalogEntry (line 21) | type CatalogEntry = {
  type PackageInfo (line 26) | type PackageInfo = {
  constant PACKAGE_PATHS (line 32) | const PACKAGE_PATHS = [
  function processCatalogs (line 53) | function processCatalogs(vfs: VirtualFileSystem, config: ProjectConfig):...
  function findDuplicateDependencies (line 84) | function findDuplicateDependencies(
  function setupBunCatalogs (line 124) | function setupBunCatalogs(vfs: VirtualFileSystem, catalog: Record<string...
  function setupPnpmCatalogs (line 150) | function setupPnpmCatalogs(vfs: VirtualFileSystem, catalog: Record<strin...
  function updatePackageJsonsWithCatalogs (line 176) | function updatePackageJsonsWithCatalogs(

FILE: packages/template-generator/src/post-process/index.ts
  function processPostGeneration (line 15) | function processPostGeneration(vfs: VirtualFileSystem, config: ProjectCo...

FILE: packages/template-generator/src/post-process/package-configs.ts
  type PackageJson (line 11) | type PackageJson = {
  type PackageManagerConfig (line 22) | type PackageManagerConfig = {
  type DesktopWebScript (line 29) | type DesktopWebScript = "build" | "dev" | "generate";
  function processPackageConfigs (line 34) | function processPackageConfigs(vfs: VirtualFileSystem, config: ProjectCo...
  function updateRootPackageJson (line 52) | function updateRootPackageJson(vfs: VirtualFileSystem, config: ProjectCo...
  function getPackageManagerConfig (line 189) | function getPackageManagerConfig(
  function updateDesktopPackageJson (line 237) | function updateDesktopPackageJson(vfs: VirtualFileSystem, config: Projec...
  function getDesktopWebCommand (line 268) | function getDesktopWebCommand(
  function getLocalRunCommand (line 292) | function getLocalRunCommand(packageManager: ProjectConfig["packageManage...
  function updateDbPackageJson (line 304) | function updateDbPackageJson(vfs: VirtualFileSystem, config: ProjectConf...
  function updateAuthPackageJson (line 348) | function updateAuthPackageJson(vfs: VirtualFileSystem, config: ProjectCo...
  function updateApiPackageJson (line 356) | function updateApiPackageJson(vfs: VirtualFileSystem, config: ProjectCon...
  function updateConfigPackageJson (line 364) | function updateConfigPackageJson(vfs: VirtualFileSystem, config: Project...
  function updateEnvPackageJson (line 372) | function updateEnvPackageJson(vfs: VirtualFileSystem, config: ProjectCon...
  function updateUiPackageJson (line 404) | function updateUiPackageJson(vfs: VirtualFileSystem, config: ProjectConf...
  function updateInfraPackageJson (line 412) | function updateInfraPackageJson(vfs: VirtualFileSystem, config: ProjectC...
  function updateConvexPackageJson (line 420) | function updateConvexPackageJson(vfs: VirtualFileSystem, config: Project...
  function renameDevScriptsForAlchemy (line 429) | function renameDevScriptsForAlchemy(vfs: VirtualFileSystem, config: Proj...

FILE: packages/template-generator/src/processors/addons-deps.ts
  type PackageJson (line 6) | type PackageJson = {
  function processAddonsDeps (line 15) | function processAddonsDeps(vfs: VirtualFileSystem, config: ProjectConfig...

FILE: packages/template-generator/src/processors/alchemy-plugins.ts
  function processAlchemyPlugins (line 6) | function processAlchemyPlugins(vfs: VirtualFileSystem, config: ProjectCo...
  function processNextAlchemy (line 30) | function processNextAlchemy(vfs: VirtualFileSystem) {
  function processNuxtAlchemy (line 54) | function processNuxtAlchemy(vfs: VirtualFileSystem) {
  function processSvelteAlchemy (line 240) | function processSvelteAlchemy(vfs: VirtualFileSystem) {
  function processTanStackStartAlchemy (line 335) | function processTanStackStartAlchemy(vfs: VirtualFileSystem) {
  function processAstroAlchemy (line 473) | function processAstroAlchemy(vfs: VirtualFileSystem) {

FILE: packages/template-generator/src/processors/api-deps.ts
  type FrontendType (line 6) | type FrontendType = {
  function getFrontendType (line 15) | function getFrontendType(frontend: Frontend[]): FrontendType {
  function processApiDeps (line 30) | function processApiDeps(vfs: VirtualFileSystem, config: ProjectConfig): ...
  function addApiPackageDeps (line 49) | function addApiPackageDeps(
  function addServerDeps (line 99) | function addServerDeps(vfs: VirtualFileSystem, api: API, backend: Backen...
  function addSelfBackendWebDeps (line 120) | function addSelfBackendWebDeps(
  function addWebClientDeps (line 147) | function addWebClientDeps(
  function addNativeDeps (line 222) | function addNativeDeps(vfs: VirtualFileSystem, api: API, backend: Backen...
  function addQueryDeps (line 243) | function addQueryDeps(vfs: VirtualFileSystem, frontend: Frontend[], back...
  function addConvexDeps (line 275) | function addConvexDeps(

FILE: packages/template-generator/src/processors/auth-deps.ts
  constant CONVEX_BETTER_AUTH_VERSION (line 6) | const CONVEX_BETTER_AUTH_VERSION = "1.6.9";
  function processAuthDeps (line 8) | function processAuthDeps(vfs: VirtualFileSystem, config: ProjectConfig):...
  function processConvexAuthDeps (line 19) | function processConvexAuthDeps(vfs: VirtualFileSystem, config: ProjectCo...
  function processStandardAuthDeps (line 126) | function processStandardAuthDeps(vfs: VirtualFileSystem, config: Project...

FILE: packages/template-generator/src/processors/auth-plugins.ts
  function processAuthPlugins (line 6) | function processAuthPlugins(vfs: VirtualFileSystem, config: ProjectConfi...

FILE: packages/template-generator/src/processors/backend-deps.ts
  function processBackendDeps (line 6) | function processBackendDeps(vfs: VirtualFileSystem, config: ProjectConfi...

FILE: packages/template-generator/src/processors/db-deps.ts
  function processDatabaseDeps (line 6) | function processDatabaseDeps(vfs: VirtualFileSystem, config: ProjectConf...
  function processPrismaDeps (line 26) | function processPrismaDeps(
  function processDrizzleDeps (line 85) | function processDrizzleDeps(

FILE: packages/template-generator/src/processors/deploy-deps.ts
  function processDeployDeps (line 6) | function processDeployDeps(vfs: VirtualFileSystem, config: ProjectConfig...

FILE: packages/template-generator/src/processors/env-deps.ts
  function processEnvDeps (line 6) | function processEnvDeps(vfs: VirtualFileSystem, config: ProjectConfig): ...

FILE: packages/template-generator/src/processors/env-vars.ts
  type EnvVariable (line 5) | interface EnvVariable {
  type AddEnvVariablesOptions (line 12) | type AddEnvVariablesOptions = {
  function generateRandomString (line 16) | function generateRandomString(length: number, charset: string) {
  function generateAuthSecret (line 40) | function generateAuthSecret() {
  function getClientServerVar (line 44) | function getClientServerVar(frontend: string[], backend: ProjectConfig["...
  function getConvexVar (line 65) | function getConvexVar(frontend: string[]) {
  function escapeRegExp (line 77) | function escapeRegExp(value: string): string {
  function addEnvVariablesToContent (line 81) | function addEnvVariablesToContent(
  function writeEnvFile (line 120) | function writeEnvFile(
  function buildClientVars (line 134) | function buildClientVars(
  function buildNativeVars (line 205) | function buildNativeVars(
  function buildConvexBackendVars (line 257) | function buildConvexBackendVars(
  function buildConvexCommentBlocks (line 334) | function buildConvexCommentBlocks(
  function buildServerVars (line 379) | function buildServerVars(
  function processEnvVariables (line 488) | function processEnvVariables(vfs: VirtualFileSystem, config: ProjectConf...

FILE: packages/template-generator/src/processors/examples-deps.ts
  function processExamplesDeps (line 6) | function processExamplesDeps(vfs: VirtualFileSystem, config: ProjectConf...
  function setupTodoDependencies (line 22) | function setupTodoDependencies(vfs: VirtualFileSystem, config: ProjectCo...
  function setupAIDependencies (line 38) | function setupAIDependencies(vfs: VirtualFileSystem, config: ProjectConf...

FILE: packages/template-generator/src/processors/frontend-deps.ts
  function processFrontendDeps (line 6) | function processFrontendDeps(vfs: VirtualFileSystem, config: ProjectConf...

FILE: packages/template-generator/src/processors/index.ts
  function processDependencies (line 25) | function processDependencies(vfs: VirtualFileSystem, config: ProjectConf...

FILE: packages/template-generator/src/processors/infra-deps.ts
  function processInfraDeps (line 6) | function processInfraDeps(vfs: VirtualFileSystem, config: ProjectConfig)...

FILE: packages/template-generator/src/processors/nx-generator.ts
  type NxTargetDefaults (line 11) | type NxTargetDefaults = {
  type NxConfig (line 17) | type NxConfig = {
  function processNxConfig (line 23) | function processNxConfig(vfs: VirtualFileSystem, config: ProjectConfig):...
  function generateNxConfig (line 30) | function generateNxConfig(config: ProjectConfig): NxConfig {
  function getConvexTargets (line 73) | function getConvexTargets(): Record<string, NxTargetDefaults> {
  function getDatabaseTargets (line 81) | function getDatabaseTargets(dbSupport: DbScriptSupport): Record<string, ...
  function getDockerTargets (line 103) | function getDockerTargets(): Record<string, NxTargetDefaults> {
  function getSqliteLocalTarget (line 112) | function getSqliteLocalTarget(): Record<string, NxTargetDefaults> {
  function getDeployTargets (line 118) | function getDeployTargets(): Record<string, NxTargetDefaults> {

FILE: packages/template-generator/src/processors/payments-deps.ts
  function processPaymentsDeps (line 6) | function processPaymentsDeps(vfs: VirtualFileSystem, config: ProjectConf...

FILE: packages/template-generator/src/processors/pwa-plugins.ts
  function processPwaPlugins (line 6) | function processPwaPlugins(vfs: VirtualFileSystem, config: ProjectConfig...

FILE: packages/template-generator/src/processors/readme-generator.ts
  function getDesktopStaticBuildNote (line 6) | function getDesktopStaticBuildNote(frontend: ProjectConfig["frontend"]):...
  function getClerkQuickstartUrl (line 25) | function getClerkQuickstartUrl(frontend: ProjectConfig["frontend"]): str...
  function getClerkFrontendEnvLines (line 47) | function getClerkFrontendEnvLines(frontend: ProjectConfig["frontend"]): ...
  function getClerkSetupLines (line 69) | function getClerkSetupLines(
  function hasNativeFrontend (line 125) | function hasNativeFrontend(frontend: ProjectConfig["frontend"]): boolean {
  function hasWebFrontend (line 131) | function hasWebFrontend(frontend: ProjectConfig["frontend"]): boolean {
  function processReadme (line 146) | function processReadme(vfs: VirtualFileSystem, config: ProjectConfig): v...
  function generateReadmeContent (line 151) | function generateReadmeContent(options: ProjectConfig): string {
  function generateStackDescription (line 262) | function generateStackDescription(
  function generateRunningInstructions (line 302) | function generateRunningInstructions(
  function generateReactUiSection (line 333) | function generateReactUiSection(hasReactWeb: boolean, projectName: strin...
  function generateProjectStructure (line 365) | function generateProjectStructure(config: ProjectConfig): string {
  function generateFeaturesList (line 445) | function generateFeaturesList(
  function generateDatabaseSetup (line 565) | function generateDatabaseSetup(config: ProjectConfig, packageManagerRunC...
  function generateScriptsList (line 627) | function generateScriptsList(
  function generateDeploymentCommands (line 724) | function generateDeploymentCommands(
  function generateGitHooksSection (line 757) | function generateGitHooksSection(

FILE: packages/template-generator/src/processors/runtime-deps.ts
  type PackageJson (line 6) | type PackageJson = {
  function processRuntimeDeps (line 11) | function processRuntimeDeps(vfs: VirtualFileSystem, config: ProjectConfi...

FILE: packages/template-generator/src/processors/turbo-generator.ts
  type TurboTask (line 11) | interface TurboTask {
  type TurboConfig (line 19) | interface TurboConfig {
  function processTurboConfig (line 25) | function processTurboConfig(vfs: VirtualFileSystem, config: ProjectConfi...
  function generateTurboConfig (line 32) | function generateTurboConfig(config: ProjectConfig): TurboConfig {
  function getBaseTasks (line 58) | function getBaseTasks(frontend: string[]): Record<string, TurboTask> {
  function getConvexTasks (line 102) | function getConvexTasks(): Record<string, TurboTask> {
  function getDatabaseTasks (line 111) | function getDatabaseTasks(dbSupport: DbScriptSupport): Record<string, Tu...
  function getDockerTasks (line 133) | function getDockerTasks(): Record<string, TurboTask> {
  function getSqliteLocalTask (line 152) | function getSqliteLocalTask(): Record<string, TurboTask> {
  function getDeployTasks (line 160) | function getDeployTasks(): Record<string, TurboTask> {

FILE: packages/template-generator/src/processors/workspace-deps.ts
  constant NATIVE_TYPESCRIPT_VERSION (line 7) | const NATIVE_TYPESCRIPT_VERSION = "~5.9.2";
  function processWorkspaceDeps (line 9) | function processWorkspaceDeps(vfs: VirtualFileSystem, config: ProjectCon...
  function getRuntimeDevDeps (line 191) | function getRuntimeDevDeps(

FILE: packages/template-generator/src/template-handlers/addons.ts
  function processAddonTemplates (line 6) | async function processAddonTemplates(

FILE: packages/template-generator/src/template-handlers/api.ts
  function processApiTemplates (line 6) | async function processApiTemplates(

FILE: packages/template-generator/src/template-handlers/auth.ts
  function processAuthTemplates (line 6) | async function processAuthTemplates(

FILE: packages/template-generator/src/template-handlers/backend.ts
  function processBackendTemplates (line 6) | async function processBackendTemplates(

FILE: packages/template-generator/src/template-handlers/base.ts
  function processBaseTemplate (line 6) | async function processBaseTemplate(

FILE: packages/template-generator/src/template-handlers/database.ts
  function processDbTemplates (line 6) | async function processDbTemplates(

FILE: packages/template-generator/src/template-handlers/deploy.ts
  function processDeployTemplates (line 6) | async function processDeployTemplates(

FILE: packages/template-generator/src/template-handlers/examples.ts
  function processExampleTemplates (line 6) | async function processExampleTemplates(

FILE: packages/template-generator/src/template-handlers/extras.ts
  function processExtrasTemplates (line 11) | async function processExtrasTemplates(

FILE: packages/template-generator/src/template-handlers/frontend.ts
  function processFrontendTemplates (line 6) | async function processFrontendTemplates(

FILE: packages/template-generator/src/template-handlers/packages.ts
  function processConfigPackage (line 6) | async function processConfigPackage(
  function processEnvPackage (line 14) | async function processEnvPackage(
  function processUiPackage (line 100) | async function processUiPackage(

FILE: packages/template-generator/src/template-handlers/payments.ts
  function processPaymentsTemplates (line 6) | async function processPaymentsTemplates(

FILE: packages/template-generator/src/template-handlers/utils.ts
  type TemplateData (line 6) | type TemplateData = Map<string, string>;
  function hasTemplatesWithPrefix (line 8) | function hasTemplatesWithPrefix(templates: TemplateData, prefix: string)...
  function processSingleTemplate (line 16) | function processSingleTemplate(
  function processTemplatesFromPrefix (line 42) | function processTemplatesFromPrefix(

FILE: packages/template-generator/src/templates.generated.ts
  constant EMBEDDED_TEMPLATES (line 4) | const EMBEDDED_TEMPLATES: Map<string, string> = new Map([
  constant TEMPLATE_COUNT (line 30044) | const TEMPLATE_COUNT = 467;

FILE: packages/template-generator/src/types.ts
  type VirtualFile (line 4) | interface VirtualFile {
  type VirtualDirectory (line 13) | interface VirtualDirectory {
  type VirtualNode (line 20) | type VirtualNode = VirtualFile | VirtualDirectory;
  type VirtualFileTree (line 22) | interface VirtualFileTree {
  type GeneratorOptions (line 29) | interface GeneratorOptions {
  class GeneratorError (line 40) | class GeneratorError extends TaggedError("GeneratorError")<{

FILE: packages/template-generator/src/utils/add-deps.ts
  type PackageJson (line 7) | type PackageJson = {
  type AvailableDependencies (line 169) | type AvailableDependencies = keyof typeof dependencyVersionMap;
  type AddDepsOptions (line 171) | type AddDepsOptions = {
  function addPackageDependency (line 183) | function addPackageDependency(options: AddDepsOptions): void {

FILE: packages/template-generator/src/utils/db-scripts.ts
  type DbScriptSupport (line 3) | type DbScriptSupport = {
  function getDbScriptSupport (line 12) | function getDbScriptSupport(config: ProjectConfig): DbScriptSupport {

FILE: packages/template-generator/src/utils/reproducible-command.ts
  function normalizeMultiValues (line 3) | function normalizeMultiValues(values: string[] | undefined): string[] {
  function formatMultiFlag (line 9) | function formatMultiFlag(flag: string, values: string[]): string {
  function getBaseCommand (line 16) | function getBaseCommand(packageManager: ProjectConfig["packageManager"])...
  function generateReproducibleCommand (line 28) | function generateReproducibleCommand(config: ProjectConfig): string {

FILE: packages/template-generator/templates/frontend/solid/src/components/loader.tsx
  function Loader (line 3) | function Loader() {

FILE: packages/types/src/json-schema.ts
  function getDatabaseJsonSchema (line 30) | function getDatabaseJsonSchema() {
  function getORMJsonSchema (line 34) | function getORMJsonSchema() {
  function getBackendJsonSchema (line 38) | function getBackendJsonSchema() {
  function getRuntimeJsonSchema (line 42) | function getRuntimeJsonSchema() {
  function getFrontendJsonSchema (line 46) | function getFrontendJsonSchema() {
  function getAddonsJsonSchema (line 50) | function getAddonsJsonSchema() {
  function getExamplesJsonSchema (line 54) | function getExamplesJsonSchema() {
  function getPackageManagerJsonSchema (line 58) | function getPackageManagerJsonSchema() {
  function getDatabaseSetupJsonSchema (line 62) | function getDatabaseSetupJsonSchema() {
  function getAPIJsonSchema (line 66) | function getAPIJsonSchema() {
  function getAuthJsonSchema (line 70) | function getAuthJsonSchema() {
  function getPaymentsJsonSchema (line 74) | function getPaymentsJsonSchema() {
  function getWebDeployJsonSchema (line 78) | function getWebDeployJsonSchema() {
  function getServerDeployJsonSchema (line 82) | function getServerDeployJsonSchema() {
  function getDirectoryConflictJsonSchema (line 86) | function getDirectoryConflictJsonSchema() {
  function getTemplateJsonSchema (line 90) | function getTemplateJsonSchema() {
  function getAddonOptionsJsonSchema (line 94) | function getAddonOptionsJsonSchema() {
  function getDbSetupOptionsJsonSchema (line 98) | function getDbSetupOptionsJsonSchema() {
  function getCreateInputJsonSchema (line 102) | function getCreateInputJsonSchema() {
  function getAddInputJsonSchema (line 106) | function getAddInputJsonSchema() {
  function getProjectConfigJsonSchema (line 110) | function getProjectConfigJsonSchema() {
  function getBetterTStackConfigJsonSchema (line 114) | function getBetterTStackConfigJsonSchema() {
  function getInitResultJsonSchema (line 118) | function getInitResultJsonSchema() {
  function getAllJsonSchemas (line 123) | function getAllJsonSchemas() {

FILE: packages/types/src/schemas.ts
  constant DATABASE_VALUES (line 539) | const DATABASE_VALUES = DatabaseSchema.options;
  constant ORM_VALUES (line 540) | const ORM_VALUES = ORMSchema.options;
  constant BACKEND_VALUES (line 541) | const BACKEND_VALUES = BackendSchema.options;
  constant RUNTIME_VALUES (line 542) | const RUNTIME_VALUES = RuntimeSchema.options;
  constant FRONTEND_VALUES (line 543) | const FRONTEND_VALUES = FrontendSchema.options;
  constant ADDONS_VALUES (line 544) | const ADDONS_VALUES = AddonsSchema.options;
  constant EXAMPLES_VALUES (line 545) | const EXAMPLES_VALUES = ExamplesSchema.options;
  constant PACKAGE_MANAGER_VALUES (line 546) | const PACKAGE_MANAGER_VALUES = PackageManagerSchema.options;
  constant DATABASE_SETUP_VALUES (line 547) | const DATABASE_SETUP_VALUES = DatabaseSetupSchema.options;
  constant API_VALUES (line 548) | const API_VALUES = APISchema.options;
  constant AUTH_VALUES (line 549) | const AUTH_VALUES = AuthSchema.options;
  constant PAYMENTS_VALUES (line 550) | const PAYMENTS_VALUES = PaymentsSchema.options;
  constant WEB_DEPLOY_VALUES (line 551) | const WEB_DEPLOY_VALUES = WebDeploySchema.options;
  constant SERVER_DEPLOY_VALUES (line 552) | const SERVER_DEPLOY_VALUES = ServerDeploySchema.options;
  constant DIRECTORY_CONFLICT_VALUES (line 553) | const DIRECTORY_CONFLICT_VALUES = DirectoryConflictSchema.options;
  constant TEMPLATE_VALUES (line 554) | const TEMPLATE_VALUES = TemplateSchema.options;

FILE: packages/types/src/types.ts
  type Database (line 32) | type Database = z.infer<typeof DatabaseSchema>;
  type ORM (line 33) | type ORM = z.infer<typeof ORMSchema>;
  type Backend (line 34) | type Backend = z.infer<typeof BackendSchema>;
  type Runtime (line 35) | type Runtime = z.infer<typeof RuntimeSchema>;
  type Frontend (line 36) | type Frontend = z.infer<typeof FrontendSchema>;
  type Addons (line 37) | type Addons = z.infer<typeof AddonsSchema>;
  type Examples (line 38) | type Examples = z.infer<typeof ExamplesSchema>;
  type PackageManager (line 39) | type PackageManager = z.infer<typeof PackageManagerSchema>;
  type DatabaseSetup (line 40) | type DatabaseSetup = z.infer<typeof DatabaseSetupSchema>;
  type API (line 41) | type API = z.infer<typeof APISchema>;
  type Auth (line 42) | type Auth = z.infer<typeof AuthSchema>;
  type Payments (line 43) | type Payments = z.infer<typeof PaymentsSchema>;
  type WebDeploy (line 44) | type WebDeploy = z.infer<typeof WebDeploySchema>;
  type ServerDeploy (line 45) | type ServerDeploy = z.infer<typeof ServerDeploySchema>;
  type DirectoryConflict (line 46) | type DirectoryConflict = z.infer<typeof DirectoryConflictSchema>;
  type Template (line 47) | type Template = z.infer<typeof TemplateSchema>;
  type AddonOptions (line 48) | type AddonOptions = z.infer<typeof AddonOptionsSchema>;
  type DbSetupOptions (line 49) | type DbSetupOptions = z.infer<typeof DbSetupOptionsSchema>;
  type ProjectName (line 50) | type ProjectName = z.infer<typeof ProjectNameSchema>;
  type CreateInput (line 52) | type CreateInput = z.infer<typeof CreateInputSchema>;
  type AddInput (line 53) | type AddInput = z.infer<typeof AddInputSchema>;
  type CLIInput (line 54) | type CLIInput = z.infer<typeof CLIInputSchema>;
  type ProjectConfig (line 55) | type ProjectConfig = z.infer<typeof ProjectConfigSchema>;
  type BetterTStackConfig (line 56) | type BetterTStackConfig = z.infer<typeof BetterTStackConfigSchema>;
  type InitResult (line 57) | type InitResult = z.infer<typeof InitResultSchema>;
  type WebFrontend (line 59) | type WebFrontend = Extract<
  type DesktopWebFrontend (line 72) | type DesktopWebFrontend = Exclude<WebFrontend, "none">;
  type NativeFrontend (line 74) | type NativeFrontend = Extract<

FILE: scripts/bump-version.ts
  constant CLI_PACKAGE_JSON_PATH (line 7) | const CLI_PACKAGE_JSON_PATH = join(process.cwd(), "apps/cli/package.json");
  constant ALIAS_PACKAGE_JSON_PATH (line 8) | const ALIAS_PACKAGE_JSON_PATH = join(process.cwd(), "packages/create-bts...
  constant TYPES_PACKAGE_JSON_PATH (line 9) | const TYPES_PACKAGE_JSON_PATH = join(process.cwd(), "packages/types/pack...
  constant TEMPLATE_GENERATOR_PACKAGE_JSON_PATH (line 10) | const TEMPLATE_GENERATOR_PACKAGE_JSON_PATH = join(
  function main (line 15) | async function main(): Promise<void> {

FILE: scripts/canary-release.ts
  constant CLI_PACKAGE_JSON_PATH (line 7) | const CLI_PACKAGE_JSON_PATH = join(process.cwd(), "apps/cli/package.json");
  constant ALIAS_PACKAGE_JSON_PATH (line 8) | const ALIAS_PACKAGE_JSON_PATH = join(process.cwd(), "packages/create-bts...
  constant TYPES_PACKAGE_JSON_PATH (line 9) | const TYPES_PACKAGE_JSON_PATH = join(process.cwd(), "packages/types/pack...
  constant TEMPLATE_GENERATOR_PACKAGE_JSON_PATH (line 10) | const TEMPLATE_GENERATOR_PACKAGE_JSON_PATH = join(
  function main (line 15) | async function main(): Promise<void> {

FILE: scripts/cleanup-previews.ts
  constant PACKAGES (line 4) | const PACKAGES = [
  type DistTags (line 11) | interface DistTags {
  function main (line 15) | async function main(): Promise<void> {
  function cleanupPR (line 121) | async function cleanupPR(prNumber: string, isDryRun: boolean): Promise<v...

FILE: scripts/publish-smoke.ts
  constant ROOT (line 19) | const ROOT = resolve(import.meta.dir, "..");
  type Publishable (line 21) | type Publishable = {
  constant PUBLISHABLES (line 29) | const PUBLISHABLES: Publishable[] = [
  function pack (line 43) | async function pack(pkg: Publishable, outDir: string): Promise<string> {
  function installAndRun (line 77) | async function installAndRun(
  function hasPackageManager (line 121) | async function hasPackageManager(pm: string): Promise<boolean> {

FILE: scripts/release.ts
  function main (line 9) | async function main(): Promise<void> {
Condensed preview — 832 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,908K chars).
[
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 4391,
    "preview": "# Contributing to Better-T-Stack\n\nThank you for your interest in contributing to Better-T-Stack! This document provides "
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 860,
    "preview": "# These are supported funding model platforms\n\ngithub: [amanvarshney01]\npatreon: # Replace with a single Patreon usernam"
  },
  {
    "path": ".github/workflows/pr-preview.yaml",
    "chars": 6965,
    "preview": "name: PR Preview\n\non:\n  pull_request_target:\n    types: [labeled]\n\npermissions:\n  contents: read\n  pull-requests: write\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "chars": 8147,
    "preview": "name: Release\n\non:\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: write\n  pull-requests: write\n  id-token:"
  },
  {
    "path": ".github/workflows/test.yaml",
    "chars": 1401,
    "preview": "name: Test\n\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\n\nconcurrency:\n  group: test-${{ github.head_r"
  },
  {
    "path": ".gitignore",
    "chars": 492,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# Dependencies\nnode_modules\n.pnp\n"
  },
  {
    "path": ".oxfmtrc.json",
    "chars": 335,
    "preview": "{\n  \"$schema\": \"./node_modules/oxfmt/configuration_schema.json\",\n  \"experimentalSortImports\": {\n    \"order\": \"asc\"\n  },\n"
  },
  {
    "path": "AGENTS.md",
    "chars": 3212,
    "preview": "# Repository Guidelines\n\n## Project Structure & Module Organization\n\nThis repo is a Bun + Turborepo monorepo.\n\n- `apps/c"
  },
  {
    "path": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2025 Better T Stack\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 3334,
    "preview": "# Better-T-Stack\n\nA modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and cus"
  },
  {
    "path": "apps/cli/.gitignore",
    "chars": 26,
    "preview": "/node_modules\n/dist\n.smoke"
  },
  {
    "path": "apps/cli/README.md",
    "chars": 16418,
    "preview": "# Create Better-T-Stack CLI\n\nA modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practi"
  },
  {
    "path": "apps/cli/bunfig.toml",
    "chars": 340,
    "preview": "[test]\n# Preload setup file for global setup/teardown\npreload = [\"./test/setup.ts\"]\n\n# Per-test timeout (3 minutes for s"
  },
  {
    "path": "apps/cli/package.json",
    "chars": 2494,
    "preview": "{\n  \"name\": \"create-better-t-stack\",\n  \"version\": \"3.28.0\",\n  \"description\": \"A modern CLI tool for scaffolding end-to-e"
  },
  {
    "path": "apps/cli/src/cli.ts",
    "chars": 509,
    "preview": "import { createBtsCli } from \"./index\";\nimport { startBtsMcpServer } from \"./mcp\";\n\nconst [, , command, ...args] = proce"
  },
  {
    "path": "apps/cli/src/commands/history.ts",
    "chars": 2569,
    "preview": "import { intro, log } from \"@clack/prompts\";\nimport pc from \"picocolors\";\n\nimport { clearHistory, getHistory, type Proje"
  },
  {
    "path": "apps/cli/src/commands/meta.ts",
    "chars": 1294,
    "preview": "import { intro, log } from \"@clack/prompts\";\nimport { Result } from \"better-result\";\nimport pc from \"picocolors\";\n\nimpor"
  },
  {
    "path": "apps/cli/src/constants.ts",
    "chars": 1755,
    "preview": "import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { desktopWebFrontends } from \"@better-t-"
  },
  {
    "path": "apps/cli/src/helpers/addons/addons-setup.ts",
    "chars": 5472,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\nimport pc from \"picoco"
  },
  {
    "path": "apps/cli/src/helpers/addons/evlog-setup.ts",
    "chars": 35804,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\n\nimport type { Backend"
  },
  {
    "path": "apps/cli/src/helpers/addons/fumadocs-setup.ts",
    "chars": 8939,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport fs from \"fs-ext"
  },
  {
    "path": "apps/cli/src/helpers/addons/mcp-setup.ts",
    "chars": 14060,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors\";\n\nimport { navigableMulti"
  },
  {
    "path": "apps/cli/src/helpers/addons/oxlint-setup.ts",
    "chars": 2090,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport fs from \"fs-ext"
  },
  {
    "path": "apps/cli/src/helpers/addons/skills-setup.ts",
    "chars": 14586,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors\";\n\nimport { navigableMulti"
  },
  {
    "path": "apps/cli/src/helpers/addons/starlight-setup.ts",
    "chars": 1696,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport fs from \"fs-ext"
  },
  {
    "path": "apps/cli/src/helpers/addons/tauri-setup.ts",
    "chars": 3504,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { execa } from \"execa\";\nimport fs from \"fs"
  },
  {
    "path": "apps/cli/src/helpers/addons/tui-setup.ts",
    "chars": 5375,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport fs from \"fs-ext"
  },
  {
    "path": "apps/cli/src/helpers/addons/ultracite-setup.ts",
    "chars": 9343,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors\";\n\nimport { navigableMulti"
  },
  {
    "path": "apps/cli/src/helpers/addons/wxt-setup.ts",
    "chars": 4492,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport fs from \"fs-ext"
  },
  {
    "path": "apps/cli/src/helpers/core/add-handler.ts",
    "chars": 10317,
    "preview": "import path from \"node:path\";\n\nimport {\n  EMBEDDED_TEMPLATES,\n  processAddonTemplates,\n  processAddonsDeps,\n  VirtualFil"
  },
  {
    "path": "apps/cli/src/helpers/core/command-handlers.ts",
    "chars": 17544,
    "preview": "import path from \"node:path\";\n\nimport { generateReproducibleCommand } from \"@better-t-stack/template-generator\";\nimport "
  },
  {
    "path": "apps/cli/src/helpers/core/convex-codegen.ts",
    "chars": 537,
    "preview": "import path from \"node:path\";\n\nimport { $ } from \"execa\";\n\nimport type { PackageManager } from \"../../types\";\nimport { g"
  },
  {
    "path": "apps/cli/src/helpers/core/create-project.ts",
    "chars": 5851,
    "preview": "import os from \"node:os\";\nimport path from \"node:path\";\n\nimport { generate, EMBEDDED_TEMPLATES } from \"@better-t-stack/t"
  },
  {
    "path": "apps/cli/src/helpers/core/db-setup-options.ts",
    "chars": 1590,
    "preview": "import type { DatabaseSetup, DbSetupOptions } from \"../../types\";\nimport { isSilent } from \"../../utils/context\";\n\nexpor"
  },
  {
    "path": "apps/cli/src/helpers/core/db-setup.ts",
    "chars": 3593,
    "preview": "/**\n * Database setup - CLI-only operations\n * Calls external database provider CLIs (turso, neon, prisma-postgres, etc."
  },
  {
    "path": "apps/cli/src/helpers/core/detect-project-config.ts",
    "chars": 1497,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\n\nimport { readBtsConfi"
  },
  {
    "path": "apps/cli/src/helpers/core/git.ts",
    "chars": 1334,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors\";\n\nimport { ProjectCreatio"
  },
  {
    "path": "apps/cli/src/helpers/core/install-dependencies.ts",
    "chars": 1274,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors\";\n\nimport type { Addons, P"
  },
  {
    "path": "apps/cli/src/helpers/core/post-installation.ts",
    "chars": 21533,
    "preview": "import pc from \"picocolors\";\n\nimport type {\n  Backend,\n  Database,\n  DatabaseSetup,\n  Frontend,\n  ORM,\n  ProjectConfig,\n"
  },
  {
    "path": "apps/cli/src/helpers/database-providers/d1-setup.ts",
    "chars": 1612,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\n\nimport type { ProjectConfig } from \"../../types\""
  },
  {
    "path": "apps/cli/src/helpers/database-providers/docker-compose-setup.ts",
    "chars": 1845,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\n\nimport type { Database, ProjectConfig } from \".."
  },
  {
    "path": "apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts",
    "chars": 7284,
    "preview": "import path from \"node:path\";\n\nimport { cancel, isCancel, select, text } from \"@clack/prompts\";\nimport { Result } from \""
  },
  {
    "path": "apps/cli/src/helpers/database-providers/neon-setup.ts",
    "chars": 11777,
    "preview": "import path from \"node:path\";\n\nimport { isCancel, select, text } from \"@clack/prompts\";\nimport { Result } from \"better-r"
  },
  {
    "path": "apps/cli/src/helpers/database-providers/planetscale-setup.ts",
    "chars": 2950,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\n\nimport type { Project"
  },
  {
    "path": "apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts",
    "chars": 8372,
    "preview": "import path from \"node:path\";\n\nimport { isCancel, select } from \"@clack/prompts\";\nimport { Result } from \"better-result\""
  },
  {
    "path": "apps/cli/src/helpers/database-providers/supabase-setup.ts",
    "chars": 8374,
    "preview": "import path from \"node:path\";\n\nimport { isCancel, select } from \"@clack/prompts\";\nimport { Result } from \"better-result\""
  },
  {
    "path": "apps/cli/src/helpers/database-providers/turso-setup.ts",
    "chars": 14515,
    "preview": "import os from \"node:os\";\nimport path from \"node:path\";\n\nimport { confirm, isCancel, select, text } from \"@clack/prompts"
  },
  {
    "path": "apps/cli/src/index.ts",
    "chars": 14552,
    "preview": "import { getAllJsonSchemas } from \"@better-t-stack/types/json-schema\";\nimport { initTRPC } from \"@trpc/server\";\nimport {"
  },
  {
    "path": "apps/cli/src/mcp.ts",
    "chars": 13027,
    "preview": "import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontext"
  },
  {
    "path": "apps/cli/src/prompts/addons.ts",
    "chars": 6512,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport {\n  type Addons,\n  AddonsSchema,\n  type Auth,\n  type Backend,\n  ty"
  },
  {
    "path": "apps/cli/src/prompts/api.ts",
    "chars": 1511,
    "preview": "import type { API, Backend, Frontend } from \"../types\";\nimport {\n  allowedApisForFrontends,\n  validateApiFrontendCompati"
  },
  {
    "path": "apps/cli/src/prompts/auth.ts",
    "chars": 2282,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Auth, Backend, Frontend } from \"../types\";\nimport { support"
  },
  {
    "path": "apps/cli/src/prompts/backend.ts",
    "chars": 2210,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Frontend } from \"../types\";\nimport { UserCancelled"
  },
  {
    "path": "apps/cli/src/prompts/config-prompts.ts",
    "chars": 5758,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type {\n  Addons,\n  API,\n  Auth,\n  Backend,\n  Database,\n  DatabaseS"
  },
  {
    "path": "apps/cli/src/prompts/database-setup.ts",
    "chars": 3088,
    "preview": "import type { Backend, DatabaseSetup, ORM, Runtime } from \"../types\";\nimport { UserCancelledError } from \"../utils/error"
  },
  {
    "path": "apps/cli/src/prompts/database.ts",
    "chars": 1514,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Database, Runtime } from \"../types\";\nimport { User"
  },
  {
    "path": "apps/cli/src/prompts/examples.ts",
    "chars": 1456,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { API, Backend, Database, Examples, Frontend } from \"../types"
  },
  {
    "path": "apps/cli/src/prompts/frontend.ts",
    "chars": 4601,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Frontend } from \"../types\";\nimport { isFrontendAll"
  },
  {
    "path": "apps/cli/src/prompts/git.ts",
    "chars": 496,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport { UserCancelledError } from \"../utils/errors\";\nimport { isCancel, "
  },
  {
    "path": "apps/cli/src/prompts/install.ts",
    "chars": 511,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport { UserCancelledError } from \"../utils/errors\";\nimport { isCancel, "
  },
  {
    "path": "apps/cli/src/prompts/navigable-group.ts",
    "chars": 2445,
    "preview": "/**\n * Navigable group - a group of prompts that allows going back\n */\n\nimport { didLastPromptShowUI, setIsFirstPrompt, "
  },
  {
    "path": "apps/cli/src/prompts/navigable.ts",
    "chars": 19330,
    "preview": "/**\n * Navigable prompt wrappers using @clack/core\n * These prompts return GO_BACK_SYMBOL when 'b' is pressed (instead o"
  },
  {
    "path": "apps/cli/src/prompts/orm.ts",
    "chars": 1535,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Database, ORM, Runtime } from \"../types\";\nimport {"
  },
  {
    "path": "apps/cli/src/prompts/package-manager.ts",
    "chars": 1009,
    "preview": "import type { PackageManager } from \"../types\";\nimport { UserCancelledError } from \"../utils/errors\";\nimport { getUserPk"
  },
  {
    "path": "apps/cli/src/prompts/payments.ts",
    "chars": 1297,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Auth, Backend, Frontend, Payments } from \"../types\";\nimport"
  },
  {
    "path": "apps/cli/src/prompts/project-name.ts",
    "chars": 2715,
    "preview": "import path from \"node:path\";\n\nimport { isCancel, text } from \"@clack/prompts\";\nimport fs from \"fs-extra\";\nimport pc fro"
  },
  {
    "path": "apps/cli/src/prompts/runtime.ts",
    "chars": 1200,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Runtime } from \"../types\";\nimport { UserCancelledE"
  },
  {
    "path": "apps/cli/src/prompts/server-deploy.ts",
    "chars": 2026,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, Runtime, ServerDeploy, WebDeploy } from \"../types\""
  },
  {
    "path": "apps/cli/src/prompts/web-deploy.ts",
    "chars": 2681,
    "preview": "import { DEFAULT_CONFIG } from \"../constants\";\nimport type { Backend, DatabaseSetup, Frontend, Runtime, WebDeploy } from"
  },
  {
    "path": "apps/cli/src/types.ts",
    "chars": 39,
    "preview": "export * from \"@better-t-stack/types\";\n"
  },
  {
    "path": "apps/cli/src/utils/add-package-deps.ts",
    "chars": 1640,
    "preview": "import path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport { type AvailableDependencies, dependencyVersionMap } f"
  },
  {
    "path": "apps/cli/src/utils/analytics.ts",
    "chars": 1317,
    "preview": "import { Result } from \"better-result\";\n\nimport type { ProjectConfig } from \"../types\";\nimport { getLatestCLIVersion } f"
  },
  {
    "path": "apps/cli/src/utils/bts-config.ts",
    "chars": 1574,
    "preview": "import path from \"node:path\";\n\nimport type { BetterTStackConfig } from \"@better-t-stack/types\";\nimport fs from \"fs-extra"
  },
  {
    "path": "apps/cli/src/utils/command-exists.ts",
    "chars": 606,
    "preview": "import { Result } from \"better-result\";\nimport { $ } from \"execa\";\n\nexport async function commandExists(command: string)"
  },
  {
    "path": "apps/cli/src/utils/compatibility-rules.ts",
    "chars": 14629,
    "preview": "import { Result } from \"better-result\";\n\nimport { ADDON_COMPATIBILITY } from \"../constants\";\nimport type {\n  Addons,\n  A"
  },
  {
    "path": "apps/cli/src/utils/compatibility.ts",
    "chars": 221,
    "preview": "import type { Frontend } from \"../types\";\n\nexport const WEB_FRAMEWORKS: readonly Frontend[] = [\n  \"tanstack-router\",\n  \""
  },
  {
    "path": "apps/cli/src/utils/config-processing.ts",
    "chars": 3854,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\n\nimport type {\n  API,\n  Auth,\n  Backend,\n  CLIInp"
  },
  {
    "path": "apps/cli/src/utils/config-validation.ts",
    "chars": 18564,
    "preview": "import { Result } from \"better-result\";\n\nimport type { CLIInput, Database, DatabaseSetup, ProjectConfig, Runtime } from "
  },
  {
    "path": "apps/cli/src/utils/context.ts",
    "chars": 3256,
    "preview": "import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { PackageManager } from \"../types\";\n\nexport type Navi"
  },
  {
    "path": "apps/cli/src/utils/display-config.ts",
    "chars": 3169,
    "preview": "import pc from \"picocolors\";\n\nimport type { ProjectConfig } from \"../types\";\n\nexport function displayConfig(config: Part"
  },
  {
    "path": "apps/cli/src/utils/docker-utils.ts",
    "chars": 2019,
    "preview": "import os from \"node:os\";\n\nimport { Result } from \"better-result\";\nimport { $ } from \"execa\";\nimport pc from \"picocolors"
  },
  {
    "path": "apps/cli/src/utils/env-utils.ts",
    "chars": 1578,
    "preview": "import fs from \"fs-extra\";\n\nexport interface EnvVariable {\n  key: string;\n  value: string;\n  condition?: boolean;\n}\n\nexp"
  },
  {
    "path": "apps/cli/src/utils/errors.ts",
    "chars": 5829,
    "preview": "import { cancel } from \"@clack/prompts\";\nimport { Result, TaggedError } from \"better-result\";\nimport pc from \"picocolors"
  },
  {
    "path": "apps/cli/src/utils/external-commands.ts",
    "chars": 152,
    "preview": "export function shouldSkipExternalCommands(): boolean {\n  return process.env.BTS_SKIP_EXTERNAL_COMMANDS === \"1\" || proce"
  },
  {
    "path": "apps/cli/src/utils/file-formatter.ts",
    "chars": 2258,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\nimport { format, type "
  },
  {
    "path": "apps/cli/src/utils/get-latest-cli-version.ts",
    "chars": 781,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\nimport fs from \"fs-extra\";\n\nimport { PKG_ROOT } f"
  },
  {
    "path": "apps/cli/src/utils/get-package-manager.ts",
    "chars": 309,
    "preview": "import type { PackageManager } from \"../types\";\n\nexport const getUserPkgManager: () => PackageManager = () => {\n  const "
  },
  {
    "path": "apps/cli/src/utils/input-hardening.ts",
    "chars": 826,
    "preview": "import { Result } from \"better-result\";\n\nimport { ValidationError } from \"./errors\";\n\ntype ValidationResult = Result<voi"
  },
  {
    "path": "apps/cli/src/utils/navigation.ts",
    "chars": 152,
    "preview": "export const GO_BACK_SYMBOL = Symbol(\"clack:goBack\");\n\nexport function isGoBack(value: unknown): value is symbol {\n  ret"
  },
  {
    "path": "apps/cli/src/utils/open-url.ts",
    "chars": 485,
    "preview": "import { $ } from \"execa\";\n\nexport async function openUrl(url: string): Promise<void> {\n  const platform = process.platf"
  },
  {
    "path": "apps/cli/src/utils/package-runner.ts",
    "chars": 3355,
    "preview": "import type { PackageManager } from \"../types\";\n\nfunction splitCommandArgs(commandWithArgs: string): string[] {\n  const "
  },
  {
    "path": "apps/cli/src/utils/project-directory.ts",
    "chars": 3943,
    "preview": "import path from \"node:path\";\n\nimport { isCancel, log, select, spinner } from \"@clack/prompts\";\nimport { Result } from \""
  },
  {
    "path": "apps/cli/src/utils/project-history.ts",
    "chars": 5709,
    "preview": "import path from \"node:path\";\n\nimport { Result, TaggedError } from \"better-result\";\nimport envPaths from \"env-paths\";\nim"
  },
  {
    "path": "apps/cli/src/utils/project-name-validation.ts",
    "chars": 1906,
    "preview": "import path from \"node:path\";\n\nimport { Result } from \"better-result\";\n\nimport { ProjectNameSchema } from \"../types\";\nim"
  },
  {
    "path": "apps/cli/src/utils/render-title.ts",
    "chars": 1447,
    "preview": "import gradient from \"gradient-string\";\n\nexport const TITLE_TEXT = `\n ██████╗ ███████╗████████╗████████╗███████╗██████╗\n"
  },
  {
    "path": "apps/cli/src/utils/sponsors.ts",
    "chars": 7953,
    "preview": "import { log, outro, spinner } from \"@clack/prompts\";\nimport { Result } from \"better-result\";\nimport pc from \"picocolors"
  },
  {
    "path": "apps/cli/src/utils/telemetry.ts",
    "chars": 601,
    "preview": "/**\n * Returns true if telemetry/analytics should be enabled, false otherwise.\n *\n * - If BTS_TELEMETRY_DISABLED is pres"
  },
  {
    "path": "apps/cli/src/utils/templates.ts",
    "chars": 2305,
    "preview": "import type { CreateInput, Template } from \"../types\";\n\nexport const TEMPLATE_PRESETS: Record<Template, CreateInput | nu"
  },
  {
    "path": "apps/cli/src/utils/terminal-output.ts",
    "chars": 1406,
    "preview": "import { log, spinner } from \"@clack/prompts\";\nimport { consola, createConsola } from \"consola\";\n\nimport { isSilent } fr"
  },
  {
    "path": "apps/cli/src/utils/ts-morph.ts",
    "chars": 739,
    "preview": "import {\n  type ArrayLiteralExpression,\n  IndentationText,\n  type ObjectLiteralExpression,\n  Project,\n  QuoteKind,\n  Syn"
  },
  {
    "path": "apps/cli/src/validation.ts",
    "chars": 4106,
    "preview": "import { Result } from \"better-result\";\n\nimport type { CLIInput, ProjectConfig } from \"./types\";\nimport { getProvidedFla"
  },
  {
    "path": "apps/cli/src/virtual.ts",
    "chars": 930,
    "preview": "/**\n * Virtual filesystem export for web preview\n * Re-exports from @better-t-stack/template-generator for browser-compa"
  },
  {
    "path": "apps/cli/test/add-handler.test.ts",
    "chars": 709,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:pa"
  },
  {
    "path": "apps/cli/test/addon-options.test.ts",
    "chars": 4847,
    "preview": "import { beforeEach, describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\n"
  },
  {
    "path": "apps/cli/test/addon-setup-regressions.test.ts",
    "chars": 9393,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport { set"
  },
  {
    "path": "apps/cli/test/addons.test.ts",
    "chars": 39005,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport { existsSync } from \"node:fs\";\nimport { readdir, readFile } from"
  },
  {
    "path": "apps/cli/test/api.test.ts",
    "chars": 18105,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { createVirtual } from \"../src/index\";\nimport type { API, Backe"
  },
  {
    "path": "apps/cli/test/auth.test.ts",
    "chars": 24412,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport type "
  },
  {
    "path": "apps/cli/test/backend-runtime.test.ts",
    "chars": 14538,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport type { Backend, Frontend, Runtime } from \"../src/types\";\nimport { expec"
  },
  {
    "path": "apps/cli/test/basic-configurations.test.ts",
    "chars": 5809,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { expectError, expectSuccess, PACKAGE_MANAGERS, runTRPCTest } f"
  },
  {
    "path": "apps/cli/test/benchmark.test.ts",
    "chars": 13868,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { expectSuccess, runTRPCTest, type TestConfig } from \"./test-ut"
  },
  {
    "path": "apps/cli/test/clerk-matrix.test.ts",
    "chars": 15371,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { createVirtual } from \"../src/index\";\nimport { validateConfigC"
  },
  {
    "path": "apps/cli/test/cli-validation.test.ts",
    "chars": 2655,
    "preview": "import { expect, test } from \"bun:test\";\n\nimport { FailedToExitError } from \"trpc-cli\";\n\nimport { createBtsCli } from \"."
  },
  {
    "path": "apps/cli/test/cloudflare-db-clients.test.ts",
    "chars": 13068,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { createVirtual } from \"../src/index\";\nimport { collectFiles } "
  },
  {
    "path": "apps/cli/test/database-orm.test.ts",
    "chars": 6536,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport type { Database, ORM } from \"../src/types\";\nimport { DATABASES, expectE"
  },
  {
    "path": "apps/cli/test/database-setup.test.ts",
    "chars": 14701,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport { DB_SETUPS, expectError, expectSuccess, runTRPCTest, type TestConfig }"
  },
  {
    "path": "apps/cli/test/db-setup-mode-resolution.test.ts",
    "chars": 937,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport {\n  mergeResolvedDbSetupOptions,\n  resolveDbSetupMode,\n} from \""
  },
  {
    "path": "apps/cli/test/db-setup-options.test.ts",
    "chars": 5666,
    "preview": "import { beforeEach, describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\n"
  },
  {
    "path": "apps/cli/test/deployment.test.ts",
    "chars": 15609,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport {\n  expectError,\n  expectSuccess,\n  runTRPCTest,\n  SERVER_DEPLOYS,\n  ty"
  },
  {
    "path": "apps/cli/test/dry-run.test.ts",
    "chars": 1356,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport { cre"
  },
  {
    "path": "apps/cli/test/electrobun-addon.test.ts",
    "chars": 8208,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport { run"
  },
  {
    "path": "apps/cli/test/examples.test.ts",
    "chars": 14109,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport { EXAMPLES, expectError, expectSuccess, runTRPCTest, type TestConfig } "
  },
  {
    "path": "apps/cli/test/external-commands.test.ts",
    "chars": 1852,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } fr"
  },
  {
    "path": "apps/cli/test/frontend.test.ts",
    "chars": 18234,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport { expectError, expectSuccess, runTRPCTest, type TestConfig } from \"./te"
  },
  {
    "path": "apps/cli/test/index.test.ts",
    "chars": 2175,
    "preview": "import { afterAll, beforeAll, describe, expect, it } from \"bun:test\";\n\nimport { expectSuccess, runTRPCTest } from \"./tes"
  },
  {
    "path": "apps/cli/test/input-schemas.test.ts",
    "chars": 3044,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport {\n  AddInputSchema,\n  BetterTStackConfigFileSchema,\n  CLIInputS"
  },
  {
    "path": "apps/cli/test/integration.test.ts",
    "chars": 18792,
    "preview": "import { describe, it } from \"bun:test\";\n\nimport type { Backend, Runtime } from \"../src/types\";\nimport { expectError, ex"
  },
  {
    "path": "apps/cli/test/mcp.test.ts",
    "chars": 12957,
    "preview": "import { afterEach, beforeEach, describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport { Client }"
  },
  {
    "path": "apps/cli/test/project-name-validation.test.ts",
    "chars": 1709,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport { cre"
  },
  {
    "path": "apps/cli/test/readme.test.ts",
    "chars": 2766,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { createVirtual } from \"../src/index\";\nimport { collectFiles } "
  },
  {
    "path": "apps/cli/test/schema-command.test.ts",
    "chars": 1331,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { initTRPC } from \"@trpc/server\";\n\nimport { router } from \"../s"
  },
  {
    "path": "apps/cli/test/setup.ts",
    "chars": 1598,
    "preview": "import { afterAll, beforeAll } from \"bun:test\";\nimport { mkdir, rm } from \"node:fs/promises\";\nimport { join } from \"node"
  },
  {
    "path": "apps/cli/test/silent-create-output.test.ts",
    "chars": 4931,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport path from \"node:path\";\n\nimport { execa } from \"execa\";\nimport fs"
  },
  {
    "path": "apps/cli/test/sponsors.test.ts",
    "chars": 2260,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport type { SponsorEntry } from \"../src/utils/sponsors\";\nimport { fo"
  },
  {
    "path": "apps/cli/test/tauri-setup.test.ts",
    "chars": 2371,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { buildTauriInitArgs } from \"../src/helpers/addons/tauri-setup\""
  },
  {
    "path": "apps/cli/test/test-utils.ts",
    "chars": 6757,
    "preview": "import { expect } from \"bun:test\";\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport {"
  },
  {
    "path": "apps/cli/test/tui-setup.test.ts",
    "chars": 2428,
    "preview": "import { describe, expect, it } from \"bun:test\";\nimport { join } from \"node:path\";\n\nimport fs from \"fs-extra\";\n\nimport {"
  },
  {
    "path": "apps/cli/test/ultracite-setup.test.ts",
    "chars": 1426,
    "preview": "import { describe, expect, it } from \"bun:test\";\n\nimport { buildUltraciteInitArgs } from \"../src/helpers/addons/ultracit"
  },
  {
    "path": "apps/cli/tsconfig.json",
    "chars": 360,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"esModul"
  },
  {
    "path": "apps/cli/tsdown.config.ts",
    "chars": 399,
    "preview": "import { defineConfig } from \"tsdown\";\n\nexport default defineConfig({\n  entry: [\"src/index.ts\", \"src/cli.ts\", \"src/virtu"
  },
  {
    "path": "apps/web/.eslintrc.json",
    "chars": 61,
    "preview": "{\n  \"extends\": [\"next/core-web-vitals\", \"next/typescript\"]\n}\n"
  },
  {
    "path": "apps/web/.gitignore",
    "chars": 364,
    "preview": "# deps\n/node_modules\n\n# generated content\n.contentlayer\n.content-collections\n.source\npublic/analytics-minimal.json\n\n# te"
  },
  {
    "path": "apps/web/.vercelignore",
    "chars": 17,
    "preview": "apps/web/scripts/"
  },
  {
    "path": "apps/web/README.md",
    "chars": 1090,
    "preview": "# Better-T-Stack Website\n\nThis is the official documentation website for Better-T-Stack, built with Next.js and Fumadocs"
  },
  {
    "path": "apps/web/cli.json",
    "chars": 29,
    "preview": "{\n  \"uiLibrary\": \"base-ui\"\n}\n"
  },
  {
    "path": "apps/web/components.json",
    "chars": 677,
    "preview": "{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-lyra\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": "
  },
  {
    "path": "apps/web/content/docs/analytics.mdx",
    "chars": 2315,
    "preview": "---\ntitle: Analytics & Telemetry\ndescription: What we collect, how to disable it, and where to view aggregated insights\n"
  },
  {
    "path": "apps/web/content/docs/bts-config.mdx",
    "chars": 2212,
    "preview": "---\ntitle: bts.jsonc\ndescription: What bts.jsonc does and why it matters\n---\n\n## What is it?\n\n`bts.jsonc` is a small con"
  },
  {
    "path": "apps/web/content/docs/cli/agent-workflows.mdx",
    "chars": 8270,
    "preview": "---\ntitle: Agent Workflows\ndescription: JSON-first and schema-driven workflows for agents, scripts, and automation\n---\n\n"
  },
  {
    "path": "apps/web/content/docs/cli/compatibility.mdx",
    "chars": 11743,
    "preview": "---\ntitle: Compatibility Rules\ndescription: Understanding compatibility rules and restrictions between different CLI opt"
  },
  {
    "path": "apps/web/content/docs/cli/index.mdx",
    "chars": 6795,
    "preview": "---\ntitle: Commands\ndescription: Complete reference for all CLI commands\n---\n\n## Overview\n\nThe Better-T-Stack CLI provid"
  },
  {
    "path": "apps/web/content/docs/cli/meta.json",
    "chars": 144,
    "preview": "{\n  \"title\": \"CLI\",\n  \"defaultOpen\": true,\n  \"pages\": [\"index\", \"agent-workflows\", \"programmatic-api\", \"options\", \"promp"
  },
  {
    "path": "apps/web/content/docs/cli/options.mdx",
    "chars": 10540,
    "preview": "---\ntitle: Options Reference\ndescription: Complete reference for all CLI options and flags\n---\n\n## General Options\n\n### "
  },
  {
    "path": "apps/web/content/docs/cli/programmatic-api.mdx",
    "chars": 4654,
    "preview": "---\ntitle: Programmatic API\ndescription: Use Better-T-Stack programmatically in your Node.js applications\n---\n\n## Overvi"
  },
  {
    "path": "apps/web/content/docs/cli/prompts.mdx",
    "chars": 1756,
    "preview": "---\ntitle: Using the interactive prompts\ndescription: How to navigate and answer the CLI's interactive questions\n---\n\n##"
  },
  {
    "path": "apps/web/content/docs/contributing.mdx",
    "chars": 2460,
    "preview": "---\ntitle: Contributing\ndescription: How to set up your environment and contribute changes\n---\n\n<Callout title=\"Importan"
  },
  {
    "path": "apps/web/content/docs/faq.mdx",
    "chars": 2452,
    "preview": "---\ntitle: Frequently Asked Questions\ndescription: Short answers to common beginner questions\n---\n\nimport { Accordion, A"
  },
  {
    "path": "apps/web/content/docs/guides/cloudflare-alchemy.mdx",
    "chars": 17567,
    "preview": "---\ntitle: Deploying to Cloudflare with Alchemy\ndescription: Learn how to deploy your Better-T-Stack app to Cloudflare W"
  },
  {
    "path": "apps/web/content/docs/guides/index.mdx",
    "chars": 913,
    "preview": "---\ntitle: Guides\ndescription: Practical guides for common setups\n---\n\n## Guides\n\nCurated, task-focused guides for worki"
  },
  {
    "path": "apps/web/content/docs/guides/meta.json",
    "chars": 91,
    "preview": "{\n  \"title\": \"Guides\",\n  \"defaultOpen\": true,\n  \"pages\": [\"index\", \"cloudflare-alchemy\"]\n}\n"
  },
  {
    "path": "apps/web/content/docs/index.mdx",
    "chars": 3143,
    "preview": "---\ntitle: Quick Start\ndescription: Create your first Better-T-Stack project in minutes\n---\n\n## Philosophy\n\n- Roll your "
  },
  {
    "path": "apps/web/content/docs/meta.json",
    "chars": 149,
    "preview": "{\n  \"pages\": [\n    \"index\",\n    \"cli\",\n    \"guides\",\n    \"project-structure\",\n    \"bts-config\",\n    \"analytics\",\n    \"co"
  },
  {
    "path": "apps/web/content/docs/project-structure.mdx",
    "chars": 15353,
    "preview": "---\ntitle: Project Structure\ndescription: Understanding the structure of projects created by Better-T-Stack CLI\n---\n\n## "
  },
  {
    "path": "apps/web/next.config.ts",
    "chars": 923,
    "preview": "import { createMDX } from \"fumadocs-mdx/next\";\nimport type { NextConfig } from \"next\";\n\nconst withMDX = createMDX();\n\nco"
  },
  {
    "path": "apps/web/package.json",
    "chars": 2134,
    "preview": "{\n  \"name\": \"web\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"prebuild\": \"(cd ../../packages/types && "
  },
  {
    "path": "apps/web/postcss.config.mjs",
    "chars": 70,
    "preview": "export default {\n  plugins: {\n    \"@tailwindcss/postcss\": {},\n  },\n};\n"
  },
  {
    "path": "apps/web/public/_headers",
    "chars": 67,
    "preview": "/_next/static/*\n  Cache-Control: public,max-age=31536000,immutable\n"
  },
  {
    "path": "apps/web/public/favicon/site.webmanifest",
    "chars": 450,
    "preview": "{\n  \"name\": \"Better T Stack\",\n  \"short_name\": \"Better T Stack\",\n  \"icons\": [\n    {\n      \"src\": \"/web-app-manifest-192x1"
  },
  {
    "path": "apps/web/public/robots.txt",
    "chars": 72,
    "preview": "User-agent: *\nAllow: /\n\nSitemap: https://better-t-stack.dev/sitemap.xml\n"
  },
  {
    "path": "apps/web/scripts/generate-schema.ts",
    "chars": 608,
    "preview": "import { execSync } from \"node:child_process\";\nimport { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\""
  },
  {
    "path": "apps/web/source.config.ts",
    "chars": 663,
    "preview": "import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from \"fumadocs-mdx/config\";\nimport { z } from \"zod\";\n"
  },
  {
    "path": "apps/web/src/app/(home)/_components/FeatureCard.tsx",
    "chars": 2549,
    "preview": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { useTheme } from \"next-themes\";\nimport Image from \"next/im"
  },
  {
    "path": "apps/web/src/app/(home)/_components/code-container.tsx",
    "chars": 3880,
    "preview": "\"use client\";\nimport { Check, ClipboardCopy } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react"
  },
  {
    "path": "apps/web/src/app/(home)/_components/command-section.tsx",
    "chars": 5354,
    "preview": "\"use client\";\nimport { Check, ChevronDown, ChevronRight, Copy, Terminal, Zap } from \"lucide-react\";\nimport Link from \"ne"
  },
  {
    "path": "apps/web/src/app/(home)/_components/footer.tsx",
    "chars": 5083,
    "preview": "import { Terminal } from \"lucide-react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { FaGithub"
  },
  {
    "path": "apps/web/src/app/(home)/_components/hero-section.tsx",
    "chars": 2005,
    "preview": "import NpmPackage from \"./npm-package\";\n\nexport default function HeroSection() {\n  return (\n    <section className=\"roun"
  },
  {
    "path": "apps/web/src/app/(home)/_components/icons.tsx",
    "chars": 7471,
    "preview": "const PackageIcon = ({ pm, className }: { pm: string; className?: string }) => {\n  switch (pm) {\n    case \"npm\":\n      r"
  },
  {
    "path": "apps/web/src/app/(home)/_components/npm-package.tsx",
    "chars": 1026,
    "preview": "\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\nconst NpmPackage = () => {\n  const [version, setVersion] = "
  },
  {
    "path": "apps/web/src/app/(home)/_components/shiny-text.tsx",
    "chars": 440,
    "preview": "interface ShinyTextProps {\n  text: string;\n  disabled?: boolean;\n  speed?: number;\n  className?: string;\n}\n\nconst ShinyT"
  },
  {
    "path": "apps/web/src/app/(home)/_components/sponsors-section.tsx",
    "chars": 17426,
    "preview": "\"use client\";\nimport { ChevronDown, ChevronUp, Globe, Heart, Star, Terminal } from \"lucide-react\";\nimport Image from \"ne"
  },
  {
    "path": "apps/web/src/app/(home)/_components/stats-section.tsx",
    "chars": 7902,
    "preview": "\"use client\";\nimport { api } from \"@better-t-stack/backend/convex/_generated/api\";\nimport { useNpmDownloadCounter } from"
  },
  {
    "path": "apps/web/src/app/(home)/_components/testimonials.tsx",
    "chars": 11027,
    "preview": "\"use client\";\n\nimport { ChevronDown, ChevronUp, Play, Terminal } from \"lucide-react\";\nimport { motion } from \"motion/rea"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/analytics-header.tsx",
    "chars": 5195,
    "preview": "import { Activity, DatabaseZap, Terminal } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { formatCompa"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/analytics-helpers.ts",
    "chars": 7587,
    "preview": "import { format } from \"date-fns\";\n\nimport type {\n  ComboMatrix,\n  Distribution,\n  ShareDistributionItem,\n  TimeSeriesPo"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/analytics-page.tsx",
    "chars": 1471,
    "preview": "\"use client\";\n\nimport Footer from \"../../_components/footer\";\nimport { AnalyticsHeader } from \"./analytics-header\";\nimpo"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/analytics-sources.tsx",
    "chars": 2911,
    "preview": "import { ArrowUpRight } from \"lucide-react\";\nimport Link from \"next/link\";\n\nexport function AnalyticsSources() {\n  retur"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/chart-card.tsx",
    "chars": 1335,
    "preview": "import type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport function ChartCard({\n  title,\n  descr"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/dev-environment-charts.tsx",
    "chars": 8020,
    "preview": "\"use client\";\n\nimport { EvilBarChart } from \"@/components/evilcharts/charts/bar-chart\";\nimport { cn } from \"@/lib/utils\""
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/evil-chart-utils.ts",
    "chars": 2651,
    "preview": "import type { ChartConfig } from \"@/components/evilcharts/ui/chart\";\n\nimport type { ShareDistributionItem } from \"./type"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/live-logs.tsx",
    "chars": 9000,
    "preview": "\"use client\";\n\nimport { api } from \"@better-t-stack/backend/convex/_generated/api\";\nimport { useQuery } from \"convex/rea"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/metrics-cards.tsx",
    "chars": 10875,
    "preview": "\"use client\";\n\nimport NumberFlow from \"@number-flow/react\";\nimport { AreaChart, Flame, Gauge, Radar, Sparkles, Sunrise }"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/preference-chart-card.tsx",
    "chars": 4172,
    "preview": "\"use client\";\n\nimport { EvilBarChart } from \"@/components/evilcharts/charts/bar-chart\";\nimport { cn } from \"@/lib/utils\""
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/section-header.tsx",
    "chars": 726,
    "preview": "import type { ReactNode } from \"react\";\n\nexport function SectionHeader({\n  label,\n  title,\n  description,\n  aside,\n}: {\n"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/stack-configuration-charts.tsx",
    "chars": 3201,
    "preview": "\"use client\";\n\nimport { shortenLabel } from \"./analytics-helpers\";\nimport { PreferenceChartCard } from \"./preference-cha"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/timeline-charts.tsx",
    "chars": 6995,
    "preview": "\"use client\";\n\nimport { EvilAreaChart } from \"@/components/evilcharts/charts/area-chart\";\nimport { EvilBarChart } from \""
  },
  {
    "path": "apps/web/src/app/(home)/analytics/_components/types.ts",
    "chars": 3096,
    "preview": "export type DistributionItem = { name: string; value: number };\nexport type Distribution = DistributionItem[];\n\nexport t"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/analytics-client.tsx",
    "chars": 13658,
    "preview": "\"use client\";\n\nimport { api } from \"@better-t-stack/backend/convex/_generated/api\";\nimport { type Preloaded, useConvexCo"
  },
  {
    "path": "apps/web/src/app/(home)/analytics/page.tsx",
    "chars": 1452,
    "preview": "import { api } from \"@better-t-stack/backend/convex/_generated/api\";\nimport { preloadQuery } from \"convex/nextjs\";\nimpor"
  },
  {
    "path": "apps/web/src/app/(home)/layout.tsx",
    "chars": 463,
    "preview": "\"use client\";\n\nimport { HomeLayout } from \"fumadocs-ui/layouts/home\";\nimport type { ReactNode } from \"react\";\n\nimport { "
  },
  {
    "path": "apps/web/src/app/(home)/new/_components/action-buttons.tsx",
    "chars": 2501,
    "preview": "\"use client\";\n\nimport { RefreshCw, Settings, Shuffle, Star } from \"lucide-react\";\n\ntype ActionButtonsProps = {\n  onReset"
  }
]

// ... and 632 more files (download for full content)

About this extraction

This page contains the full source code of the better-t-stack/create-better-t-stack GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 832 files (3.4 MB), approximately 958.3k tokens, and a symbol index with 1357 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!