Skip to content

Commit 25e18c1

Browse files
committed
chore: refresh the starters
1 parent 97baf88 commit 25e18c1

File tree

136 files changed

+3089
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+3089
-21
lines changed

examples/blog-starter/.cta.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"projectName": "blog-example",
3+
"targetDir": "/Users/jherr/projects/cta/new-examples/blog-example",
4+
"mode": "file-router",
5+
"typescript": true,
6+
"tailwind": true,
7+
"packageManager": "pnpm",
8+
"git": true,
9+
"version": 1,
10+
"framework": "react-cra",
11+
"existingAddOns": [
12+
"shadcn",
13+
"start"
14+
]
15+
}

examples/blog-starter/.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
6+
.output
7+
.vinxi
8+
.content-collections
6.81 MB
Loading

examples/blog-starter/README.md

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
Welcome to your new TanStack app!
2+
3+
# Getting Started
4+
5+
To run this application:
6+
7+
```bash
8+
pnpm install
9+
pnpm start
10+
```
11+
12+
# Building For Production
13+
14+
To build this application for production:
15+
16+
```bash
17+
pnpm build
18+
```
19+
20+
## Testing
21+
22+
This project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with:
23+
24+
```bash
25+
pnpm test
26+
```
27+
28+
## Styling
29+
30+
This project uses [Tailwind CSS](https://tailwindcss.com/) for styling.
31+
32+
33+
34+
## Shadcn
35+
36+
Add components using the latest version of [Shadcn](https://ui.shadcn.com/).
37+
38+
```bash
39+
pnpx shadcn@latest add button
40+
```
41+
42+
43+
44+
## Routing
45+
This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`.
46+
47+
### Adding A Route
48+
49+
To add a new route to your application just add another a new file in the `./src/routes` directory.
50+
51+
TanStack will automatically generate the content of the route file for you.
52+
53+
Now that you have two routes you can use a `Link` component to navigate between them.
54+
55+
### Adding Links
56+
57+
To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.
58+
59+
```tsx
60+
import { Link } from "@tanstack/react-router";
61+
```
62+
63+
Then anywhere in your JSX you can use it like so:
64+
65+
```tsx
66+
<Link to="/about">About</Link>
67+
```
68+
69+
This will create a link that will navigate to the `/about` route.
70+
71+
More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).
72+
73+
### Using A Layout
74+
75+
In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `<Outlet />` component.
76+
77+
Here is an example layout that includes a header:
78+
79+
```tsx
80+
import { Outlet, createRootRoute } from '@tanstack/react-router'
81+
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
82+
83+
import { Link } from "@tanstack/react-router";
84+
85+
export const Route = createRootRoute({
86+
component: () => (
87+
<>
88+
<header>
89+
<nav>
90+
<Link to="/">Home</Link>
91+
<Link to="/about">About</Link>
92+
</nav>
93+
</header>
94+
<Outlet />
95+
<TanStackRouterDevtools />
96+
</>
97+
),
98+
})
99+
```
100+
101+
The `<TanStackRouterDevtools />` component is not required so you can remove it if you don't want it in your layout.
102+
103+
More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).
104+
105+
106+
## Data Fetching
107+
108+
There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.
109+
110+
For example:
111+
112+
```tsx
113+
const peopleRoute = createRoute({
114+
getParentRoute: () => rootRoute,
115+
path: "/people",
116+
loader: async () => {
117+
const response = await fetch("https://swapi.dev/api/people");
118+
return response.json() as Promise<{
119+
results: {
120+
name: string;
121+
}[];
122+
}>;
123+
},
124+
component: () => {
125+
const data = peopleRoute.useLoaderData();
126+
return (
127+
<ul>
128+
{data.results.map((person) => (
129+
<li key={person.name}>{person.name}</li>
130+
))}
131+
</ul>
132+
);
133+
},
134+
});
135+
```
136+
137+
Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).
138+
139+
### React-Query
140+
141+
React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.
142+
143+
First add your dependencies:
144+
145+
```bash
146+
pnpm add @tanstack/react-query @tanstack/react-query-devtools
147+
```
148+
149+
Next we'll need to create a query client and provider. We recommend putting those in `main.tsx`.
150+
151+
```tsx
152+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
153+
154+
// ...
155+
156+
const queryClient = new QueryClient();
157+
158+
// ...
159+
160+
if (!rootElement.innerHTML) {
161+
const root = ReactDOM.createRoot(rootElement);
162+
163+
root.render(
164+
<QueryClientProvider client={queryClient}>
165+
<RouterProvider router={router} />
166+
</QueryClientProvider>
167+
);
168+
}
169+
```
170+
171+
You can also add TanStack Query Devtools to the root route (optional).
172+
173+
```tsx
174+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
175+
176+
const rootRoute = createRootRoute({
177+
component: () => (
178+
<>
179+
<Outlet />
180+
<ReactQueryDevtools buttonPosition="top-right" />
181+
<TanStackRouterDevtools />
182+
</>
183+
),
184+
});
185+
```
186+
187+
Now you can use `useQuery` to fetch your data.
188+
189+
```tsx
190+
import { useQuery } from "@tanstack/react-query";
191+
192+
import "./App.css";
193+
194+
function App() {
195+
const { data } = useQuery({
196+
queryKey: ["people"],
197+
queryFn: () =>
198+
fetch("https://swapi.dev/api/people")
199+
.then((res) => res.json())
200+
.then((data) => data.results as { name: string }[]),
201+
initialData: [],
202+
});
203+
204+
return (
205+
<div>
206+
<ul>
207+
{data.map((person) => (
208+
<li key={person.name}>{person.name}</li>
209+
))}
210+
</ul>
211+
</div>
212+
);
213+
}
214+
215+
export default App;
216+
```
217+
218+
You can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview).
219+
220+
## State Management
221+
222+
Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.
223+
224+
First you need to add TanStack Store as a dependency:
225+
226+
```bash
227+
pnpm add @tanstack/store
228+
```
229+
230+
Now let's create a simple counter in the `src/App.tsx` file as a demonstration.
231+
232+
```tsx
233+
import { useStore } from "@tanstack/react-store";
234+
import { Store } from "@tanstack/store";
235+
import "./App.css";
236+
237+
const countStore = new Store(0);
238+
239+
function App() {
240+
const count = useStore(countStore);
241+
return (
242+
<div>
243+
<button onClick={() => countStore.setState((n) => n + 1)}>
244+
Increment - {count}
245+
</button>
246+
</div>
247+
);
248+
}
249+
250+
export default App;
251+
```
252+
253+
One of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.
254+
255+
Let's check this out by doubling the count using derived state.
256+
257+
```tsx
258+
import { useStore } from "@tanstack/react-store";
259+
import { Store, Derived } from "@tanstack/store";
260+
import "./App.css";
261+
262+
const countStore = new Store(0);
263+
264+
const doubledStore = new Derived({
265+
fn: () => countStore.state * 2,
266+
deps: [countStore],
267+
});
268+
doubledStore.mount();
269+
270+
function App() {
271+
const count = useStore(countStore);
272+
const doubledCount = useStore(doubledStore);
273+
274+
return (
275+
<div>
276+
<button onClick={() => countStore.setState((n) => n + 1)}>
277+
Increment - {count}
278+
</button>
279+
<div>Doubled - {doubledCount}</div>
280+
</div>
281+
);
282+
}
283+
284+
export default App;
285+
```
286+
287+
We use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating.
288+
289+
Once we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook.
290+
291+
You can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest).
292+
293+
# Demo files
294+
295+
Files prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed.
296+
297+
# Learn More
298+
299+
You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).

examples/blog-starter/app.config.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import contentCollections from "@content-collections/vinxi";
2+
import { defineConfig } from "@tanstack/react-start/config";
3+
import viteTsConfigPaths from "vite-tsconfig-paths";
4+
import tailwindcss from "@tailwindcss/vite";
5+
6+
const config = defineConfig({
7+
tsr: {
8+
appDirectory: "src",
9+
},
10+
vite: {
11+
plugins: [
12+
contentCollections(),
13+
viteTsConfigPaths({
14+
projects: ["./tsconfig.json"],
15+
}),
16+
tailwindcss(),
17+
],
18+
},
19+
});
20+
21+
export default config;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { defineCollection, defineConfig } from "@content-collections/core";
2+
3+
const posts = defineCollection({
4+
name: "posts",
5+
directory: "content/posts",
6+
include: "**/*.md",
7+
schema: (z) => ({
8+
title: z.string(),
9+
summary: z.string(),
10+
categories: z.array(z.string()),
11+
slug: z.string().optional(),
12+
image: z.string(),
13+
date: z.string(),
14+
}),
15+
transform: async (doc) => {
16+
return {
17+
...doc,
18+
slug: doc.title
19+
.toLowerCase()
20+
.replace(".md", "")
21+
.replace(/[^\w-]+/g, "_"),
22+
};
23+
},
24+
});
25+
26+
export default defineConfig({
27+
collections: [posts],
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
date: 2025-03-01
3+
title: "Day At The Beach"
4+
summary: "Had a great day at the beach in Hawaii"
5+
categories:
6+
- Relaxing
7+
image: beach.jpg
8+
---
9+
10+
The morning sun painted the ocean in shimmering gold as I paddled out beyond the break, my surfboard gliding smoothly through the crystal-clear Hawaiian waters. The waves were perfect today - clean, consistent sets rolling in with just enough power to make things interesting without being intimidating. After catching several exhilarating rides, each one lasting what felt like an eternity, I found myself grinning from ear to ear, salt water dripping from my hair, and feeling completely in tune with the rhythm of the ocean.
11+
12+
After my surf session, I found the perfect spot on the warm sand to soak in the midday sun. The gentle trade winds carried the sweet scent of plumeria, while palm trees swayed overhead providing occasional patches of shade. I alternated between reading my book, taking refreshing dips in the turquoise water, and simply watching the parade of beach life unfold around me - children building sandcastles, paddleboarders gliding by in the distance, and sea turtles occasionally popping their heads above the surface. It was one of those perfect Hawaiian days that remind you why these islands are called paradise.

0 commit comments

Comments
 (0)