170- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
171- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
172- **React Configuration:** When using React libraries, pin versions with `?deps=react@18.2.0,react-dom@18.2.0` and start the file with `/** @jsxImportSource https://esm.sh/react@18.2.0 */`
173- Ensure all React dependencies and sub-dependencies are pinned to the same version
174- **Styling:** Default to using TailwindCSS via `<script src="https://cdn.twind.style" crossorigin></script>` unless otherwise specified
175
257 - Always run table creation before querying
258
2593. **React Configuration:**
260 - All React dependencies must be pinned to 18.2.0
261 - Always include `@jsxImportSource https://esm.sh/react@18.2.0` at the top of React files
262 - Rendering issues often come from mismatched React versions
263
2644. **File Handling:**
180- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
181- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
182- **React Configuration:** When using React libraries, pin versions with `?deps=react@18.2.0,react-dom@18.2.0` and start the file with `/** @jsxImportSource https://esm.sh/react@18.2.0 */`
183- Ensure all React dependencies and sub-dependencies are pinned to the same version
184- **Styling:** Default to using TailwindCSS via `<script src="https://cdn.twind.style" crossorigin></script>` unless otherwise specified
185
266 - Always run table creation before querying
267
2683. **React Configuration:**
269 - All React dependencies must be pinned to 18.2.0
270 - Always include `@jsxImportSource https://esm.sh/react@18.2.0` at the top of React files
271 - Rendering issues often come from mismatched React versions
272
2734. **File Handling:**
42* Use Deno.env.get('keyname') for environment variables
43* Import npm/deno dependencies via https://esm.sh
44* When using React, pin to version 18.2.0 with ?deps=react@18.2.0,react-dom@18.2.0
45```
46
46 If needed and if the user asks for something that requires persistence, use Val Town SQLite or Blob storage. Use the val's `import.meta.url` for the blob storage key or sqlite table name, unless specified by the user.
47
48 * If you use any React library, use esm.sh and pin its React version to 18.2.0 and its ReactDOM version to 18.2.0 by adding `?deps=react@18.2.0,react-dom@18.2.0` to the end of the URL. If the user is facing a client-side error where nothing is being rendered, check if all React dependencies and sub-dependencies are pinned to the same version, including the @jsxImportSource pragma.
49</requirements>
50
148```val type=http
149/** Use this template when you create http vals only */
150/** @jsxImportSource https://esm.sh/react@18.2.0 */
151import React from "https://esm.sh/react@18.2.0";
152import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
153
154/**
113- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
114- For persistence, use Val Town SQLite or Blob storage with `import.meta.url` for keys/table names
115- **React Configuration:** When using React libraries, pin versions with `?deps=react@18.2.0,react-dom@18.2.0` and include the `@jsxImportSource` pragma
116- When facing client-side render issues, check if all React dependencies are pinned to the same version
117- **Styling:** Default to using TailwindCSS via `<script src="https://cdn.twind.style" crossorigin></script>`, use dark and light themes, unless otherwise specified
118
226
227### Frontend Best Practices
228- Structure as a standard client-side React app
229- Use SVG for favicons (Val Town only supports text files)
230- Separate components into individual files
231- Access bootstrapped data from `window.__INITIAL_DATA__`
232- Use React 18.2.0 consistently in all imports and the `@jsxImportSource` pragma
233- Follow the React component pattern from the example project
234- Handle API calls properly with proper error catching
235
253 - Always run table creation before querying
254
2553. **React Configuration:**
256 - All React dependencies must be pinned to 18.2.0
257 - Always include `@jsxImportSource https://esm.sh/react@18.2.0` at the top of React files
258 - Rendering issues often come from mismatched React versions
259
2604. **File Handling:**
1/** @jsxImportSource https://esm.sh/react@19 */
2import React from "https://esm.sh/react@19";
3import {
4 RootRoute,
7 createRouter,
8 RouterProvider,
9} from "https://esm.sh/@tanstack/react-router@^1.121.0?deps=react@19";
10import {
11 QueryClient,
12 QueryClientProvider,
13} from "https://esm.sh/@tanstack/react-query@^5.0.0?deps=react@19";
14import { App } from "./components/App.tsx";
15
59
60// Register the router for TypeScript
61declare module "@tanstack/react-router" {
62 interface Register {
63 router: typeof router;
1# React + TanStack + Hono Val Town Project
2
3Full-stack message board built for Val Town.
11
12### Frontend
13- React 19
14- TanStack Router (code-first routing)
15- TanStack Query (server state management)
31โ โโโ database/ # Drizzle schema, migrations, and queries
32โ โโโ index.ts # Main Hono application
33โโโ frontend/ # React app running in browser
34โ โโโ components/ # React components
35โ โโโ lib/ # Utilities and hooks
36โ โโโ router.tsx # TanStack Router configuration
40## API Endpoints
41
42- `GET /` - Serves the React application with initial data
43- `GET /api/messages` - Fetch all messages (JSON)
44- `POST /api/messages` - Create a new message
1# Frontend
2
3This template is a classic client-side-only React app.
4
5## `index.html`
9This HTML file imports `/frontend/style.css` from `/public/style.css` and `/frontend/favicon.svg` from `/frontend/favicon.svg`. Everything in `/frontend/` is mapped to `/public` by `/backend/index.ts`. This is just a convention. You could import & serve everything out of the same folder name.
10
11This HTML file has a `<div id="root"></div>`, which is where we mount the React app.
12
13This HTML file imports `/frontend/index.tsx` from `/public/index.tsx`, which is the **entrypoint** for all frontend JavaScript, including all the React. It is not a problem that it imports a file with a `.tsx` extension becaues browsers ignore file extensions. They only pay attention to content-types, which is great, because all these files will be returned as transpiled JS with the appropriate JS content type by [stevekrouse/utils/serve-public](https://www.val.town/x/stevekrouse/utils/branch/main/code/serve-public/README.md).)
14
15## `index.tsx`
16
17This file is the **entrypoint** for frontend JavaScript. It imports the React app from `/frontend/components/App.tsx` and mounts it on `<div id="root"></div>`.
18
19It also looks for *bootstrapped* JSON data at `window.__INITIAL_DATA`, and passes that only to the `<App />`.
25## `components/`
26
27This directory is where the React components are stored. They're pretty standard client-side React components.
12## Serving assets to the frontend
13
14This backend HTTP server is responsible for serving all static assets to the browser to render the app, including HTML, JavaScript (including all client-side React), CSS, and even the favicon SVG.
15
16In a normal server environment, you would likely use a middleware [like this one](https://hono.dev/docs/getting-started/nodejs#serve-static-files) to serve static files. Some frameworks or deployment platforms automatically make any content inside a `public/` folder public.
26## CRUD API Routes
27
28This app has two CRUD API routes: for reading and inserting into the messages table. They both speak JSON, which is standard. They import their functions from `/backend/database/queries.ts`. These routes are called from the React app to refresh and update data.
29
30## Errors
8## Migrations
9
10In `backend/database/migrations.ts`, this app creates a new SQLite table `reactHonoStarter_messages` to store messages.
11
12This "migration" runs once on every app startup because it's imported in `index.ts`. You can comment this line out for a slight (30ms) performance improvement on cold starts. It's left in so that users who fork this project will have the migration run correctly.