
react-ts-starter
An Opinionated React + TypeScript Starting Point
A GitHub template for React, TypeScript, Vite, and Tailwind v4 projects. Distilled from the patterns I kept rewriting across production apps — semantic color tokens with automatic dark mode, an accessibility baseline, lazy routes behind an error boundary, and a verify pipeline that gates every push. Press “Use this template” and the first commit already passes CI.
react-ts-starter is the starting point I reach for on every new React project. It is less a boilerplate than a set of settled arguments: how color tokens work, where environment variables are read, what happens when a route throws, and what has to pass before anything merges. Everything it ships is a decision I got tired of re-litigating.
The constraint that shaped the most code is theming. Colors resolve through semantic tokens — text-foreground, bg-raised, text-accent — and dark mode re-maps those same variables under prefers-color-scheme. There is not a single dark: variant in the markup, which means a component author never writes a color twice, and the two themes cannot drift apart the way parallel class lists always eventually do.
What It Ships
- Semantic color tokens with automatic dark mode via prefers-color-scheme — no dark: variants anywhere in the markup
- Accessibility baselines wired in globally: prefers-reduced-motion and forced-colors overrides, and a visible focus-visible ring
- Route-level code splitting behind a shared Suspense fallback, with an ErrorBoundary that resets on navigation
- One place to read environment variables, and one file for shared types — no per-domain type modules
- A verify pipeline — prettier-check, lint, typecheck, build — run identically on a laptop and in CI
- A GitHub Pages workflow that derives its base path from the repository name, so project pages and user pages both work unedited
Deep links were the fiddly part. A single-page app on GitHub Pages breaks on a hard refresh, because Pages looks for a file at that path and finds none. The template generates its 404.html at build time with the resolved base baked in, rather than keeping a static copy — Vite copies the public folder verbatim and never rewrites paths inside it, so a hand-written redirect silently dies the moment the site moves to a project page. Generating it means a fork works unchanged whether it deploys to a project page, a user page, or a custom domain.
The dependency list is the feature I am most protective of. Three runtime dependencies — React, React DOM, and React Router — and everything else is a build-time tool. The technology logos on the site are plain SVG files rather than an icon package, for the same reason: a starting point that arrives with opinions should not also arrive with a supply chain.

