Skip to content

alixlahuec/typescript-fullstack-template

Repository files navigation

Typescript Full Stack Template (React + Vite + Nitro)

A simple template for a ready-to-build, full-stack application written completely in Typescript using:

  • Vite and React 18 for building a single-page application (SPA);
  • Nitro for defining the API layer and serving the full application (SPA + API);
  • Vitest for testing;
  • Biome for code standards and formatting;
  • Lefthook for Git hooks.

The template is not opinionated about tooling for:

Start coding in minutes, then scale at your pace - based on what you need, what you like, and how your application evolves.

The application can be deployed anywhere where Nitro can be deployed.

Prerequisites

  • Node >=v22
  • npm (or your preferred package manager) and base knowledge about its commands/behavior

All commands below assume npm as package manager, for simplicity. If you use a different manager - be aware that certain tools like Lefthook may have additional specifications for other managers like pnpm, so take a quick look at the documentation to see if you need to make adjustments. You'll also want to do a text search for "npm" in the repository to make sure you replace all usages.

Available commands

npm start           # start the application in development mode
npm test            # run tests

npm run check       # run linting and formatting checks on all files
npm run fmt         # apply linting and formatting to all files
npm run typecheck   # run typecheck

npm run prepare     # ensure local setup is ready

npm run build       # bundle the application for production
npm run preview     # serve the output of `npm run build`

Stack components (and how to replace anything you don't need)

The Javascript ecosystem is always evolving, and it's hard to keep up while avoiding compatibility issues, vendor lock-in, and constantly learning new abstractions. This template uses a small, modern, performant set of tools that play well with each other, without making any part irreplaceable. The main goals are modularity, simplicity, and avoiding unseen "magic" - while promoting code quality and a great development experience from the start.

The sections below introduce each tool, and how to remove/replace it based on your own preferences.

At the time of writing, the project has no known vulnerable dependencies.

Biome

Handles linting, formatting, and code quality checks. This is an alternative to tools like ESLint and Prettier. Biome is extremely fast, supports Typescript out-of-the-box, provides great CLI feedback, and intentionally keeps things simple - avoiding extensive configuration files and complex plugin systems that take time to maintain, upgrade, and ensure compatibility for.

Configuration

The template mainly uses Biome's defaults, with only a handful of configurations (see the biome.json file).

If you use an IDE, you may want to setup its integration with Biome if available (for example, to use format-as-you-type or format-on-save features). See available integrations here.

How to remove or replace it

To remove Biome:

  1. Remove it from the project dependencies: npm uninstall @biomejs/biome.
  2. Delete the configuration file, biome.json.
  3. Update (or remove) the "check" and "fmt" commands from package.json.
  4. Update the Lefthook configuration file (lefthook.yaml) accordingly:
    • If you deleted the commands and do not want to use a linter/formatter at all: remove the pre-push hook.
    • If you updated the commands to use your own preferred tools: update the pre-push hook as needed. Read the Lefthook section below for more details.

Lefthook

Provides convenient automations while developing, based on Git hooks. This is an alternative to tools like Husky and lint-staged. Lefthook is easy to configure, works with any stack, and enables direct reuse of commands from package.json so that all configuration is centralized. It's directly installable and maintainable as a single project dependency, rather than requiring additional installation steps.

Configuration

The template configures two Git hooks:

  • post-checkout: on branch checkout, it installs the project's dependencies with npm install. In turn, this will run the "prepare" script from package.json (npm documentation), which ensures Lefthook is configured and also refreshes your local Nitro artefacts.
  • pre-push: on commit push, it runs the "fmt" script from package.json. This is an intentional departure from the classic "pre-commit" setup, to enable fast iteration locally (without worrying about writing fully clean, conformant code) and defer formatting/validating code until it's ready to be pushed. The command only runs on the actual files being pushed, for optimal speed.

How to remove or replace it

To remove Lefthook:

  1. Uninstall it from the project dependencies: npm uninstall lefthook.
  2. Delete the configuration file, lefthook.yaml.
  3. Update the "prepare" command from package.json to remove "lefthook install".

Nitro

Creates a web server for Javascript runtimes. This is an alternative to tools like Express, Hono, and Fastify. Nitro provides an intuitive API for defining routes, aligned with web standards and promoting modularity & composability, with full Typescript support. It's easy to extend with custom or library code, with compatibility adapters for multiple middleware types, and offers hot module replacement (HMR) during local development.

Configuration

The template uses a minimal Nitro configuration (see nitro.config.ts) to expose:

  1. An index route (index.ts), which serves the client app as a single-page application (SPA).
  2. An API endpoint (api/health.ts) that returns a healthcheck.

In development mode, the server integrates with Vite through a custom plugin and middleware - this provides a way to start the full application locally from a single command, with hot module replacement (HMR) for both client and server logic. In production mode, the server expects to find the app's static assets in the dist directory and will serve them directly.s

Auto-imports and virtual imports are disabled to prevent "magic" behavior. If you're familiar with how this works and know what you're doing, you can restore those functionalities:

  • Auto-import
    • Remove the imports.autoImports parameter in nitro.config.ts, so that it uses the default value (true).
    • Add .nitro/types/nitro-imports.d.ts to the include list in tsconfig.server.json.
  • Virtual imports
    • Remove the typescript.generateTsConfig parameter in nitro.config.ts, so that it uses the default value (true).
    • Update tsconfig.server.json so that it extends from ./nitro/types/tsconfig/json (order is important): "extends": ["./nitro/types/tsconfig/json", "./tsconfig.json"].
    • Remove the .nitro/* files from the include list.

If you do so, be aware that additional changes will be needed if you want to import from Nitro files when writing tests, because the test runner will need to be able to find the different imports.

How to remove or replace it

To replace Nitro:

  1. Uninstall it from the project's dependencies: npm uninstall nitropack.
  2. Delete the configuration file, nitro.config.ts.
  3. Update .gitignore to remove the entries under "Nitro".
  4. Remove all type references:
    • Update tsconfig.server.json and tsconfig.app.json to remove all .nitro/* files from the include list.
    • Delete src/types.ts.
  5. Migrate the relevant package.json commands ("build", "prepare", "preview", "start") and the code from the server directory. The exact steps will depend on what you want to replace Nitro with. Read the documentation for each of the commands and the server README to understand what you need to re-implement.

React

How to remove or replace it

To replace React:

  1. Uninstall the related project dependencies: npm uninstall react react-dom @vitejs/plugin-react @types/react @types/react-dom.
  2. Remove the plugin from Vite's configuration file (vite.config.ts).
  3. Update src/main.tsx and src/app/index.tsx to render app code with your chosen framework (e.g. Vue, Svelte, Preact).

You may also need to update the Typescript configuration for client files (tsconfig.app.json).

Typescript

Configuration

The template uses strict typechecking, with a few additional rules to improve code quality (see tsconfig.json). Two projects are used to define the appropriate runtimes for different parts of the app:

  • tsconfig.app.json for client files. This also makes the server's API schema available for use in client code via the auto-generated .nitro/types/nitro-routes.d.ts.
  • tsconfig.server.json for server files. This also makes available the models for the server's runtime configuration (.nitro/types/nitro-config.d.ts) and routes (.nitro/types/nitro-routes.d.ts) for improved typechecking.
    • This is a necessary departure from what the Nitro documentation recommends, because the template disables auto-imports and virtual imports (see the Nitro section for more context).

Vite

Manages the bundling of client files into static assets. This is an alternative to tools like Parcel, Rsbuild, and Webpack. Vite provides a performant dev server with hot module replacement (HMR), interfaces for composability (e.g. for SSR and backend integrations), and a lean core that is easy to extend.

Configuration

The template uses default configuration for Vite, with the React plugin (@vitejs/plugin-react). See vite.config.ts.

Vitest

Testing framework. This is an alternative to tools like Jest, Mocha, and Jasmine. Vitest can directly integrate with Vite, allowing to consolidate bundling configuration into one file (vite.config.ts), and provides similar performance benefits as Vite for local development.

Configuration

The template uses default configuration for Vitest (no vitest.config.ts).

How to remove or replace it

To remove Vitest:

  1. Uninstall it from the project's dependencies: npm uninstall vitest.
  2. Update or remove the "test" command from package.json.
  3. Update or remove the server/tests code as needed.

About

Template for a full-stack Typescript application

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published