Search
Code1,917
/** @jsxImportSource https://esm.sh/react@18.2.0 *//** SSR-friendly doc page — receives pre-rendered HTML from the server. * No client-side markdown fetching or parsing needed. */import { useState, useEffect, useCallback } from "https://esm.sh/react@18.2.0";import { styled } from "../styled.ts";/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Client hydration entry for Landing page. All content is pre-rendered server-side. */import { hydrateRoot } from "https://esm.sh/react-dom@18.2.0/client";import { Landing } from "../../components/Landing.tsx";This project is a Val Town HTTP React/D3 visualization.- Keep `index.http.tsx` thin.- Keep Val Town server response and client bootstrapping in `index.http.tsx`.- Keep page composition in `App.tsx`.- Keep D3 imperative rendering, simulation, zoom, drag, and hover behavior inside top-level `ForceDirectedGraph.tsx`.- Keep React controls/details/legend/stats in pure top-level component files such as `GraphControls.tsx`, `GraphDetails.tsx`, `GraphLegend.tsx`, and `GraphStats.tsx`.- Do not move D3 selection, simulation, or DOM mutation logic into React panel components.## Important D3 And React RuleDo not store transient hover state in React if it causes the force simulation torebuild. React should own durable UI state such as filters, layout mode, labelmode, and clicked or keyboard-selected node/link details. D3 should own| --- | --- || **[`basic-html-starter`](https://www.val.town/x/templates/basic-html-starter)** *(you're here)* | Static HTML pages. Sprinkle of vanilla JS. No server-side rendering. || [`hono-jsx-starter`](https://www.val.town/x/templates/hono-jsx-starter) | Dynamic server-rendered HTML with JSX. API routes. No React, no SPA. || [`react-hono-starter`](https://www.val.town/x/templates/react-hono-starter) | Client-side React SPA with a Hono API backend. |/** @jsxImportSource https://esm.sh/react@18.2.0 */import { Hono } from "npm:hono";// Serve the client-side JS for hydrationapp.get("/client.js", async (c) => { return serveFile("./client.tsx", import.meta.url);}); </div> <script type="module" src="/client.js"></script> </body>This template is a classic client-side-only React app. This HTML file has a `<div id="root"></div>`, which is where we mount the React app.This 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).)This 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>`.This directory is where the React components are stored. They're pretty standard client-side React components.This 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.In 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. We *bootstrap* `index.html` with some initial data from the server, so that it gets dynamically injected JSON data without having to make another round-trip request to the server to get that data on the frontend. This is a common pattern for client-side rendered apps.This 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.# React + TanStack + Hono Val Town Project### Frontend- React 19- TanStack Router (code-first routing)- Message board with persistent storage- Client-side routing- Optimistic updates- Server-side data injection- Type-safe database operations│ └── index.ts # Main Hono application├── frontend/ # React app running in browser│ ├── components/ # React components│ ├── lib/ # Utilities and hooks- `GET /` - Serves the React application with initial data- `GET /api/messages` - Fetch all messages (JSON) onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["messages"] }); },/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Server-side rendering utility. * * Renders a React component to HTML string with styled-components CSS extraction. * Used by route handlers in main.ts / mcp/auth.ts to produce complete HTML pages. */import { renderToString } from "https://esm.sh/react-dom@18.2.0/server";import { ServerStyleSheet } from "https://esm.sh/styled-components@6?deps=react@18.2.0,react-dom@18.2.0";import type { ReactElement } from "https://esm.sh/react@18.2.0";import { shell, type ShellOptions } from "./shell.ts";export interface RenderPageOptions { /** The React element to render */ element: ReactElement; /** Path to the client hydration script (e.g. "/frontend/pages/recover/client.tsx") */ entry: string; /** Props to serialize for client hydration */ props?: Record<string, unknown>;/** Render a React page to a full HTML Response with SSR + styled-components CSS. */export function renderPage(opts: RenderPageOptions): Response {/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Client hydration entry for Landing page. All content is pre-rendered server-side. */import { hydrateRoot } from "https://esm.sh/react-dom@18.2.0/client";import { Landing } from "../../components/Landing.tsx";/** @jsxImportSource https://esm.sh/react@18.2.0 *//** SSR-friendly doc page — receives pre-rendered HTML from the server. * No client-side markdown fetching or parsing needed. */import { useState, useEffect, useCallback } from "https://esm.sh/react@18.2.0";import { styled } from "../styled.ts";/** @jsxImportSource https://esm.sh/react@18.2.0 *//** SSR-friendly doc page — receives pre-rendered HTML from the server. * No client-side markdown fetching or parsing needed. */import { useState, useEffect, useCallback } from "https://esm.sh/react@18.2.0";import { styled } from "../styled.ts";/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Server-side rendering utility. * * Renders a React component to HTML string with styled-components CSS extraction. * Used by route handlers in main.ts / mcp/auth.ts to produce complete HTML pages. */import { renderToString } from "https://esm.sh/react-dom@18.2.0/server";import { ServerStyleSheet } from "https://esm.sh/styled-components@6?deps=react@18.2.0,react-dom@18.2.0";import type { ReactElement } from "https://esm.sh/react@18.2.0";import { shell, type ShellOptions } from "./shell.ts";export interface RenderPageOptions { /** The React element to render */ element: ReactElement; /** Path to the client hydration script (e.g. "/frontend/pages/recover/client.tsx") */ entry: string; /** Props to serialize for client hydration */ props?: Record<string, unknown>;/** Render a React page to a full HTML Response with SSR + styled-components CSS. */export function renderPage(opts: RenderPageOptions): Response {/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Client hydration entry for Landing page. All content is pre-rendered server-side. */import { hydrateRoot } from "https://esm.sh/react-dom@18.2.0/client";import { Landing } from "../../components/Landing.tsx";/** @jsxImportSource https://esm.sh/react@18.2.0 *//** Client hydration entry for Landing page. All content is pre-rendered server-side. */import { hydrateRoot } from "https://esm.sh/react-dom@18.2.0/client";import { Landing } from "../../components/Landing.tsx";