Skip to content

Conversation

waruhachi
Copy link
Contributor

@waruhachi waruhachi commented Aug 26, 2025

This pull request introduces support for the T3 Env addon.

  • The initial implementation was created a few months ago but wasn’t fully tested at that time.
  • The code has now been updated to align with the latest changes in the fork.
  • Note: This feature is expected to work, but extensive testing is required before merging.

Next Steps

  • Validate the integration with existing workflows.
  • Confirm compatibility with current configurations.
  • Report any issues or edge cases during testing.

References:
[Feature Request] Add Support for t3-env package and backend static serving #253
Request for T3 ENV #422

Summary by CodeRabbit

  • New Features

    • Introduced a “T3 Env” addon for type-safe environment variables, available in the CLI and stack builder.
    • Enabled integration across Next.js and Nuxt templates, including server/client env validation.
    • Included “T3 Env” by default in presets and the default stack.
  • Documentation

    • Updated READMEs, CLI options reference, and examples to include “t3env”.
    • Reflected addon in generated project READMEs and site content.
  • Chores

    • Added “t3env” to package keywords and site metadata.
    • Updated UI labels/colors to display the new addon.

Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

Walkthrough

Introduces a new CLI addon “t3env” for type-safe environment variables. Updates CLI constants, prompts, types, addon setup flow, and adds templates for Next/Nuxt env scaffolding. Adjusts defaults/presets to include t3env, updates docs and website to surface the addon, and adds required dependency versions.

Changes

Cohort / File(s) Summary
CLI Addon Core Integration
apps/cli/src/constants.ts, apps/cli/src/helpers/addons/addons-setup.ts, apps/cli/src/helpers/addons/t3env-setup.ts, apps/cli/src/prompts/addons.ts, apps/cli/src/types.ts
Adds t3env addon: extends defaults and compatibility, adds dependency versions (zod, @t3-oss/env-*), integrates setup flow via setupT3Env, updates prompts and Addons schema.
CLI Templates: T3 Env
apps/cli/templates/addons/t3env/...
New templates for Next/Nuxt env: server and client env validation using @t3-oss/env-* and zod; Next/Nuxt config imports to initialize env.
CLI Nuxt Base Template Touch-up
apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs
Adds import of ./env.
CLI Package Metadata
apps/cli/package.json
Adds keyword "t3env".
CLI README
apps/cli/README.md
Documents t3env addon, usage flag --addons t3env, and compatibility note with none.
Root README
README.md
Lists “T3 Env” in Addons.
Website UI/Logic & Presets
apps/web/src/lib/constant.ts, apps/web/src/app/(home)/_components/stack-builder.tsx, apps/web/src/app/(home)/analytics/_components/types.ts, apps/web/src/app/layout.tsx, apps/web/src/app/(home)/_components/npm-package.tsx
Adds t3env addon option, includes it in defaults/presets, enables command generation with t3env, updates analytics config and site metadata keywords; minor formatting.
Website Docs
apps/web/content/docs/index.mdx, apps/web/content/docs/cli/options.mdx
Updates examples and options to include t3env; adjusts default stack command to include t3env.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as CLI (create)
  participant Addons as setupAddons
  participant T3Env as setupT3Env
  participant FS as fs-extra
  participant Pkg as addPackageDependency

  User->>CLI: run with --addons ... t3env ...
  CLI->>Addons: setupAddons(config)
  Addons->>Addons: if addons includes "t3env"
  Addons->>T3Env: setupT3Env(config)

  rect rgba(230,230,255,0.4)
    note right of T3Env: Start spinner: "Setting up T3 Env"
    T3Env->>FS: check apps/server, apps/web existence
    alt Frontend: Next
      T3Env->>Pkg: add @t3-oss/env-nextjs (+ zod if needed)
    else Frontend: Nuxt
      T3Env->>Pkg: add @t3-oss/env-nuxt + zod
    else Other web
      T3Env->>Pkg: add @t3-oss/env-core + zod
    end
    opt Server present
      T3Env->>Pkg: add @t3-oss/env-core + zod (server)
    end
  end

  T3Env-->>Addons: success or error (spinner stop)
  Addons-->>CLI: continue other addon setups
  CLI-->>User: generated project with T3 Env scaffolding
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

In burrows of code I nibble with glee,
A sprout named t3env grows type-safely.
Zod in my paws, I validate breeze,
Next and Nuxt forests whisper env keys.
With presets updated, I thump in delight—
Burrow secure, variables right. 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (18)
apps/web/src/app/(home)/_components/npm-package.tsx (3)

15-17: Guard against empty or unexpected GitHub releases payload

Accessing data[0].tag_name will throw if there are no releases or the payload shape changes. Add a defensive check and a safe fallback.

Apply this diff:

-        const data = await res.json();
-        const latestVersion = data[0].tag_name.replace(/^v/, "");
-        setVersion(latestVersion);
+        const data = await res.json();
+        const tag =
+          Array.isArray(data) && data.length > 0 && typeof data[0]?.tag_name === "string"
+            ? data[0].tag_name
+            : null;
+        setVersion(tag ? tag.replace(/^v/, "") : "latest");

8-24: Prevent state update on unmounted component; add AbortController and pass signal to fetch

If the component unmounts before the request resolves, setVersion may run after unmount. Abort the fetch and avoid potential React warnings. This also sets you up to add caching or retries later.

Apply this diff:

 useEffect(() => {
-    const getLatestVersion = async () => {
+    const controller = new AbortController();
+    const getLatestVersion = async () => {
       try {
-        const res = await fetch(
-          "https://api.github.com/repos/AmanVarshney01/create-better-t-stack/releases",
-        );
+        const res = await fetch(
+          "https://api.github.com/repos/AmanVarshney01/create-better-t-stack/releases",
+          { signal: controller.signal },
+        );
         if (!res.ok) throw new Error("Failed to fetch version");
-        const data = await res.json();
+        const data = await res.json();
         const latestVersion = data[0].tag_name.replace(/^v/, "");
         setVersion(latestVersion);
       } catch (error) {
         console.error("Error fetching NPM version:", error);
         setVersion("latest");
       }
     };
     getLatestVersion();
-  }, []);
+    return () => controller.abort();
+  }, []);

Architecture note: For a public homepage, an unauthenticated client-side call to GitHub’s API risks rate limits. Consider moving this to a server component/route with caching (e.g., revalidate) or switching to the npm registry endpoint for the package’s dist-tags.latest, which is simpler to parse and cacheable by your edge/CDN.


19-20: Clarify log message source

The message says “NPM” but the data source is GitHub. Align the message to reduce confusion during debugging.

-        console.error("Error fetching NPM version:", error);
+        console.error("Error fetching version from GitHub releases:", error);
apps/web/src/app/layout.tsx (1)

39-40: Minor SEO nit: add common synonyms for the new keyword

Adding a couple of variants can help searchability without changing behavior.

Apply this diff to extend the keywords list:

-		"t3env",
+		"t3env",
+		"t3 env",
+		"t3-oss/env",
apps/web/src/app/(home)/_components/stack-builder.tsx (1)

1166-1179: Avoid hardcoding addon ids; derive from TECH_OPTIONS to prevent future drift

validAddons is a hardcoded whitelist. It can silently drift from TECH_OPTIONS or the CLI if new addons are added later. Use TECH_OPTIONS.addons to derive the allowed set and filter out "none".

Apply this diff to make the list source-of-truth driven:

-			const validAddons = stackState.addons.filter((addon) =>
-				[
-					"pwa",
-					"tauri",
-					"starlight",
-					"biome",
-					"husky",
-					"turborepo",
-					"ultracite",
-					"fumadocs",
-					"oxlint",
-					"ruler",
-					"t3env",
-				].includes(addon),
-			);
+			const knownAddons =
+				(TECH_OPTIONS.addons ?? [])
+					.map((opt) => opt.id)
+					.filter((id) => id !== "none");
+			const validAddons = stackState.addons.filter((addon) =>
+				knownAddons.includes(addon),
+			);
apps/cli/package.json (1)

52-59: Optional: consider migrating tests to Bun’s built-in runner

Per project guidelines, prefer “bun test” over external runners. This is out-of-scope for this PR but worth a follow-up to simplify toolchain and devDependencies.

Example scripts section using Bun’s runner:

{
  "scripts": {
    "build": "tsdown",
    "dev": "tsdown --watch",
    "check-types": "tsc --noEmit",
    "check": "biome check --write .",
    "test": "bun test",
    "test:ui": "bun test --watch",
    "prepublishOnly": "npm run build"
  }
}

I can open a small follow-up PR to migrate tests and remove unused deps if you’d like.

apps/web/content/docs/cli/options.mdx (1)

248-248: Docs LGTM: Addons list now includes t3env

Reads well and matches the CLI flag. Consider adding a one-liner note that the CLI wires T3 Env with zod and provides Next/Nuxt env templates so users know what to expect.

Possible clarification right under the bullet:

  • “The CLI sets up T3 Env with zod. Client/server templates are provided for Next/Nuxt; server-only uses env-core.”

If helpful, I can add a short “Usage” snippet showing --addons t3env in a full command.

apps/cli/README.md (3)

44-44: Keep feature list in sync with CLI options (missing addons in table).

The Addons row omits several options present in the CLI (fumadocs, ultracite, oxlint, ruler). Add them for consistency.

-| **Addons**               | • PWA support<br>• Tauri (desktop applications)<br>• Starlight (documentation site)<br>• Biome (linting and formatting)<br>• Husky (Git hooks)<br>• Turborepo (optimized builds)<br>• T3 Env (Type-safe environment variables)                                                                           |
+| **Addons**               | • PWA support<br>• Tauri (desktop applications)<br>• Starlight (documentation site)<br>• Biome (linting and formatting)<br>• Husky (Git hooks)<br>• Turborepo (optimized builds)<br>• T3 Env (Type-safe environment variables)<br>• Fumadocs (documentation site)<br>• Ultracite (Biome preset + AI)<br>• Oxlint (Rust linter)<br>• Ruler (AI rules) |

61-61: Add missing addon "ruler" to the CLI flag help.

The --addons list is missing ruler, which exists in code (ADDON_COMPATIBILITY and web constants). Add it to prevent confusion.

-  --addons <types...>             Additional addons (pwa, tauri, starlight, biome, husky, turborepo, fumadocs, ultracite, oxlint, t3env, none)
+  --addons <types...>             Additional addons (pwa, tauri, starlight, biome, husky, turborepo, fumadocs, ultracite, oxlint, ruler, t3env, none)

195-195: Generalize or update the "Addons 'none'" note to include all addons.

Currently lists a subset; either remove the parenthetical or include all addons to avoid drift.

-- **Addons 'none'**: Skips all addons (PWA, Tauri, Starlight, Biome, Husky, Turborepo, T3 Env).
+- **Addons 'none'**: Skips all addons (e.g., PWA, Tauri, Starlight, Biome, Husky, Turborepo, T3 Env, Fumadocs, Ultracite, Oxlint, Ruler).
apps/cli/src/helpers/addons/t3env-setup.ts (3)

23-29: Server deps: LGTM, but gate on backend existence.

Install @t3-oss/env-core + zod only if a server app exists and backend !== "none".

-		const serverDir = path.join(projectDir, "apps/server");
-		if (await fs.pathExists(serverDir)) {
+		const serverDir = path.join(projectDir, "apps/server");
+		if (backend !== "none" && (await fs.pathExists(serverDir))) {

43-47: Fix misleading comment for Nuxt branch.

The comment says “use the core package” but you install @t3-oss/env-nuxt. Update the comment.

-				// For Nuxt, we'll use the core package
+				// For Nuxt, use the Nuxt-specific package

57-63: Success/error messaging: enhance clarity.

Consider coloring success with pc.green and include which apps were configured (server/web) to aid debugging in multi-app repos.

-		s.stop("T3 Env configured successfully!");
+		s.stop(pc.green("T3 Env configured successfully!"));
apps/web/src/lib/constant.ts (1)

513-520: Icon path consistency for t3env.

Most icons use ICON_BASE_URL; t3env points to a local /icon/t3env.svg. Prefer a consistent source (or confirm the asset exists in public/icon/ and is deployed).

-			icon: "/icon/t3env.svg",
+			icon: `${ICON_BASE_URL}/t3env.svg`,

If the remote asset doesn’t exist yet, add it to the CDN or keep the local path and ensure the file is present in the web app’s public assets.

apps/cli/src/helpers/addons/addons-setup.ts (1)

63-65: Consider allowing T3 Env without a backend

setupT3Env exits early when backend === "none". T3 Env can still be valuable for Next-only apps (client/public env validation). Consider relaxing the restriction and running the web dependency/setup path even without a backend.

If you choose to keep the restriction, make sure the prompt/README explicitly calls it out to avoid user confusion.

apps/cli/templates/addons/t3env/apps/server/next/src/env/server.ts.hbs (1)

1-15: Tighten runtimeEnv mapping and add opt-out for validation in CI

Current config passes experimental__runtimeEnv: process.env but doesn’t explicitly scope runtimeEnv. To prevent accidental exposure and to improve treeshaking, explicitly map only the keys you declare. Also, add a skipValidation flag controlled by SKIP_ENV_VALIDATION (commonly used in CI).

Apply this diff:

 export const env = createEnv({
   server: {
     DATABASE_URL: z.string().url(),
     BETTER_AUTH_SECRET: z.string().min(1),
     BETTER_AUTH_URL: z.string().url(),
     CORS_ORIGIN: z.string().url(),
     {{#if (includes examples 'ai')}}
     GOOGLE_GENERATIVE_AI_API_KEY: z.string().min(1),
     {{/if}}
   },
-  experimental__runtimeEnv: process.env,
+  // Only provide the vars you defined above to the runtime mapping
+  runtimeEnv: {
+    DATABASE_URL: process.env.DATABASE_URL,
+    BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
+    BETTER_AUTH_URL: process.env.BETTER_AUTH_URL,
+    CORS_ORIGIN: process.env.CORS_ORIGIN,
+    {{#if (includes examples 'ai')}}
+    GOOGLE_GENERATIVE_AI_API_KEY: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
+    {{/if}}
+  },
+  // Optional: allow skipping validation in CI/local scripts
+  skipValidation: !!process.env.SKIP_ENV_VALIDATION,
+  experimental__runtimeEnv: process.env,
 });

Please confirm the targeted @t3-oss/env-nextjs version still recommends experimental__runtimeEnv with Next.js, and whether you want CORS_ORIGIN to support multiple origins (array or CSV). If yes, we can tweak the schema accordingly.

apps/cli/templates/addons/t3env/apps/web/next/src/env/client.ts.hbs (2)

4-17: Add skipValidation and emptyStringAsUndefined for better DX and CI ergonomics.

This prevents noisy failures in CI or on platforms that inject empty strings. It’s a common pattern across T3 Env templates.

Apply this diff:

 export const env = createEnv({
   client: {
     NEXT_PUBLIC_SERVER_URL: z.string().url(),
     {{#if (eq backend 'convex')}}
     NEXT_PUBLIC_CONVEX_URL: z.string().url(),
     {{/if}}
   },
   runtimeEnv: {
     NEXT_PUBLIC_SERVER_URL: process.env.NEXT_PUBLIC_SERVER_URL,
     {{#if (eq backend 'convex')}}
     NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL,
     {{/if}}
-  },
+  },
+  // Skip validation in CI or when explicitly requested.
+  skipValidation:
+    process.env.CI === "true" || process.env.SKIP_ENV_VALIDATION === "true",
+  // Treat empty strings as undefined to avoid false positives on some hosts.
+  emptyStringAsUndefined: true,
 });

7-9: Convex key naming LGTM; confirm docs alignment.

NEXT_PUBLIC_CONVEX_URL matches typical Convex examples. Just ensure the CLI scaffold also writes this key into .env (local) and docs/readme so users don’t miss it.

If helpful, I can add .env(.example) insertion and a short README section for Convex with a checklist.

Also applies to: 13-15

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 77b3b72 and 1f8afc7.

⛔ Files ignored due to path filters (2)
  • apps/web/public/icon/t3env.svg is excluded by !**/*.svg
  • demo.gif is excluded by !**/*.gif
📒 Files selected for processing (22)
  • README.md (1 hunks)
  • apps/cli/README.md (3 hunks)
  • apps/cli/package.json (1 hunks)
  • apps/cli/src/constants.ts (3 hunks)
  • apps/cli/src/helpers/addons/addons-setup.ts (2 hunks)
  • apps/cli/src/helpers/addons/t3env-setup.ts (1 hunks)
  • apps/cli/src/helpers/core/create-readme.ts (1 hunks)
  • apps/cli/src/prompts/addons.ts (2 hunks)
  • apps/cli/src/types.ts (1 hunks)
  • apps/cli/templates/addons/t3env/apps/server/next/next.config.ts (1 hunks)
  • apps/cli/templates/addons/t3env/apps/server/next/src/env/server.ts.hbs (1 hunks)
  • apps/cli/templates/addons/t3env/apps/web/next/src/env/client.ts.hbs (1 hunks)
  • apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs (1 hunks)
  • apps/cli/templates/addons/t3env/apps/web/nuxt/src/env/client.ts.hbs (1 hunks)
  • apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs (1 hunks)
  • apps/web/content/docs/cli/options.mdx (1 hunks)
  • apps/web/content/docs/index.mdx (1 hunks)
  • apps/web/src/app/(home)/_components/npm-package.tsx (1 hunks)
  • apps/web/src/app/(home)/_components/stack-builder.tsx (1 hunks)
  • apps/web/src/app/(home)/analytics/_components/types.ts (1 hunks)
  • apps/web/src/app/layout.tsx (1 hunks)
  • apps/web/src/lib/constant.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/convex_rules.mdc)

**/*.{ts,tsx}: Use Id from './_generated/dataModel' to type document ids (e.g., Id<'users'>)
Ensure Record key/value types align with validators (e.g., v.record(v.id('users'), v.string()) => Record<Id<'users'>, string>)
Be strict with types for document ids; prefer Id<'table'> over string
Use 'as const' for string literals in discriminated unions
When using Array and Record types, declare with explicit generic types (e.g., const arr: Array = ...)

Files:

  • apps/cli/templates/addons/t3env/apps/server/next/next.config.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/types.ts
  • apps/web/src/app/(home)/_components/stack-builder.tsx
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/app/(home)/_components/npm-package.tsx
  • apps/cli/src/helpers/addons/t3env-setup.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/(home)/analytics/_components/types.ts
  • apps/cli/src/constants.ts
  • apps/web/src/lib/constant.ts
**/*.{js,jsx,ts,tsx,mjs,cjs}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{js,jsx,ts,tsx,mjs,cjs}: Do not use dotenv; Bun auto-loads .env
Use Bun.serve() for HTTP/WebSockets; do not use express
Use bun:sqlite for SQLite; do not use better-sqlite3
Use Bun.redis for Redis; do not use ioredis
Use Bun.sql for Postgres; do not use pg or postgres.js
Use built-in WebSocket; do not use ws
Prefer Bun.file over node:fs readFile/writeFile
Use Bun.$ instead of execa for shelling out

Files:

  • apps/cli/templates/addons/t3env/apps/server/next/next.config.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/types.ts
  • apps/web/src/app/(home)/_components/stack-builder.tsx
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/app/(home)/_components/npm-package.tsx
  • apps/cli/src/helpers/addons/t3env-setup.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/(home)/analytics/_components/types.ts
  • apps/cli/src/constants.ts
  • apps/web/src/lib/constant.ts
**/package.json

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

In package.json scripts, prefer running files with bun <file> instead of node <file> or ts-node <file>

Files:

  • apps/cli/package.json
{**/package.json,**/@(jest|vitest).config.@(js|ts|mjs|cjs)}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

{**/package.json,**/@(jest|vitest).config.@(js|ts|mjs|cjs)}: Use bun test instead of jest or vitest
Use bun test to run tests

Files:

  • apps/cli/package.json
{**/package.json,**/webpack.config.@(js|ts|mjs|cjs),**/esbuild.config.@(js|ts|mjs|cjs)}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild

Files:

  • apps/cli/package.json
{**/package.json,**/vite.config.@(js|ts|mjs|cjs)}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve(); do not use vite

Files:

  • apps/cli/package.json
🧬 Code graph analysis (2)
apps/cli/src/helpers/addons/t3env-setup.ts (2)
apps/cli/src/types.ts (1)
  • ProjectConfig (160-179)
apps/cli/src/utils/add-package-deps.ts (1)
  • addPackageDependency (6-43)
apps/cli/src/helpers/addons/addons-setup.ts (1)
apps/cli/src/helpers/addons/t3env-setup.ts (1)
  • setupT3Env (9-64)
🪛 LanguageTool
README.md

[grammar] ~42-~42: There might be a mistake here.
Context: ...madocs, Ruler, Ultracite, Oxlint, T3 Env - Examples: Todo, AI - DB Setup: Turso, Ne...

(QB_NEW_EN)

🔇 Additional comments (19)
apps/web/src/app/(home)/_components/npm-package.tsx (1)

34-34: LGTM: export formatting only

No behavioral change; default export remains intact.

README.md (1)

42-42: LGTM: Added “T3 Env” to the feature list

The documentation change is consistent with the new addon’s display name used elsewhere. No issues.

apps/web/src/app/(home)/_components/stack-builder.tsx (1)

1166-1179: t3env wiring verified end-to-end

All expected references to t3env have been found and correctly configured across the repository:

  • CLI constants, types, and prompts (apps/cli/src/constants.ts, types.ts, prompts/addons.ts)
  • Dependency map including @t3-oss/env-* packages and zod in apps/cli/src/constants.ts
  • Addon setup module (apps/cli/src/helpers/addons/t3env-setup.ts)
  • Templates under apps/cli/templates/addons/t3env (with no dotenv usage)
  • Web UI constants and types (apps/web/src/lib/constant.ts, layout.tsx, analytics types)
  • Documentation mentions in CLI options and site docs (apps/web/content/docs)

No missing wiring detected; this comment can be resolved.

apps/cli/package.json (1)

39-41: LGTM: Added “t3env” to keywords

The keyword helps npm search visibility and aligns with the new addon. No functional impact.

apps/cli/src/types.ts (1)

51-53: Exhaustive t3env coverage confirmed
All references to the new t3env addon have been verified across the CLI and web layers, including:

  • apps/cli/src/constants.ts (defaults & dependency map)
  • apps/cli/src/prompts/addons.ts (prompt label/hint and grouping)
  • apps/cli/src/helpers/core/create-readme.ts (README generation)
  • apps/cli/src/helpers/addons/addons-setup.ts (import & invocation of setupT3Env)
  • apps/web/src/lib/constant.ts (display metadata & default presets)
  • apps/web/src/app/layout.tsx, analytics types, and stack-builder component
  • Documentation in apps/web/content/docs (options.mdx & index.mdx)

Type narrowing for Addons remains exhaustive and consistent. No missing references detected—ready to merge.

apps/cli/src/helpers/core/create-readme.ts (1)

471-473: Feature blurb for T3 Env — good addition

Accurately describes the addon and matches naming used elsewhere (“T3 Env”). No changes needed.

apps/cli/templates/addons/t3env/apps/web/nuxt/src/env/client.ts.hbs (1)

1-11: Nuxt client env schema is correct; no runtimeEnv needed

@t3-oss/env-nuxt auto-fills runtimeEnv, so providing only the client schema is expected. Validations for public URLs look good. (env.t3.gg)

apps/web/src/app/(home)/analytics/_components/types.ts (1)

355-358: Analytics config: New addon entry for T3 Env looks good.

Label and color slot are consistent with neighboring entries.

apps/cli/src/constants.ts (2)

166-167: Addon compatibility entry for t3env set to [] looks fine.

No hard constraints makes sense since env tooling spans frameworks. Revisit later if specific frameworks require special handling.


17-17: Addon Compatibility for “t3env” Verified

– The ADDON_COMPATIBILITY map explicitly lists t3env: [], meaning it’s considered compatible by default (no frontend constraint) since an empty array is treated as “always compatible.”
– In the interactive prompt (getAddonsChoice), validateAddonCompatibility("t3env", frontends) always returns isCompatible: true, so “T3 Env” remains selectable even if no frontends are chosen.
– During scaffold execution, t3env setup (helpers/addons/t3env-setup.ts) bails out with a warning if backend === "none", skipping environment-file generation but not failing the overall flow.

No further auto-removal logic exists for t3env when either backend or frontend is “none,” but the warning in t3env-setup.ts ensures graceful handling.

No action required unless you’d prefer stricter UX (e.g., filtering “T3 Env” out of the prompt when backend: none or when frontend: none).

apps/cli/src/helpers/addons/t3env-setup.ts (1)

49-54: No changes needed for the fallback branch’s zod dependency
The @t3-oss/env-core package relies on zod (as a peer dependency), so including zod alongside @t3-oss/env-core in the “other frameworks” fallback is correct. There’s no template‐level import to correlate here—zod is required at runtime by the core environment package.

apps/web/src/lib/constant.ts (3)

600-601: Preset default: including t3env by default is fine.

Matches CLI defaults. Ensure “Generate command” and docs reflect this to avoid surprises for users.


736-737: DEFAULT_STACK includes t3env: LGTM.

Keeps the marketing site and CLI in sync.


622-623: Verify T3 Env addon only targets the web layer in the Convex preset

The Convex preset still pulls in the t3env addon even though it sets runtime: "none" and omits any server scaffolding. Please double-check that setupT3Env does not assume or mutate a traditional backend package—i.e. it only operates on your web project and won’t touch apps/server (or any non-existent server package.json).

• In apps/cli/src/helpers/addons/t3env-setup.ts, confirm all file operations and dependency injections are scoped to the web app (e.g. under apps/web or its equivalent).
• Ensure there are no references to apps/server, serverAppDir, or direct writes to a backend package.json when config.backend === "convex".
• If you’re unsure, run a targeted grep for backend paths in that file:
grep -R "apps/server" -n apps/cli/src/helpers/addons/t3env-setup.ts
grep -R "package\\.json" -n apps/cli/src/helpers/addons/t3env-setup.ts

If setupT3Env is already isolated to the web directory, no changes are needed here.

apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs (1)

1-1: Use a relative import for the env module in next.config.ts

Next.js loads next.config.ts via Node at runtime and does not resolve TypeScript path aliases like "@/…". In your template, next.config.ts is placed under src/, so you should import the env client using a path relative to that file:

- import "@/env/client";
+ import "./env/client";

If you ever move next.config.ts to the project root (outside src/), then use:

import "./src/env/client";

Please confirm where the generator emits next.config.ts —in src/ or at the project root—and update the import path accordingly.

apps/cli/src/helpers/addons/addons-setup.ts (1)

12-12: Import placement LGTM

Importing setupT3Env alongside other addon setup helpers is consistent with the existing pattern.

apps/cli/src/prompts/addons.ts (2)

61-64: Addon display for “T3 Env” looks good

Label and hint are concise and consistent with other entries.


76-76: Grouping under “Other” is reasonable; no conflicts detected

t3env sits well with other cross-cutting addons. No compatibility side-effects here.

apps/cli/templates/addons/t3env/apps/web/next/src/env/client.ts.hbs (1)

1-2: Imports look correct and minimal.

No issues. These are the expected imports for the T3 Env + Zod setup in a Next.js client env module.

Comment on lines +147 to +150
zod: "^4.0.14",
"@t3-oss/env-core": "^0.13.8",
"@t3-oss/env-nextjs": "^0.13.8",
"@t3-oss/env-nuxt": "^0.13.8",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Pin checks: ensure versions exist and are compatible (Zod v4 + @t3-oss/env).*

Zod v4 is specified. Some ecosystems still assume v3; ensure templates and @t3-oss/env* peer ranges are compatible with v4 to avoid runtime/TS errors.


🏁 Script executed:

#!/bin/bash
# Check published versions and peer deps for compatibility.
for pkg in zod @t3-oss/env-core @t3-oss/env-nextjs @t3-oss/env-nuxt; do
  echo "== $pkg latest =="
  npm view "$pkg" version
  echo "== $pkg peerDependencies =="
  npm view "$pkg" peerDependencies --json | jq .
done

Length of output: 1642


Ensure zod version matches @t3-oss/env peer dependency*

The published v0.13.8 of @t3-oss/env-core, env-nextjs, and env-nuxt peer-depend on

"zod": "^3.24.0 || ^4.0.0-beta.0"

which does not include the stable v4.0.14 you’ve pinned. Installing zod@^4.0.14 will trigger a peer-dependency conflict.

You have two remediation paths:

• Pin to a prerelease zod that satisfies the peer range:
– In apps/cli/src/constants.ts (lines 147–150), change

- zod: "^4.0.14",
+ zod: "^4.0.0-beta.0",

This will align with the existing peer-dependency and avoid install-time errors.

• Upgrade to a future @t3-oss/env-* release that adds stable zod v4 support (once published).

🤖 Prompt for AI Agents
In apps/cli/src/constants.ts around lines 147–150, the pinned "zod": "^4.0.14"
conflicts with the peer range declared by @t3-oss/env-* (which accepts "zod":
"^3.24.0 || ^4.0.0-beta.0"); to fix, either change the zod entry to a prerelease
that satisfies the peer range (for example use a ^4.0.0-beta.x prerelease
specifier) so installs don't produce peer-dependency conflicts, or upgrade the
@t3-oss/env-* packages to a future release that formally supports stable zod v4
and then pin zod to a stable v4 once that dependency change is available.

💡 Verification agent

🧩 Analysis chain

Consider gating/removing dotenv when T3 Env is present.

Since T3 Env is now default and the guidelines discourage dotenv with Bun, ensure scaffolding doesn’t include both, to avoid duplicated/conflicting env loading.


🏁 Script executed:

#!/bin/bash
# Find any templates or code that still import/use dotenv.
rg -nP -C2 '\bdotenv\b|\bconfig\s*\(' apps/cli/templates apps || true

Length of output: 14762


Remove direct dotenv usage from CLI scaffolding now that T3 Env is the default

T3 Env packages (@t3-oss/env-core, env-nextjs, env-nuxt, etc.) now handle .env loading across runtimes, and Bun auto-loads .env files out of the box. Keeping dotenv imports/dependencies leads to duplicated or conflicting environment loading. Please remove or gate all direct dotenv usage in your scaffolding and helper code:

• In apps/cli/src/constants.ts
– Remove the "dotenv": "^17.2.1", entry.

• In all Prisma templates (apps/cli/templates/db/prisma/*/prisma.config.ts.hbs)
– Drop the top-level import "dotenv/config";.

• In backend server templates (apps/cli/templates/backend/server/**/src/index.ts.hbs)
– Remove any import "dotenv/config"; (Hono, Elysia, Fastify, Express). If you still need to support plain Node projects without Bun, you can instead wrap this import under a {{#if (eq runtime "node")}}…{{/if}} check.

• In package-template JSON files
apps/cli/templates/backend/server/server-base/package.json.hbs and …/next/package.json.hbs: drop the "dotenv": "^17.2.1" dependency.

• In deployment scripts and helpers
apps/cli/templates/deploy/alchemy/alchemy.run.ts.hbs: remove the import { config } from "dotenv"; and all config({ path: … }) calls.
– All Alchemy setup helpers (alchemy-*.ts under src/helpers/deployment/alchemy/): remove "dotenv" from the devDependencies arrays passed to addPackageDependency.

• In database-provider setup code
apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts: stop injecting import "dotenv/config"; into the generated Prisma config.

By eliminating these, you’ll avoid double-loading environment variables and fully rely on T3 Env’s loading across both Bun and Node runtimes.

🤖 Prompt for AI Agents
In apps/cli/src/constants.ts around lines 147 to 150, the package list still
includes a direct dotenv dependency which must be removed; delete the line
containing "dotenv": "^17.2.1" and ensure no other code in this file imports or
references dotenv. Also sweep the CLI scaffolding and templates as described in
the review: remove top-level import "dotenv/config" from Prisma and backend
server template files (or guard it with a {{#if (eq runtime "node")}}…{{/if}}),
drop "dotenv" from the package-template JSON files listed, remove dotenv imports
and config(...) calls from deployment scripts/helpers, and stop injecting import
"dotenv/config"; in prisma-postgres-setup.ts so T3 Env/Bun handle .env loading
exclusively.

Comment on lines +63 to +65
if (addons.includes("t3env")) {
await setupT3Env(config);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure zod is installed for Next.js web when adding T3 Env

The client/server env templates rely on zod. In t3env-setup.ts, Next.js branch currently installs @t3-oss/env-nextjs only. It should also add zod to the web app to avoid build-time errors in env/client.ts and/or env/server.ts.

Apply this diff in apps/cli/src/helpers/addons/t3env-setup.ts:

-      if (hasNext) {
-        await addPackageDependency({
-          dependencies: ["@t3-oss/env-nextjs"],
-          projectDir: webDir,
-        });
-      } else if (hasNuxt) {
+      if (hasNext) {
+        await addPackageDependency({
+          dependencies: ["@t3-oss/env-nextjs", "zod"],
+          projectDir: webDir,
+        });
+      } else if (hasNuxt) {
         // For Nuxt, we'll use the core package
         await addPackageDependency({
           dependencies: ["@t3-oss/env-nuxt", "zod"],
           projectDir: webDir,
         });
       } else {
         // For other frameworks, use the core package
         await addPackageDependency({
           dependencies: ["@t3-oss/env-core", "zod"],
           projectDir: webDir,
         });
       }

Also confirm dependencyVersionMap includes pinned versions for zod, @t3-oss/env-core, @t3-oss/env-nextjs, and @t3-oss/env-nuxt to keep installs deterministic.


🏁 Script executed:

#!/bin/bash
# Inspect Next.js branch in t3env-setup.ts to verify if "zod" is included
rg -n "addPackageDependency" -C3 --glob "apps/cli/src/helpers/addons/t3env-setup.ts"

# Locate dependencyVersionMap to ensure pinned versions for required packages
rg -n "dependencyVersionMap" -C3

Length of output: 5018


🏁 Script executed:

#!/bin/bash
# Display the section of dependencyVersionMap around @t3-oss/env-core, @t3-oss/env-nextjs, and zod
sed -n '120,160p' apps/cli/src/constants.ts

Length of output: 1224


Ensure zod is added to the Next.js branch in t3env-setup.ts

The Next.js path in setupT3Env currently installs only @t3-oss/env-nextjs, but the generated env/client.ts/env/server.ts rely on zod, which will lead to build failures.

• File: apps/cli/src/helpers/addons/t3env-setup.ts (around line 38)

-      if (hasNext) {
-        await addPackageDependency({
-          dependencies: ["@t3-oss/env-nextjs"],
-          projectDir: webDir,
-        });
-      } else if (hasNuxt) {
+      if (hasNext) {
+        await addPackageDependency({
+          dependencies: ["@t3-oss/env-nextjs", "zod"],
+          projectDir: webDir,
+        });
+      } else if (hasNuxt) {

• I’ve confirmed in apps/cli/src/constants.ts that dependencyVersionMap pins versions for
zod (^4.0.14)
@t3-oss/env-core (^0.13.8)
@t3-oss/env-nextjs (^0.13.8)
@t3-oss/env-nuxt (^0.13.8)
so installs remain deterministic.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (addons.includes("t3env")) {
await setupT3Env(config);
}
if (hasNext) {
await addPackageDependency({
dependencies: ["@t3-oss/env-nextjs", "zod"],
projectDir: webDir,
});
} else if (hasNuxt) {
🤖 Prompt for AI Agents
In apps/cli/src/helpers/addons/t3env-setup.ts around line 38, the Next.js branch
of setupT3Env currently only installs @t3-oss/env-nextjs but omits zod (and
should also include @t3-oss/env-core), causing generated env/client.ts and
env/server.ts to fail; update the Next.js install step to add zod and
@t3-oss/env-core to the list of packages to install (using the pinned versions
from dependencyVersionMap/constants) so installs remain deterministic and match
the generated code's runtime dependencies.

Comment on lines +13 to +17
// T3 Env requires a backend to be present
if (backend === "none") {
s.stop(pc.yellow("T3 Env requires a backend to be configured"));
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect early return and spinner misuse block web-only setups.

  • T3 Env does not require a separate backend; Next/Nuxt-only projects should still be configured.
  • Calling s.stop() before s.start() is an API misuse.

Refactor to always process the web app and only skip the server section when no backend/server app exists.

-	// T3 Env requires a backend to be present
-	if (backend === "none") {
-		s.stop(pc.yellow("T3 Env requires a backend to be configured"));
-		return;
-	}
+	// Proceed regardless of backend; we'll conditionally configure server/web below.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// T3 Env requires a backend to be present
if (backend === "none") {
s.stop(pc.yellow("T3 Env requires a backend to be configured"));
return;
}
- // T3 Env requires a backend to be present
- if (backend === "none") {
- s.stop(pc.yellow("T3 Env requires a backend to be configured"));
- return;
// Proceed regardless of backend; we'll conditionally configure server/web below.
🤖 Prompt for AI Agents
In apps/cli/src/helpers/addons/t3env-setup.ts around lines 13 to 17, remove the
early return and the s.stop() call so web-only projects still run; always run
the web app configuration path and only skip the server/backend configuration
when backend === "none" (or when there is no server app detected). Ensure you
never call s.stop() before s.start(): start the spinner before any long-running
step and stop it after that specific step completes or fails, and isolate
spinner usage to the server/backend section so skipping the server does not
attempt to stop a spinner that was never started.

Comment on lines +19 to +29
try {
s.start("Setting up T3 Env for type-safe environment variables...");

// Add dependencies to server
const serverDir = path.join(projectDir, "apps/server");
if (await fs.pathExists(serverDir)) {
await addPackageDependency({
dependencies: ["@t3-oss/env-core", "zod"],
projectDir: serverDir,
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Start the spinner before any conditional exits; improve messaging.

Begin the spinner first, then handle per-app setup. This avoids calling stop before start and provides clearer UX.

-	try {
-		s.start("Setting up T3 Env for type-safe environment variables...");
+	try {
+		s.start("Setting up T3 Env for type-safe environment variables...");

Optionally, after computing presence, add a note if neither app exists:

+		const serverDir = path.join(projectDir, "apps/server");
+		const webDir = path.join(projectDir, "apps/web");
+		const hasServer = await fs.pathExists(serverDir);
+		const hasWeb = await fs.pathExists(webDir);
+		if (!hasServer && !hasWeb) {
+			s.stop(pc.yellow("No apps/server or apps/web found; skipping T3 Env setup."));
+			return;
+		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
s.start("Setting up T3 Env for type-safe environment variables...");
// Add dependencies to server
const serverDir = path.join(projectDir, "apps/server");
if (await fs.pathExists(serverDir)) {
await addPackageDependency({
dependencies: ["@t3-oss/env-core", "zod"],
projectDir: serverDir,
});
}
try {
s.start("Setting up T3 Env for type-safe environment variables...");
const serverDir = path.join(projectDir, "apps/server");
const webDir = path.join(projectDir, "apps/web");
const hasServer = await fs.pathExists(serverDir);
const hasWeb = await fs.pathExists(webDir);
if (!hasServer && !hasWeb) {
s.stop(pc.yellow("No apps/server or apps/web found; skipping T3 Env setup."));
return;
}
// Add dependencies to server
if (hasServer) {
await addPackageDependency({
dependencies: ["@t3-oss/env-core", "zod"],
projectDir: serverDir,
});
}
🤖 Prompt for AI Agents
In apps/cli/src/helpers/addons/t3env-setup.ts around lines 19 to 29, the spinner
is started only inside a branch which can lead to stop being called before start
and unclear messaging; move s.start("Setting up T3 Env for type-safe environment
variables...") to before checking app directories so the spinner begins
unconditionally, then compute existence of apps (server/client) and run per-app
setup while updating spinner messages per-app; if neither app exists, update the
spinner or log a clear message indicating no apps found and then stop the
spinner.

Comment on lines +37 to +42
if (hasNext) {
await addPackageDependency({
dependencies: ["@t3-oss/env-nextjs"],
projectDir: webDir,
});
} else if (hasNuxt) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Next.js branch should also add zod.

Templates typically import zod schemas; env-nextjs doesn’t pull zod transitively. Add it to avoid compile-time errors.

-			if (hasNext) {
+			if (hasNext) {
 				await addPackageDependency({
-					dependencies: ["@t3-oss/env-nextjs"],
+					dependencies: ["@t3-oss/env-nextjs", "zod"],
 					projectDir: webDir,
 				});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (hasNext) {
await addPackageDependency({
dependencies: ["@t3-oss/env-nextjs"],
projectDir: webDir,
});
} else if (hasNuxt) {
if (hasNext) {
await addPackageDependency({
dependencies: ["@t3-oss/env-nextjs", "zod"],
projectDir: webDir,
});
} else if (hasNuxt) {
🤖 Prompt for AI Agents
In apps/cli/src/helpers/addons/t3env-setup.ts around lines 37 to 42, the Next.js
branch adds @t3-oss/env-nextjs but omits zod which is not pulled transitively;
update the call to addPackageDependency in the hasNext branch to also include
"zod" in the dependencies array so zod is installed alongside @t3-oss/env-nextjs
to prevent compile-time errors from missing schema imports.

@@ -0,0 +1 @@
import "@/env/server";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Same alias-resolution pitfall: switch to a relative import in server Next config

Using "@/env/server" in next.config.ts is prone to resolution failures. Use a relative path.

-import "@/env/server";
+// If next.config.ts is at the app root:
+import "./src/env/server";
+// If placed under src/:
+// import "./env/server";

Double-check the final file location produced by the generator and align the relative path accordingly.


🏁 Script executed:

#!/bin/bash
set -e

# Print current working directory
pwd

# List files under the Next.js config directory
find apps/cli/templates/addons/t3env/apps/server/next -maxdepth 2 -type f -print

# Find environment schema files in the template
find apps/cli/templates/addons/t3env -type f \( -name "server.ts" -o -name "env.ts" \) -print

Length of output: 274


🏁 Script executed:

#!/bin/bash
set -e

echo "Listing all files under apps/cli/templates/addons/t3env:"
find apps/cli/templates/addons/t3env -type f

Length of output: 518


🏁 Script executed:

#!/bin/bash
# Display the beginning of the Next.js server template config to inspect import paths
sed -n '1,100p' apps/cli/templates/addons/t3env/apps/server/next/next.config.ts

Length of output: 102


Switch to a relative import in next.config.ts

Importing via the @/... alias in your Next.js config isn’t supported at load time, causing resolution failures. Update the import to a relative path from the next.config.ts file to the generated server.ts module:

• File needing update:
apps/server/next/next.config.ts

• Change the import to point at src/env/server.ts:

-import "@/env/server";
+import "./src/env/server";

Verify this path matches your final project structure (e.g., if next.config.ts ends up under a different directory, adjust accordingly).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import "@/env/server";
import "./src/env/server";
🤖 Prompt for AI Agents
In apps/cli/templates/addons/t3env/apps/server/next/next.config.ts around line
1, the file uses an absolute alias import "@" which Next.js can't resolve at
config load time; replace the aliased import with a relative import pointing to
the generated server module (e.g., "./src/env/server" or "../src/env/server"
depending on next.config.ts location) so the config uses a filesystem path;
update the import to the correct relative path to src/env/server and verify the
path matches the final project layout.

Comment on lines +5 to +10
client: {
NEXT_PUBLIC_SERVER_URL: z.string().url(),
{{#if (eq backend 'convex')}}
NEXT_PUBLIC_CONVEX_URL: z.string().url(),
{{/if}}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Keep client keys and runtimeEnv in lockstep.

Given the conditional Convex block, any future additions to client must be mirrored in runtimeEnv. T3 Env will usually catch mismatches at compile time, but template drift can still happen during refactors.

Run this quick repo check to ensure the Next template importing this file resolves path aliases and that the dependency is declared:

Also applies to: 11-16


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Verify next.config imports the client env (fail fast validation at build time)
rg -n --color=always $'from\\s+[\'"]@/env/client[\'"]' apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs || {
  echo "Missing import of '@/env/client' in next.config.ts.hbs" >&2; exit 1; }

# 2) Ensure '@' path alias exists in the Next web template tsconfig
tsconfigs=$(fd -t f --full-path 'apps/cli/templates/addons/t3env/apps/web/next/.*tsconfig.*' || true)
if [ -n "$tsconfigs" ]; then
  echo "$tsconfigs" | xargs -I{} rg -n -C2 --color=always '"paths"\s*:\s*\{\s*"@/\*"\s*:\s*\["\./src/\*"\]' {} || {
    echo "Missing '@/ -> ./src/*' path alias in Next web tsconfig" >&2; exit 1; }
else
  echo "No tsconfig found for Next web template; please verify alias setup." >&2; exit 1
fi

# 3) Confirm the dependency is declared somewhere in templates
rg -n --color=always '@t3-oss/env-nextjs' || {
  echo "Dependency '@t3-oss/env-nextjs' not found in template manifests" >&2; exit 1; }

Length of output: 281


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 2) Verify tsconfig path alias for '@/*'
echo "Checking tsconfig path aliases..."
tsconfigs=$(fd -t f --full-path 'apps/cli/templates/addons/t3env/apps/web/next/.*tsconfig.*' || true)
if [ -n "$tsconfigs" ]; then
  echo "$tsconfigs" | while read -r f; do
    echo "-- Inspecting $f --"
    rg -n -C2 '"paths"\s*:\s*\{[^}]*"@/\*"\s*:\s*\["\.\/src\/\*"\]' "$f" \
      || echo "Missing '@/*' path alias in $f"
  done
else
  echo "No tsconfig found for Next web template"
fi

# 3) Confirm the dependency '@t3-oss/env-nextjs'
echo
echo "Checking for '@t3-oss/env-nextjs' dependency..."
rg -n '@t3-oss/env-nextjs' || echo "Dependency '@t3-oss/env-nextjs' not found in template manifests"

Length of output: 836


Action required: Add missing client env import & verify path alias

The repo check indicates two critical gaps in the Next web template:

  • Missing import of the client env in next.config.ts.hbs.
    The file apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs does not import the client-side environment, causing failsafe validation to be bypassed run1.
  • No TypeScript config found for path alias.
    Our search didn’t locate any tsconfig.json under apps/cli/templates/addons/t3env/apps/web/next/, so the @/* → ./src/* alias may be unset or in a differently named config run2.

The dependency @t3-oss/env-nextjs is already declared and used in templates—no action needed there run2.

Please address the following:

• In apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs, add at the top:

+ import { createEnv } from '@/env/client';

• Locate (or create) the Next web template’s TypeScript config (tsconfig.json or tsconfig.base.json) and ensure it includes:

{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
🤖 Prompt for AI Agents
In apps/cli/templates/addons/t3env/apps/web/next/src/client.ts.hbs around lines
5 to 10, the template defines client env schema but the Next template
next.config.ts.hbs is missing the required import of the generated client env;
update apps/cli/templates/addons/t3env/apps/web/next/src/next.config.ts.hbs to
import the client env at the top (import { clientEnv } from
'<path-to-client-env>') and use it with env-nextjs middleware as needed, and
also locate or create the Next web template TypeScript config (tsconfig.json or
tsconfig.base.json) under apps/cli/templates/addons/t3env/apps/web/next/ and add
the compilerOptions.paths mapping to map "@/*" to "./src/*" so the import path
alias resolves correctly.

@@ -1,3 +1,5 @@
import "./env";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Import path and unconditional import will break non-t3env scaffolds

  • Path is wrong: the generated file is src/env/client.ts, not ./env.
  • Import is unconditional; projects without the addon will fail at build/TS time.

Gate the import behind the addon flag and point to the correct file.

Apply:

- import "./env";
+ {{#if (includes addons "t3env")}}import "~/env/client";{{/if}}

If the includes helper isn’t available in your Handlebars runtime, switch to whatever helper you already use for array membership (or add one) and keep the same intent.

To confirm helper availability across templates:


🏁 Script executed:

#!/usr/bin/env bash
# Look for existing array-membership helpers in templates
rg -n -C2 "{{#if \(includes " apps/cli/templates || true
rg -n -C2 "{{#if \(some " apps/cli/templates || true

Length of output: 293


🏁 Script executed:

#!/usr/bin/env bash
# Search for includes helper usage in Handlebars templates
rg -nF '{{#if (includes' -g '*.hbs' apps/cli/templates || true

# Search for 'some' helper usage in Handlebars templates
rg -nF '{{#if (some' -g '*.hbs' apps/cli/templates || true

# Search for includes helper registration in TypeScript code
rg -nP 'registerHelper\(\s*["'\'']?includes["'\'']?,' -g '*.ts' apps/cli || true

# Search for any helper registrations to locate available helpers
rg -n 'registerHelper' -g '*.ts' apps/cli || true

Length of output: 4376


🏁 Script executed:

#!/usr/bin/env bash
# Display the beginning of the helper registration file to verify available helpers
sed -n '1,200p' apps/cli/src/utils/template-processor.ts

Length of output: 1334


Fix conditional Nuxt env import for t3env addon

The Nuxt scaffold currently unconditionally imports ./env, but the generated file actually lives at src/env/client.ts, and projects without the t3env addon will break at build time. We’ve confirmed that the includes helper is already registered (see apps/cli/src/utils/template-processor.ts) and used throughout other templates.

• File to update:
• apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs (line 1)
• Change the import to be conditional on the t3env addon and point to the correct path:

- import "./env";
+ {{#if (includes addons "t3env")}}import "~/env/client";{{/if}}

This ensures that only projects with the t3env addon include the client‐side env shim, and the module resolution aligns with the actual file location.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import "./env";
++ b/apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs
@@ -1,1 +1,1
{{#if (includes addons "t3env")}}import "~/env/client";{{/if}}
🤖 Prompt for AI Agents
In apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs around line 1, the
template currently unconditionally imports ./env which breaks projects without
the t3env addon and points to the wrong location; update the template to
conditionally include the client shim only when the t3env addon is present by
using the existing includes helper to wrap the import, and change the import
target to the correct client path (src/env/client.ts) so only projects with
t3env will import the client-side env shim.

@@ -114,7 +114,7 @@ Skip prompts and use the default stack:
--database sqlite \
--orm drizzle \
--auth \
--addons turborepo
--addons turborepo t3env
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Docs inconsistency: only npm example includes t3env; bun/pnpm examples and the flags list omit it

This will confuse users about the default stack. Align all tabs and the cheat sheet.

Apply these diffs:

@@
   <Tab value="bun">
     ```bash
     bun create better-t-stack@latest my-webapp \
       --frontend tanstack-router \
       --backend hono \
       --database sqlite \
       --orm drizzle \
       --auth \
-      --addons turborepo
+      --addons turborepo t3env
     ```
   </Tab>
@@
   <Tab value="pnpm">
     ```bash
     pnpm create better-t-stack@latest my-webapp \
       --frontend tanstack-router \
       --backend hono \
       --database sqlite \
       --orm drizzle \
       --auth \
-      --addons turborepo
+      --addons turborepo t3env
     ```
   </Tab>
@@
-      --addons turborepo t3env
+      --addons turborepo t3env
     ```
   </Tab>

Also add t3env to the flags cheat sheet:

- - `--addons`: turborepo, pwa, tauri, biome, husky, starlight, fumadocs, ultracite, oxlint, ruler, none
+ - `--addons`: turborepo, pwa, tauri, biome, husky, starlight, fumadocs, ultracite, oxlint, ruler, t3env, none
🤖 Prompt for AI Agents
In apps/web/content/docs/index.mdx around line 117, the install command examples
are inconsistent: only the npm example includes the "--addons t3env" flag while
the bun and pnpm examples and the flags cheat sheet omit it; update the bun and
pnpm command blocks to add "--addons turborepo t3env" (matching the npm example)
and add an entry for "t3env" to the flags cheat sheet so all tabs and the cheat
sheet consistently show the t3env addon.

Comment on lines +361 to 366
color: "hsl(var(--chart-7))",
},
none: {
label: "No Addons",
color: "hsl(var(--chart-7))",
color: "hsl(var(--chart-8))",
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify availability of CSS token --chart-8 before using it.

You bumped turborepo to --chart-7 and none to --chart-8. Ensure --chart-8 exists in the theme; otherwise charts will fallback or render inconsistently.


🏁 Script executed:

#!/bin/bash
# Verify that --chart-8 is defined somewhere in CSS/vars.
rg -nP --type css --type scss --type tsx --type ts -C2 'var\(--chart-8\)' || true
rg -nP --type css --type scss --type tsx --type ts -C2 '--chart-8:' || true

Length of output: 599


🏁 Script executed:

#!/bin/bash
# Search for any definitions or usages of --chart-7 and --chart-8 across the codebase

# Find where --chart-7 is defined to locate the CSS variable declarations
rg -n -- '--chart-7' -C2

# Find any occurrences of --chart-8 (definition or usage)
rg -n -- '--chart-8' -C2

Length of output: 137


🏁 Script executed:

#!/bin/bash
# Correctly search for CSS variable definitions and usages of --chart-7 and --chart-8

# 1. Definitions in CSS/SCSS files
rg -n -C2 '\-\-chart-(7|8)\s*:' -g '*.css' -g '*.scss'

# 2. Usages via var(...) in CSS/SCSS/TS/TSX
rg -n -C2 'var\(--chart-(7|8)\)' -g '*.css' -g '*.scss' -g '*.ts' -g '*.tsx'

Length of output: 10659


Add missing CSS variable --chart-8 in your global styles

The lookup shows that --chart-8 is referenced in apps/web/src/app/(home)/analytics/_components/types.ts (lines 365–366) but not defined in your global stylesheet (only --chart-5, --chart-6, and --chart-7 exist). Without a definition, any usage of hsl(var(--chart-8)) will be invalid and render inconsistently.

Please add a matching entry for --chart-8 in apps/web/src/app/global.css alongside the other chart variables:

• File: apps/web/src/app/global.css
• Insert after the existing --chart-7 definition

diff --git a/apps/web/src/app/global.css b/apps/web/src/app/global.css
index abcdef0..1234567 100644
--- a/apps/web/src/app/global.css
+++ b/apps/web/src/app/global.css
@@ -191,6 +191,7 @@
 	--chart-5: 27 87% 67%;
 	--chart-6: 210 80% 55%;
 	--chart-7: 330 75% 60%;
+	--chart-8:  90  70%  50%;  /* <-- define this to match your theme palette */
 	--sidebar: oklch(0.93 0.01 264.52);
 	--sidebar-foreground: oklch(0.44 0.04 279.33);

Adjust the HSL values (90 70% 50%) to fit your design’s color scheme. Once defined, hsl(var(--chart-8)) will resolve correctly.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
color: "hsl(var(--chart-7))",
},
none: {
label: "No Addons",
color: "hsl(var(--chart-7))",
color: "hsl(var(--chart-8))",
},
++ b/apps/web/src/app/global.css
@@ -191,6 +191,7 @@
--chart-5: 27 87% 67%;
--chart-6: 210 80% 55%;
--chart-8: 90 70% 50%; /* define this to match your theme palette */
--sidebar: oklch(0.93 0.01 264.52);
--sidebar-foreground: oklch(0.44 0.04 279.33);
🤖 Prompt for AI Agents
In apps/web/src/app/(home)/analytics/_components/types.ts around lines 361–366
the color uses hsl(var(--chart-8)) but --chart-8 is missing from the global
stylesheet; open apps/web/src/app/global.css and add a --chart-8 variable entry
immediately after the existing --chart-7 definition (use HSL values appropriate
for your theme, e.g., "90 70% 50%" or other chosen values) so that
hsl(var(--chart-8)) resolves correctly across the app.

@waruhachi
Copy link
Contributor Author

Possible alternative: https://envin.turbostarter.dev/

@xcortservice
Copy link

plz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants