From cc22c9c16c7afb8320e40a56c6cbb4e5399bcc82 Mon Sep 17 00:00:00 2001 From: wyMinLwin Date: Sun, 12 Apr 2026 00:23:52 +0700 Subject: [PATCH 1/2] fix(create): generate minimal scaffolding when declining demo/example pages --- .../base/src/components/Footer.tsx.ejs | 1 + .../base/src/components/Header.tsx.ejs | 1 + .../base/src/components/ThemeToggle.tsx.ejs | 1 + .../project/base/src/routes/__root.tsx.ejs | 93 +++++++++++++++++++ .../project/base/src/routes/about.tsx.ejs | 1 + .../project/base/src/routes/index.tsx.ejs | 17 ++++ .../react/project/base/src/styles.css.ejs | 18 ++++ .../base/src/components/Header.tsx.ejs | 1 + .../project/base/src/routes/__root.tsx.ejs | 45 +++++++++ .../project/base/src/routes/about.tsx.ejs | 1 + .../project/base/src/routes/index.tsx.ejs | 17 ++++ .../solid/project/base/src/styles.css.ejs | 18 ++++ packages/create/src/template-file.ts | 1 + .../create/tests/template-context.test.ts | 63 +++++++++++++ 14 files changed, 278 insertions(+) diff --git a/packages/create/src/frameworks/react/project/base/src/components/Footer.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/components/Footer.tsx.ejs index 6156f908..f70e476b 100644 --- a/packages/create/src/frameworks/react/project/base/src/components/Footer.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/components/Footer.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> export default function Footer() { const year = new Date().getFullYear() diff --git a/packages/create/src/frameworks/react/project/base/src/components/Header.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/components/Header.tsx.ejs index f83a81c8..a6f3ed44 100644 --- a/packages/create/src/frameworks/react/project/base/src/components/Header.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/components/Header.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> import { Link } from '@tanstack/react-router' <% for (const integration of integrations.filter((i) => i.type === 'header-user')) { %>import <%= integration.jsName %> from '<%= relativePath(integration.path) %>' <% } %>import ThemeToggle from './ThemeToggle' diff --git a/packages/create/src/frameworks/react/project/base/src/components/ThemeToggle.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/components/ThemeToggle.tsx.ejs index 081ebe2b..61b6d82f 100644 --- a/packages/create/src/frameworks/react/project/base/src/components/ThemeToggle.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/components/ThemeToggle.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> import { useEffect, useState } from 'react' type ThemeMode = 'light' | 'dark' | 'auto' diff --git a/packages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejs index 22abf72c..2b3098ad 100644 --- a/packages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/routes/__root.tsx.ejs @@ -27,6 +27,99 @@ function RootComponent() { ) } +<% } else if (!includeExamples) { %> +<% let hasContext = addOnEnabled["apollo-client"] || addOnEnabled["tanstack-query"]; %> +import { + HeadContent, Scripts, <% if (hasContext) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %> } from '@tanstack/react-router' +import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; +import { TanStackDevtools } from '@tanstack/react-devtools' +<% for(const integration of integrations.filter(i => i.type === 'layout' || i.type === 'provider' || i.type === 'devtools')) { %> +import <%= integration.jsName %> from '<%= relativePath(integration.path, true) %>' +<% } %><% if (addOnEnabled.paraglide) { %> +import { getLocale } from '#/paraglide/runtime' +<% } %> +import appCss from '../styles.css?url' +<% if (addOnEnabled["apollo-client"]) { %> +import type { ApolloClientIntegration } from "@apollo/client-integration-tanstack-start"; +<% } %> +<% if (addOnEnabled["tanstack-query"]) { %> +import type { QueryClient } from '@tanstack/react-query' +<% if (addOnEnabled.tRPC) { %> +import type { TRPCRouter } from '#/integrations/trpc/router' +import type { TRPCOptionsProxy } from '@trpc/tanstack-react-query' +<% } %> +<% } %> +<% if (hasContext) { %> +interface MyRouterContext <% if (addOnEnabled["apollo-client"]) {%> extends ApolloClientIntegration.RouterContext <%} %>{ +<% if (addOnEnabled["tanstack-query"]) { %> + queryClient: QueryClient + <% if (addOnEnabled.tRPC) { %> + trpc: TRPCOptionsProxy + <% } %> +<% } %> +}<% } %> + +export const Route = <% if (hasContext) { %>createRootRouteWithContext()<% } else { %>createRootRoute<% } %>({ +<% if (addOnEnabled.paraglide) { %> + beforeLoad: async () => { + // Other redirect strategies are possible; see + // https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide#offline-redirect + if (typeof document !== 'undefined') { + document.documentElement.setAttribute('lang', getLocale()) + } + }, +<% } %> + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack Start Starter', + }, + ], + links: [ + { + rel: 'stylesheet', + href: appCss, + }, + ], + }), + shellComponent: RootDocument +}) + +function RootDocument({ children }: { children: React.ReactNode }) { + return ( + <% if (addOnEnabled.paraglide) { %><% } else { %><% } %> + + + + + <% for(const integration of integrations.filter(i => i.type === 'provider')) { %><<%= integration.jsName %>> + <% } %>{children} + , + }, + <% for(const integration of integrations.filter(i => i.type === 'devtools')) { %><%= integration.jsName %>,<% } %> + ]} + /> + <% for(const integration of integrations.filter(i => i.type === 'layout')) { %><<%= integration.jsName %> /> + <% } %><% for(const integration of integrations.filter(i => i.type === 'provider').reverse()) { %>> + <% } %> + + + ) +} <% } else { %> <% let hasContext = addOnEnabled["apollo-client"] || addOnEnabled["tanstack-query"]; %> import { diff --git a/packages/create/src/frameworks/react/project/base/src/routes/about.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/routes/about.tsx.ejs index 68b82b55..ee76e3fe 100644 --- a/packages/create/src/frameworks/react/project/base/src/routes/about.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/routes/about.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/about')({ diff --git a/packages/create/src/frameworks/react/project/base/src/routes/index.tsx.ejs b/packages/create/src/frameworks/react/project/base/src/routes/index.tsx.ejs index 21754f74..7dd740be 100644 --- a/packages/create/src/frameworks/react/project/base/src/routes/index.tsx.ejs +++ b/packages/create/src/frameworks/react/project/base/src/routes/index.tsx.ejs @@ -1,3 +1,19 @@ +<% if (!includeExamples) { %> +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/")({ component: Home }); + +function Home() { + return ( +
+

Welcome to TanStack Start

+

+ Edit src/routes/index.tsx to get started. +

+
+ ); +} +<% } else { %> import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/")({ component: App }); @@ -70,3 +86,4 @@ function App() { ); } +<% } %> diff --git a/packages/create/src/frameworks/react/project/base/src/styles.css.ejs b/packages/create/src/frameworks/react/project/base/src/styles.css.ejs index 498b4c53..559f0e80 100644 --- a/packages/create/src/frameworks/react/project/base/src/styles.css.ejs +++ b/packages/create/src/frameworks/react/project/base/src/styles.css.ejs @@ -1,3 +1,20 @@ +<% if (!includeExamples) { %> +@import "tailwindcss"; + +* { + box-sizing: border-box; +} + +html, +body, +#app { + min-height: 100%; +} + +body { + margin: 0; +} +<% } else { %> @import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Manrope:wght@400;500;600;700;800&display=swap"); @import "tailwindcss"; @plugin "@tailwindcss/typography"; @@ -257,3 +274,4 @@ a { transform: translateY(0); } } +<% } %> diff --git a/packages/create/src/frameworks/solid/project/base/src/components/Header.tsx.ejs b/packages/create/src/frameworks/solid/project/base/src/components/Header.tsx.ejs index 85ec43d9..e91489d8 100644 --- a/packages/create/src/frameworks/solid/project/base/src/components/Header.tsx.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/components/Header.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> import { Link } from '@tanstack/solid-router' <% for(const integration of integrations.filter(i => i.type === 'header-user')) { %> import <%= integration.jsName %> from '<%= relativePath(integration.path) %>' diff --git a/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs b/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs index e8f730c2..3fbd4358 100644 --- a/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs @@ -16,6 +16,51 @@ function RootComponent() { ) } +<% } else if (!includeExamples) { %> +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"; + +export const Route = createRootRouteWithContext()({ + head: () => ({ + links: [{ rel: "stylesheet", href: styleCss }], + }), + shellComponent: RootComponent, +}) + +function RootComponent() { + return ( + + + + + + + + + + <% for(const integration of integrations.filter(i => i.type === 'layout')) { %> + <<%= integration.jsName %> /> + <% } %> + + + + + ); +} <% } else { %> import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from '@tanstack/solid-router' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' diff --git a/packages/create/src/frameworks/solid/project/base/src/routes/about.tsx.ejs b/packages/create/src/frameworks/solid/project/base/src/routes/about.tsx.ejs index 48d300de..60072ee9 100644 --- a/packages/create/src/frameworks/solid/project/base/src/routes/about.tsx.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/routes/about.tsx.ejs @@ -1,3 +1,4 @@ +<% if (!includeExamples) { ignoreFile(); return; } %> import { createFileRoute } from '@tanstack/solid-router' export const Route = createFileRoute('/about')({ diff --git a/packages/create/src/frameworks/solid/project/base/src/routes/index.tsx.ejs b/packages/create/src/frameworks/solid/project/base/src/routes/index.tsx.ejs index 5d1367b3..dc0e5446 100644 --- a/packages/create/src/frameworks/solid/project/base/src/routes/index.tsx.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/routes/index.tsx.ejs @@ -1,3 +1,19 @@ +<% if (!includeExamples) { %> +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/')({ component: Home }) + +function Home() { + return ( +
+

Welcome to TanStack Start

+

+ Edit src/routes/index.tsx to get started. +

+
+ ) +} +<% } else { %> import { createFileRoute } from '@tanstack/solid-router' export const Route = createFileRoute('/')({ component: App }) @@ -66,3 +82,4 @@ function App() { ) } +<% } %> diff --git a/packages/create/src/frameworks/solid/project/base/src/styles.css.ejs b/packages/create/src/frameworks/solid/project/base/src/styles.css.ejs index a1952e4a..34fd84bb 100644 --- a/packages/create/src/frameworks/solid/project/base/src/styles.css.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/styles.css.ejs @@ -1,3 +1,20 @@ +<% if (!includeExamples) { %> +@import 'tailwindcss'; + +* { + box-sizing: border-box; +} + +html, +body, +#app { + min-height: 100%; +} + +body { + margin: 0; +} +<% } else { %> @import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Manrope:wght@400;500;600;700;800&display=swap'); @import 'tailwindcss'; @@ -193,3 +210,4 @@ code { transform: translateY(0); } } +<% } %> diff --git a/packages/create/src/template-file.ts b/packages/create/src/template-file.ts index dfd62236..520a4d23 100644 --- a/packages/create/src/template-file.ts +++ b/packages/create/src/template-file.ts @@ -137,6 +137,7 @@ export function createTemplateFile(environment: Environment, options: Options) { fileRouter: options.mode === 'file-router', codeRouter: options.mode === 'code-router', routerOnly: options.routerOnly === true, + includeExamples: options.includeExamples !== false, addOnEnabled, addOnOption: options.addOnOptions, addOns: options.chosenAddOns, diff --git a/packages/create/tests/template-context.test.ts b/packages/create/tests/template-context.test.ts index 6d08c8d8..4c31cff6 100644 --- a/packages/create/tests/template-context.test.ts +++ b/packages/create/tests/template-context.test.ts @@ -311,4 +311,67 @@ export const db = testAddon(/* connection */)` expect(output.files['/test/src/db/__sqlite__index.ts']).toBeUndefined() expect(output.files['/test/src/db/__postgres__index.ts']).toBeUndefined() }) +}) + +describe('Template Context - includeExamples', () => { + it('should default includeExamples to true when undefined', async () => { + const { environment, output } = createMemoryEnvironment() + const templateFile = createTemplateFile(environment, simpleOptions) + environment.startRun() + await templateFile( + 'test.txt.ejs', + '<%= includeExamples ? "with-examples" : "no-examples" %>', + ) + environment.finishRun() + + expect(output.files['/test/test.txt']).toEqual('with-examples') + }) + + it('should set includeExamples to false when options.includeExamples is false', async () => { + const { environment, output } = createMemoryEnvironment() + const templateFile = createTemplateFile(environment, { + ...simpleOptions, + includeExamples: false, + }) + environment.startRun() + await templateFile( + 'test.txt.ejs', + '<%= includeExamples ? "with-examples" : "no-examples" %>', + ) + environment.finishRun() + + expect(output.files['/test/test.txt']).toEqual('no-examples') + }) + + it('should ignore files when includeExamples is false', async () => { + const { environment, output } = createMemoryEnvironment() + const templateFile = createTemplateFile(environment, { + ...simpleOptions, + includeExamples: false, + }) + environment.startRun() + await templateFile( + 'about.ts.ejs', + '<% if (!includeExamples) { ignoreFile(); return; } %>\nexport const about = true', + ) + environment.finishRun() + + expect(output.files['/test/about.ts']).toBeUndefined() + }) + + it('should include files when includeExamples is true', async () => { + const { environment, output } = createMemoryEnvironment() + const templateFile = createTemplateFile(environment, { + ...simpleOptions, + includeExamples: true, + }) + environment.startRun() + await templateFile( + 'about.ts.ejs', + '<% if (!includeExamples) { ignoreFile(); return; } %>\nexport const about = true', + ) + environment.finishRun() + + expect(output.files['/test/about.ts']).toBeDefined() + }) }) \ No newline at end of file From 7f2732f7cc6fb242520418e0e96f3a562faa1787 Mon Sep 17 00:00:00 2001 From: wyMinLwin Date: Sun, 12 Apr 2026 01:32:41 +0700 Subject: [PATCH 2/2] fix(create): move HeadContent to head block in Solid root template --- .../frameworks/solid/project/base/src/routes/__root.tsx.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs b/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs index 3fbd4358..949f34df 100644 --- a/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs +++ b/packages/create/src/frameworks/solid/project/base/src/routes/__root.tsx.ejs @@ -46,9 +46,9 @@ function RootComponent() { + - @@ -92,9 +92,9 @@ function RootComponent() { + -