React + shadcn/ui
A Vite + React 19 client wired to the Phoenix backend, with shadcn/ui components installed via the official CLI. Pick this when you prefer React, want shadcn’s component library, or are bringing existing React skill to a Phoenix backend.
Install
npx tostada-cli create MyApp --variant react-shadcn Or interactively pick React + shadcn/ui at the variant prompt.
What happens
- CLI downloads the Tostada shared base (
server/,Makefile,scripts/) - CLI copies the React template into
client/— Vite + React 19 + TypeScript + Tailwind - CLI runs
npx shadcn@latest add --yes button card input form dialoginsideclient/, populatingsrc/components/ui/ - CLI runs
mix deps.get+npm install(unless--no-install)
The components.json shadcn config ships in the template, so the shadcn init step is skipped — you can run npx shadcn@latest add <component> later to extend.
What you get
In client/:
- React 19 + TypeScript + Vite 7
- Tailwind CSS 3 +
tailwindcss-animate - shadcn/ui components:
Button,Card,Input,Form,Dialog(insrc/components/ui/) - Lucide React for icons
src/lib/socket.ts— Phoenix socket helper with a framework-agnostic subscribe API (no React-specific bindings; usable from hooks or providers)src/lib/utils.ts— shadcn’scn()helper- A minimal
App.tsxlanding page with shadcn<Button>auth links - Strict TypeScript with project references (
tsconfig.app.json+tsconfig.node.json)
In server/:
- The shared Phoenix backend (identical across all variants)
Vite + proxy + build
The React Vite config mirrors the SvelteKit variants’ proxy block exactly. In dev, /api, /socket, /users, /live, /assets all proxy to Phoenix on :4000. In production, Vite builds to ../server/priv/static/app with base path /app/ so Phoenix serves it at /app.
Available addons
| Addon | Default | Notes |
|---|---|---|
docker | off | Dockerfile + docker-compose for containerized deploy |
Threlte and model-pipeline addons aren’t offered for this variant — they’re SvelteKit-specific.
Verifying the install
cd MyApp
make db.setup
make dev Open http://localhost:5173 — the React landing page loads, /api/me proxies through to Phoenix.
Adding more shadcn components
cd client
npx shadcn@latest add dropdown-menu sheet tabs The components.json and path aliases (@/components, @/lib) are pre-configured.
Connecting to Phoenix from React
src/lib/socket.ts exposes a framework-agnostic API:
import { connectSocket, subscribeSocketStatus, pingSocket } from '@/lib/socket';
// In a component:
useEffect(() => {
connectSocket();
return subscribeSocketStatus((status) => setStatus(status));
}, []); The shared backend’s auth flow (session cookies + socket token at /api/socket-token) works the same way as in the SvelteKit variants — see Auth System.
What to build next
- Auth System — session + socket-token flow
- Channels + Stores — Phoenix channel patterns (Svelte-flavored, but the channel protocol is identical)
- Server Authority — multiplayer state authority patterns