fix(create): strip all demo/example files when users opt out#434
fix(create): strip all demo/example files when users opt out#434tannerlinsley merged 5 commits intomainfrom
Conversation
…hen demo is disabled Previously only demo route files were filtered out when the user chose no demo files. Demo files in components/, lib/, hooks/, and data/ directories would still be created. Rename isDemoRoutePath to isDemoFilePath to reflect the broader scope and extend pattern matching to cover all non-route demo file paths.
…disabled The better-auth header-user components reference the /demo/better-auth route, which doesn't exist when users opt out of demo files. Convert these to EJS templates with conditional rendering so they return null instead of linking to a non-existent route. Also extend isDemoFilePath filtering to cover add-on integration files (previously only routes, lib, hooks, data, and components were filtered in a037c4d).
The directory-specific filter missed demo support files in /store/, /public/, at src root (demo.index.css), and example assets (example-guitar-*.jpg). Replace directory-specific checks with a filename-prefix match so any file named demo.*, demo-*, example.*, or example-* gets stripped when users opt out of demo pages, regardless of which directory it lives in. Add a regression test that exercises demo files across lib, hooks, data, components, store, public, and routes.
📝 WalkthroughWalkthroughThis diff implements a minimal starter template for new TanStack Start projects when users decline demo/example pages. It introduces an Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/create/src/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx.ejs (1)
2-4: Deduplicate the demo-route predicate in template scope.The same
routes.some(...)check appears twice. Consider computing it once to prevent future branch drift.♻️ Optional cleanup
+<%_ const hasDemoBetterAuthRoute = routes.some((r) => r.url === '/demo/better-auth') _%> -<%_ if (routes.some(r => r.url === '/demo/better-auth')) { _%> +<%_ if (hasDemoBetterAuthRoute) { _%> import { Link } from "@tanstack/react-router"; <%_ } _%> @@ -<%_ if (routes.some(r => r.url === '/demo/better-auth')) { _%> +<%_ if (hasDemoBetterAuthRoute) { _%> return ( <Link to="/demo/better-auth"Also applies to: 39-50
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/create/src/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx.ejs` around lines 2 - 4, Compute the demo-route predicate once and reuse it instead of repeating routes.some(r => r.url === '/demo/better-auth') in the template; e.g., define a local variable like hasDemoRoute = routes.some(r => r.url === '/demo/better-auth') at the top of header-user.tsx.ejs and replace both conditional occurrences with hasDemoRoute to avoid duplicate logic and future drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/create/src/create-app.ts`:
- Around line 48-52: filteredRoutes currently filters out demo routes using
isDemoFilePath and checking route.url.startsWith('/demo'), but it misses routes
with URLs under '/example'; update the filter predicate used when building
filteredRoutes (and any related stripExamplesFromOptions logic) to also exclude
route.url that startsWith('/example') (in addition to '/demo') so addOn.routes
entries with route.url like '/example/...' are removed when examples are
disabled; reference the filteredRoutes variable, addOn.routes, isDemoFilePath,
and route.url when making the change.
In `@packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs`:
- Around line 20-35: The template renders layout integration components (<%=
integration.jsName %>) in the no-examples branch but never imports them; add an
import loop near the top (after existing imports like
createRootRouteWithContext/HydrationScript) that iterates over addOns and their
layout integrations and emits import statements for each integration (using
integration.jsName) so the components referenced in the !includeExamples block
are resolved at compile time.
---
Nitpick comments:
In
`@packages/create/src/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx.ejs`:
- Around line 2-4: Compute the demo-route predicate once and reuse it instead of
repeating routes.some(r => r.url === '/demo/better-auth') in the template; e.g.,
define a local variable like hasDemoRoute = routes.some(r => r.url ===
'/demo/better-auth') at the top of header-user.tsx.ejs and replace both
conditional occurrences with hasDemoRoute to avoid duplicate logic and future
drift.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4b2b9e94-73b5-401f-bacf-f7c622e88510
📒 Files selected for processing (19)
.changeset/fix-demo-file-leaks.mdpackages/create/src/create-app.tspackages/create/src/frameworks/react/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx.ejspackages/create/src/frameworks/react/project/base/src/components/Footer.tsx.ejspackages/create/src/frameworks/react/project/base/src/components/Header.tsx.ejspackages/create/src/frameworks/react/project/base/src/components/ThemeToggle.tsx.ejspackages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejspackages/create/src/frameworks/react/project/base/src/routes/about.tsx.ejspackages/create/src/frameworks/react/project/base/src/routes/index.tsx.ejspackages/create/src/frameworks/react/project/base/src/styles.css.ejspackages/create/src/frameworks/solid/add-ons/better-auth/assets/src/integrations/better-auth/header-user.tsx.ejspackages/create/src/frameworks/solid/project/base/src/components/Header.tsx.ejspackages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejspackages/create/src/frameworks/solid/project/base/src/routes/about.tsx.ejspackages/create/src/frameworks/solid/project/base/src/routes/index.tsx.ejspackages/create/src/frameworks/solid/project/base/src/styles.css.ejspackages/create/src/template-file.tspackages/create/tests/create-app.test.tspackages/create/tests/template-context.test.ts
| const filteredRoutes = (addOn.routes || []).filter( | ||
| (route) => | ||
| !isDemoRoutePath(route.path) && | ||
| !isDemoFilePath(route.path) && | ||
| !(route.url && route.url.startsWith('/demo')), | ||
| ) |
There was a problem hiding this comment.
Also filter /example route URLs when examples are disabled.
stripExamplesFromOptions currently removes URLs prefixed with /demo only. Routes with route.url like /example/... can still pass through in code-router-style add-ons.
Suggested fix
const filteredRoutes = (addOn.routes || []).filter(
(route) =>
!isDemoFilePath(route.path) &&
- !(route.url && route.url.startsWith('/demo')),
+ !(
+ route.url &&
+ (route.url.startsWith('/demo') || route.url.startsWith('/example'))
+ ),
)📝 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.
| const filteredRoutes = (addOn.routes || []).filter( | |
| (route) => | |
| !isDemoRoutePath(route.path) && | |
| !isDemoFilePath(route.path) && | |
| !(route.url && route.url.startsWith('/demo')), | |
| ) | |
| const filteredRoutes = (addOn.routes || []).filter( | |
| (route) => | |
| !isDemoFilePath(route.path) && | |
| !( | |
| route.url && | |
| (route.url.startsWith('/demo') || route.url.startsWith('/example')) | |
| ), | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/create/src/create-app.ts` around lines 48 - 52, filteredRoutes
currently filters out demo routes using isDemoFilePath and checking
route.url.startsWith('/demo'), but it misses routes with URLs under '/example';
update the filter predicate used when building filteredRoutes (and any related
stripExamplesFromOptions logic) to also exclude route.url that
startsWith('/example') (in addition to '/demo') so addOn.routes entries with
route.url like '/example/...' are removed when examples are disabled; reference
the filteredRoutes variable, addOn.routes, isDemoFilePath, and route.url when
making the change.
| import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from '@tanstack/solid-router' | ||
| import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' | ||
| <% if (addOnEnabled['solid-ui']) { %> | ||
| import "@fontsource/inter/400.css" | ||
| <% } %> | ||
| import { HydrationScript } from 'solid-js/web' | ||
| import { Suspense } from 'solid-js' | ||
| <% for(const addOn of addOns) { | ||
| for(const init of addOn.main?.initialize || []) { %> | ||
| <%- init %> | ||
| <% } } %> | ||
| import styleCss from "../styles.css?url"; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Solid no-examples root branch =="
sed -n '19,63p' packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs
echo
echo "== Integration definitions that may be rendered here =="
rg -n -C2 --glob '*.ts' --glob '*.js' 'type\s*:\s*["'"'"'](layout|provider|devtools)["'"'"']|integrations\s*:' .
echo
echo "== React root import pattern for comparison =="
sed -n '30,45p' packages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejsRepository: TanStack/cli
Length of output: 5568
Add missing import loop for layout integrations in the no-examples branch.
The !includeExamples branch at lines 55–57 renders <%= integration.jsName %> for layout integrations but never imports them. Generated projects with Solid layout integrations will fail to compile with unresolved component references. The React root template correctly handles this pattern by importing integrations before use.
Add an import loop after line 17:
import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'
<% if (addOnEnabled['solid-ui']) { %>
import "@fontsource/inter/400.css"
<% } %>
+<% for(const integration of integrations.filter(i => i.type === 'layout')) { %>
+import <%= integration.jsName %> from '<%= relativePath(integration.path, true) %>'
+<% } %>
+
import { HydrationScript } from 'solid-js/web'📝 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.
| import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from '@tanstack/solid-router' | |
| import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' | |
| <% if (addOnEnabled['solid-ui']) { %> | |
| import "@fontsource/inter/400.css" | |
| <% } %> | |
| import { HydrationScript } from 'solid-js/web' | |
| import { Suspense } from 'solid-js' | |
| <% for(const addOn of addOns) { | |
| for(const init of addOn.main?.initialize || []) { %> | |
| <%- init %> | |
| <% } } %> | |
| import styleCss from "../styles.css?url"; | |
| import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from '@tanstack/solid-router' | |
| import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' | |
| <% if (addOnEnabled['solid-ui']) { %> | |
| import "@fontsource/inter/400.css" | |
| <% } %> | |
| <% for(const integration of integrations.filter(i => i.type === 'layout')) { %> | |
| import <%= integration.jsName %> from '<%= relativePath(integration.path, true) %>' | |
| <% } %> | |
| import { HydrationScript } from 'solid-js/web' | |
| import { Suspense } from 'solid-js' | |
| <% for(const addOn of addOns) { | |
| for(const init of addOn.main?.initialize || []) { %> | |
| <%- init %> | |
| <% } } %> | |
| import styleCss from "../styles.css?url"; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs`
around lines 20 - 35, The template renders layout integration components (<%=
integration.jsName %>) in the no-examples branch but never imports them; add an
import loop near the top (after existing imports like
createRootRouteWithContext/HydrationScript) that iterates over addOns and their
layout integrations and emits import statements for each integration (using
integration.jsName) so the components referenced in the !includeExamples block
are resolved at compile time.
Summary
Closes #422 and #409 — when users select "No" for "Would you like to include demo/example pages?", a lot of demo boilerplate was still getting scaffolded.
This PR combines the work from @WaryaWayne (#431) and @wyMinLwin (#429) into a single unified fix, plus additional coverage for edge cases they missed. Both original commits are preserved with author credit.
What was leaking through
The previous filter only matched files under
/routes/demo/or/routes/demo.*. Demo support files in/lib/,/hooks/,/data/,/components/,/store/, at thesrc/root (demo.index.css), and example assets in/public/(example-guitar-*.jpg,demo-neon.svg) were all being copied into new projects with no routes referencing them. On top of that, the base scaffolding always shipped aHeader,Footer,ThemeToggle, styled landing page, and About route — even when the user wanted a minimal starter.Fixes
From @WaryaWayne's #431:
isDemoRoutePath→isDemoFilePathand expand it to cover support files inlib,hooks,data,componentsintegrations(not just routes and files)nullwhen its demo route is excluded, instead of linking to a non-existent routeFrom @wyMinLwin's #429:
includeExamplesinto the template contextHeader,Footer,ThemeToggle,Aboutroute, styledindexroute, and styles when demo pages are disabledAdditional cleanup I layered on top:
demo.,demo-,example., orexample-gets stripped, regardless of which directory it lives in. This catches the/store/demo.*,/public/example-*, andsrc/demo.index.csscases the original approach missed.lib,hooks,data,components,store,public, androutes.Test plan
pnpm --filter @tanstack/create test(194 passed)pnpm --filter @tanstack/cli test(84 passed)pnpm --filter @tanstack/cli test:e2e(3 passed — create, solid, addons)tanstack create ... --no-examples --add-ons=ai,form,table,store,db,tanstack-queryproduces a project with nodemo*/example*files insrc/orpublic/, and no Header/Footer/ThemeToggle in the base scaffoldingtanstack create ... --examples --add-ons=tanstack-querykeeps Header/Footer/ThemeToggle and demo routesCo-authored-by: Abdullahi Mohamed 126521894+WaryaWayne@users.noreply.github.com
Co-authored-by: wyMinLwin waiyanminlwin421@gmail.com
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes