Project Structure
This document describes the layout of the solid-admin project and the
responsibilities of each directory and key file.
Overview
solid-admin is a SolidJS 2.x application scaffolded
from the with-tanstack-router template. It uses TanStack Router for routing,
data loading, and navigation. The project compiles to a purely static site with
zero server dependencies — vite build emits dist/client, which can be
deployed to any static host.
Top-level layout
solid-admin/
├── .gitignore
├── AGENTS.md # Agent guide: Solid conventions and diagnostics
├── .opencode/ # opencode config + agent skills (e.g. daisyUI)
├── bun.lock
├── node_modules/
├── oxlint.config.mjs # Lint configuration
├── package.json
├── public/ # Static assets served as-is
├── README.md
├── skills-lock.json
├── src/ # Application source (see below)
├── tsconfig.json
├── vite.config.ts # Vite + Solid plugin + TanStack router plugin
└── vitest-setup.ts # Test environment setup
src/ layout
src/
├── App.tsx # App root: creates the TanStack router
├── App.css # App-level styles
├── Document.tsx # HTML document shell (entry wrapper)
├── logo.svg
├── vite-env.d.ts # Vite client type references
├── components/ # Reusable UI components
│ ├── Counter.tsx
│ └── Counter.test.tsx
├── routes/ # TanStack route files (code-generated tree)
│ ├── __root.tsx # Root layout + not-found boundary
│ ├── index.tsx # Home route (dashboard)
│ ├── users.tsx # Users list route
│ └── users.$id.tsx # Dynamic /users/$id route with loader
└── routeTree.gen.ts # Auto-generated typed route tree (do not edit)
Directory and file responsibilities
src/App.tsx
Creates the router with createRouter({ routeTree }) and registers its types
library-wide via the Register interface augmentation, so every <Link>’s
to and params are type-checked. The default export is the component the
generated entries render, wrapped in src/Document.tsx.
src/Document.tsx
The document shell that wraps the app in the generated entries (provides the
outer <html>/<head>/<body> structure for the client-mode build). Sets the
daisyUI data-theme.
src/routes/
TanStack owns everything routing. Route files follow TanStack’s naming
convention and are watched by @tanstack/router-plugin in vite.config.ts,
which regenerates src/routeTree.gen.ts.
__root.tsx— the site-wide admin shell (drawer + navbar) every route renders inside, plus thenotFoundComponentboundary.<HeadContent />renders titles declared by matched routes’headoptions.index.tsx— the home route (/): the dashboard.users.tsx— a users list page with a daisyUI table.users.$id.tsx— a dynamic route (/users/$id) demonstrating loader-driven data:fetchUser(id)runs when navigation starts and is cached per params;Route.useLoaderData()returns typed, reactive data.
src/components/
Reusable, self-contained UI components. Counter.tsx is the demo component and
ships with its Counter.test.tsx test.
src/routeTree.gen.ts
Auto-generated by @tanstack/router-plugin. It is the typed route tree that
src/App.tsx feeds to createRouter. Do not edit by hand — it regenerates as
route files change.
Ownership of concerns
@solidjs/vite-pluginowns the compile pipeline and app shell: the JSX transform, the turnkey entries aroundsrc/App.tsx, andsrc/Document.tsx. It does not know or care which router renders inside.- TanStack Router owns everything routing: route files under
src/routes, loaders, navigation, and head management.
Routing idioms
- Typesafe navigation —
<Link to="/users/$id" params=>is checked against the actual route tree at compile time. - Loader-driven data — routes declare
loader, run on navigation start, and expose typed data viaRoute.useLoaderData(). - Head management — routes declare
headoptions;<HeadContent />in the root renders the matched title. - Route-level code splitting —
autoCodeSplitting: trueinvite.config.tssplits each route’s component out of the entry.
Tests
Components under src/components/ are tested with Vitest (see
Counter.test.tsx). Run bun test to execute the suite.
Scripts
| Script | Purpose |
|---|---|
bun dev |
Start the dev server at http://localhost:3000 |
bun build |
Build the static site to dist/client |
bun serve |
Serve the production build locally |
bun test |
Run the test suite |