feat: add official TanStack CLI add-on for ArkEnv - #1811
Conversation
🦋 Changeset detectedLatest commit: 09a270b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@arkenv/agent-plugin
arkenv
@arkenv/build
@arkenv/bun-plugin
@arkenv/core
@arkenv/fumadocs-ui
@arkenv/nextjs
@arkenv/nuxt
@arkenv/rsbuild-plugin
@arkenv/standard
@arkenv/tanstack-addon
@arkenv/vite-plugin
commit: |
There was a problem hiding this comment.
Important
Two things need attention before merge. First, the docs and changeset advertise an interactive "choose your validation engine" prompt, but tanstack create --add-ons <url> runs non-interactively in the CLI versions this ships against (@tanstack/create@0.70.0 / @tanstack/cli@0.71.0), so every scaffold silently gets ArkType and the Zod/Valibot branches are unreachable through any documented path. Second, the headline URL https://arkenv.js.org/tanstack/info.json 404s today (verified) — arkenv.js.org serves main/v0 and the next.config.ts proxy rewrite this PR's own design doc picked (B1a) is not part of this PR, so the documented command won't work until a separate main change lands.
Reviewed changes
- Add-on authoring package (
packages/tanstack-addon):.add-on/info.jsonmetadata with avalidatorselect (arktype/zod/valibot),package.json.ejs,src/env.ts.ejs, a demo route template, and.env.example. - Build & distribution (
scripts/build.ts): compiles raw assets into a schema-validAddOnCompiledSchemabundle (dist/info.json+dist/add-on.json) and mirrors it plus raw assets intoapps/www/public/tanstack/for CDN hosting. - Tests:
compile.test.tsvalidates the bundle againstAddOnCompiledSchema;templates.test.tsexercises EJS rendering across all three validators and URL-keyed option IDs;package-install-fencespasses for the new MDX fences. - Docs:
tanstack-start.mdxquickstart withnpx @tanstack/cli create my-app --add-ons …and atanstack addcallout;apps/www/tsconfig.jsonexcludespublic. - Design note + changeset:
docs/design/tanstack-cli-addon.md(living note, stackA1 + B1a + C2 + D2 + E1) and a minor-bump changeset.
I verified the add-on's generated code against the real package contracts: @arkenv/vite-plugin's default export is the plugin (arkenv() is valid; arkenvVitePlugin exists as a named alias), number.port is a real ArkEnv keyword, @arkenv/standard's root arkenv works with Zod zero-config and coerces the Valibot branch via the inline v.transform(Number), and the EJS addOnOption contract (variable name, URL keying for remote add-ons) matches what @tanstack/create@0.70.0 passes at render time.
⚠️ The advertised https://arkenv.js.org/tanstack/info.json 404s at merge time
The docs, changeset, and README all make https://arkenv.js.org/tanstack/info.json the install URL, but this PR only ships the bundle to the v1 deployment (apps/www/public/tanstack/). arkenv.js.org currently serves main (v0), and there is no next.config.ts rewrite (/tanstack/:path* → v1 preview) — the design doc's own chosen B1a — anywhere in this diff. I fetched the URL live and got a 404; until that rewrite lands on main (or the docs point at https://arkenv-v1.vercel.app/tanstack/info.json per the B1b fallback), anyone following the documented command gets a 404.
Technical details
# arkenv.js.org/tanstack/info.json is dead on merge
## Affected sites
- apps/www/content/docs/frameworks/tanstack-start.mdx:31, 51 — both `package-install` fences hardcode `https://arkenv.js.org/tanstack/info.json`
- .changeset/tanstack-addon.md:18, 24 — same URL in the release notes
- packages/tanstack-addon/README.md:10, 16 — same URL in package docs
- apps/www/next.config.ts — no `/tanstack/:path*` rewrite exists (this PR does not touch it)
## Required outcome
- The command users are told to run must resolve on the day the docs/changeset go live. Either (a) land the B1a proxy rewrite on `main` (3-line Next.js rewrite to the v1 preview) so the stable URL works from day one, or (b) advertise the currently-live v1 host (`arkenv-v1.vercel.app/tanstack/info.json`) for the alpha phase and migrate at GA — exactly the B1b fallback the design doc already scopes.
- Confirm the sequencing before merge; a 404 in the flagship command is a bad first-run experience for a brand-new feature.⚠️ The validator prompt the docs promise doesn't fire — the multi-validator feature is unreachable
packages/tanstack-addon/.add-on/info.json's validator select is the C2 centerpiece ("Multi-validator selection during scaffolding"), and tanstack-start.mdx tells users "The CLI prompts you to choose your preferred validation engine". Against the pinned @tanstack/create@0.70.0 (and current @tanstack/cli@0.71.0), this does not happen: passing --add-ons <url> short-circuits the interactive flow, and add-on option values come from defaults only (populateAddOnOptionsDefaults), so every scaffold gets ArkType. The interactive add-on picker excludes remote-URL add-ons, and tanstack add <url> reads options from the persisted .cta.json (no URL key, so no choice can reach the render either). Zod/Valibot are only reachable through the undocumented --add-on-config flag. In other words: the EJS branches are correct and the addOnOption lookup works for the shipped URL (I traced the exact render contract), but the user-facing promise of choice is not backed by the CLI behavior.
Technical details
# Documented validator choice is not reachable in the pinned CLI versions
## Affected sites
- apps/www/content/docs/frameworks/tanstack-start.mdx:34-39 — "The CLI prompts you to choose your preferred validation engine: ArkType (default) / Zod / Valibot"
- .changeset/tanstack-addon.md:10 — "Multi-validator selection during scaffolding (ArkType, Zod, or Valibot)"
- packages/tanstack-addon/README.md:21 — "Choose between ArkType, Zod, or Valibot"
## Evidence (traced from @tanstack/create@0.70.0 tarball + @tanstack/cli@0.71.0 dist)
- packages/create/src/package-json.ts:120,126 — render var is `addOnOption` (= `options.addOnOptions`), passed to `ejs.render`
- packages/create/src/custom-add-ons/add-on.ts:297 — remote add-on `id` is overwritten with the URL
- @tanstack/cli dist/options.js:149-152 — `--add-ons <url>` path uses `populateAddOnOptionsDefaults` (defaults only, no prompt)
- @tanstack/cli dist/ui-prompts.js:105 — interactive add-on picker lists built-in add-ons only; remote add-ons can't be selected there
- packages/create/src/add-to-app.ts:93-118 — `tanstack add <url>` `createOptions()` comes from persisted `.cta.json`; `addOnOptions` is never recomputed for the newly added remote add-on
## Required outcome
- The docs/changeset must describe actual CLI behavior for the shipped versions: ArkType is installed by default, and Zod/Valibot require the (currently undocumented) `--add-on-config` JSON flag keyed by URL. Either document that escape hatch, adjust the copy, or hold the multi-validator claim until an interactive option path exists.
- The template lookup itself is fine and needs no change; the `addOnOption['arkenv']` branch is just dead code for remote installs.
## Open questions for the human
- Is an interactive remote-add-on option prompt planned upstream? If the CLI changes before merge, re-verify rather than trusting this finding.ℹ️ Hardcoded 1.0.0-alpha.1 diverges from the design doc's chosen E1 strategy
package.json.ejs and info.json hardcode 1.0.0-alpha.1 in four places — the design doc rates exactly this (E2, "Hardcoded pinned alpha versions") as D-tier and picked E1 (versions synced from RELEASE_CONFIG). No breakage today (^1.0.0-alpha.1 keeps resolving new alphas), but the alpha→rc→GA transition means bumping the range in package.json.ejs, the info.json version field, the compiled bundles, and the affected test expectations by hand, when the build script is the natural place to inject apps/www/lib/config/release.ts. Worth wiring up now so the transition is a one-constant change.
ℹ️ Nitpicks
- The rendered
env.tsoutputs (all three dialects) and the demo route are asserted only via string containment; they are never typechecked as real TS files (this package's tsconfig includes onlyscripts/tests, andwwwnow excludespublic). A small temp-projecttscover the rendered output would catch a syntax/type slip that currently ships to every scaffolded app. tanstack-start.mdx:43says the add-on "ConfiguresarkenvVitePlugin()invite.config.ts", but the integration actually injectsarkenv(). Both names are valid exports of@arkenv/vite-plugin; align the docs with the generated code.- The Valibot branch uses the root
@arkenv/standardplus an inlinev.transform(Number), whereasarkenv initscaffolds@arkenv/standard/valibotwithv.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(65535)). Functional as-is, but matching the dialect keeps the add-on consistent with the CLI's own output.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
ℹ️ Minor suggestions only — one edge in the new optional-demo-route feature; nothing blocking.
Reviewed changes (delta since the prior review at 01ef1bc)
- Optional demo route (
7d1579f5): adds ademoselect ("true"default /"false") to.add-on/info.json, converts the demo route asset fromarkenv.tsxtoarkenv.tsx.ejs, and gates it onincludeExamples+ignoreFile()— verified against@tanstack/create@0.70.0, these are real render-context members (template-file.ts:141-184,edge-render.ts:18,31) and exactly the pattern the built-in add-ons use (if (!includeExamples) { ignoreFile(); return; }), so the skip mechanism is correct. Compiled bundles andwww/public/tanstackmirrors updated. - Docs:
tanstack-start.mdxcopy reworked to describe both "Validator Engine" and "Interactive Demo Route" choices;.env.examplepre-population is now listed instead of the always-on demo bullet. - Build fix:
scripts/build.tsnowrmSyncs the mirroredassets/dir before re-copying, so removed/renamed assets no longer linger inapps/www/public/tanstack/assets/. - Tests:
templates.test.tsgains four demo-template cases (render-by-default,ignoreFileondemo:"false", onincludeExamples:false, and via a URL keyed option);compile.test.tsasserts the.tsx.ejskey anddemodefault.
Status of the prior findings: the arkenv.js.org URL concern is now explicitly tracked ("Blocked by #1812" in the PR body, plus a sync-to-main plan) — good. The "prompts you with configuration choices" copy was softened, but the underlying behavior is unchanged: with @tanstack/create@0.70.0 / @tanstack/cli@0.71.0, --add-ons <url> still runs default-options-only and never prompts, so neither the validator nor the demo-route choice is user-selectable through the documented command — the prior inline comment on this stands.
⚠️ routes metadata still advertises /demo/arkenv when the demo file is skipped
info.json's routes entry is unconditional, but the newly-optional demo route now can be skipped (demo: "false" → ignoreFile()), so the compiled add-on can hand the CLI a route whose file was never written. The routes array is passed into the framework templates (template-file.ts:104-109,147), which wire the demo-route nav pills, so a skip would leave the scaffold's home layout pointing at a nonexistent src/routes/demo/arkenv.tsx. It's latent today (unreachable via --add-ons <url>, needs --add-on-config), but the option and the metadata now disagree by design.
Technical details
# routes metadata is stale when demo route is skipped
## Affected sites
- packages/tanstack-addon/.add-on/info.json:49-56 — `routes` always lists `/demo/arkenv` → `src/routes/demo/arkenv.tsx`
- packages/tanstack-addon/.add-on/assets/src/routes/demo/arkenv.tsx.ejs:7-13 — skip via `ignoreFile()` / `includeExamples`
- apps/www/public/tanstack/{info,add-on}.json — same metadata in the compiled bundles
## Required outcome
- When the demo route is skipped, the scaffolded app must not reference the missing route (no dangling nav pill, no missing-route error). Decide how `routes` metadata should behave under `demo:"false"` — e.g. make the entry conditional in the build step, or document that `--add-on-config '{"<url>":{"demo":"false"}}'` currently leaves a stale nav entry.
## Open questions for the human
- Does `@tanstack/create` fail hard on a route whose file is absent, or just render a dead link?DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
### Summary This PR adds a reverse proxy rewrite in `apps/www/next.config.ts` routing `/tanstack/:path*` requests to `https://arkenv-v1.vercel.app/tanstack/:path*`. ### Why The official TanStack CLI add-on for ArkEnv is deployed on the `v1` branch at `https://arkenv-v1.vercel.app/tanstack/info.json`. Because production docs (`https://arkenv.js.org`) are deployed from `main` (which flows from `dev`), this rewrite allows `https://arkenv.js.org/tanstack/info.json` to resolve immediately during the alpha prerelease phase without URL rot or waiting for the full v1 merge. Once merged to `dev`, this change can be synced directly to `main` via `sync-main.yml` (Category 1 doc/infra sync). **Blocks / Relates to:** #1811 (feat: add official TanStack CLI add-on for ArkEnv) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
…te drift in compile tests
…tor defaults in changeset
Review Feedback Addressed
|
|
@pullfrog review |
|

Important
Blocked by #1812: To ensure the canonical URL
https://arkenv.js.org/tanstack/info.jsonresolves in the documentation quickstart commands, #1812 must be merged intodevand synced tomain(gh workflow run sync-main.yml --ref dev) so production proxies/tanstack/*tohttps://arkenv-v1.vercel.app/tanstack/*.Summary
This PR adds the official TanStack CLI add-on for ArkEnv (
@arkenv/tanstack-addon), enabling developers to scaffold typesafe environment variable validation in TanStack Start applications viatanstack create my-app --add-ons https://arkenv.js.org/tanstack/info.jsonortanstack add ....Key Features
packages/tanstack-addon):.add-on/info.jsonprompting for validator choice:@arkenv/coreandarktype)@arkenv/standardandzod)@arkenv/standardandvalibot)package.json.ejsinjecting validator runtime dependencies and@arkenv/vite-plugindevDependencies aligned withRELEASE_CONFIG.src/env.ts.ejstemplate with fallback matching for remote add-on option IDs (addOnOption[url]vsaddOnOption['arkenv']).src/routes/demo/arkenv.tsxshowcasing server-only variable protection increateServerFn, inlined publicVITE_variables on the client, and an interactive leak button triggering ArkEnv's throwing getter boundary error..env.examplepre-populated with declared schema keys.scripts/build.ts):dist/info.jsonanddist/add-on.json) conforming to@tanstack/create'sAddOnCompiledSchema.apps/www/public/tanstack/for CDN distribution athttps://arkenv.js.org/tanstack/info.json.apps/www/content/docs/frameworks/tanstack-start.mdxwith quickstart instructions using TanStack CLI..changeset/tanstack-addon.mdwith a minor bump for@arkenv/tanstack-addon.Verification
packages/tanstack-addon/tests/compile.test.ts: validated bundle against@tanstack/create'sAddOnCompiledSchema.packages/tanstack-addon/tests/templates.test.ts: 10 test cases verifying EJS rendering for ArkType, Zod, Valibot, and URL-based option keys.apps/www/lib/package-install-fences.test.ts: verified remark-npm package-install compliance.pnpm biome check packages/tanstack-addon: clean (0 errors, 0 warnings).pnpm run check:mdx: 132 files checked, 0 errors.pnpm manypkg check: workspaces valid.pnpm typecheck: 32/32 Turbo tasks passed.pnpm test -- --run: 161/161 test files passed (1,359 tests passed).pnpm --filter www build: Next.js production build succeeded (108 static pages generated).