sidebase
sidebase is a modern, best-practice, batteries-included fullstack-app starter based on Nuxt 3 and TypeScript.
With this nuxt 3 starter you get production-ready frontend + backend projects while still having fun! Atinux, CEO of Nuxt said to sidebase on Twitter:
Beautiful work on sidebase!
Quick start
- Use the official
nuxi
-cli to start:npx nuxi@latest init -t community/sidebase
- Go into the
nuxt-sidebase/
directorycd nuxt-sidebase
- Install the dependencies
npm i
- Start developing (with database, backend, API, ... running) at localhost:3000
npm run dev
Features
The key features are:
-
π Fullstack: Develop frontend and backend in a single TypeScript code base- Fullstack
Vue 3
+Nuxt 3 RC.10
, - Data base models, migrations, queries and easy DB-switching via
TypeORM
, - Frontend- and Backend data-transformation via
nuxt-sidebase-parse
andzod
, - In-memory development SQL-database via
sqlite3
, - Linting via
eslint
, - Test management, Test UI, component snapshotting via
vitest
, - Component tests via
test-library/vue
, - API tests via
supertest
, - Code coverage via
c8
, - Component stories via
histoire
, - CSS utiltities via
TailwindCSS
, - CSS components via
Ant Design Vue
, - Type checking in script and template via
Volar / vue-tsc
- Fullstack
-
ποΈ Fast to code: Database, example tests, example components and example pages are all there for you to fill out -
π Fewer bugs: Strong data-validation usingzod
to validate all transferred data, fully typed API-routes, strict DB models viaTypeORM
-
π Easy to use: Designed to follow best practices and to be ready-to-go for development, without additional dev-dependencies likedocker
that make it hard to get started -
π Ready for launch: Github Actions CI, Dockerfile, easy switch to most popular SQL-databases are all there, out of the box (get in touch if you're missing something)
To facilitate this sidebase
bootstraps a nuxt 3 project that permits developing a backend and a frontend using just Nuxt 3 with overarching TypeScript support. We want to show the world how enjoyable end-to-end typescript programming can be, displacing the myth that JS/TS-backends are no good. This starter solves a lot fo the "real-world" problems that occur after you start using Nuxt or any other framework: How to write backend tests? How to write component tests? How to calculate test coverage? How to integrate a database? How to build a docker image? ...?
If you have any problems with this project (e.g., setting it up on your PC) open an issue and we'll figure it out together with you
Documentation
This is the documentation section of sidebase. It contains useful commands and guides to make your work easier and more pleasurable.
Commands
Useful Commands for development, testing and deployment:
- Develop & Debug the app:
npm i
: Install required dependenciesnpm run dev
: Start the fullstack app, including databasenpm run story
: Starthistoire
for component story based development of UI
- Linting & Formatting (
npm run lint
)npm run lint:style
: eslint for formatting & lintingnpm run lint:style -- --fix
: Autofix styles and lints where possiblenpm run lint:types
: typescript typechecking
- Testing & Code Coverage & Component Snapshots
npm run test
: Run tests once, report results and coveragenpm run test:watch
: Run tests and watch file changes, run tests for changed filesnpm run test -- -u
: Update component snapshots after components changednpm run test -- -t "some test-text"
: Run all tests withsome test-text
in theirtest(...)
description
npm run test:ui
: Run the vitest testing web UI for easier test interaction@testing-library/vue
for easy and best-practice component tests, see example here- breakpoint debugging (zero-config in VS Code)
- Open the command palette (CMD / CTRL + SHIFT + P)
- Select "Debug: JavaScript Debug Terminal"
- Run any
npm
command insideapp/
, e.g.:npm run test
- Your code editor colors should change a bit (e.g.: to orange) while executing the command, the left side should show deep execution insights
- Set breakpoints (click left of line count in editor - red dot should appear) - the debugger will automatically work and stop at them and allow you to inspect variables
- Run a command that runs the code you set breakpoints at, e.g.,
npm run test
- Building & Deploying:
npm run build
: Build the app for productionnpm run start
: Start the app in production (requiresnpm run build
beforehand)
- CSS usable without imports
- Utility & Styling: TailwindCSS 3
- Components: Ant Design Vue with component-auto-import
- slim docker ready
> docker build -t nuxt3-app . > docker run -p 3000:3000 --init --rm nuxt3-app
- Note: Docker is not required for development or deployment - for development
sqlite3
is used and will launch automatically vianpm run dev
π
- Note: Docker is not required for development or deployment - for development
- Miscallaneous
nvm use
: If you usenvm
, use this command to make sure that your local environment uses the correct, required node version- Pre-commit checking (husky) & fixing (lint-staged)
- github CI pipeline to linting, testing, typing checks
- nuxt-component support in tests and histoire
- debug sql database queries by setting
logging: true
in thedatabase/index.ts
: This will show you a live log of all ongoing database queries which is super helpful to debug database problems
Guides
Useful guides to get started with or use more advanced features of sidebase
.
First time node and npm setup
If this is the first time you run a npm
/ node
app on your setup:
- Install the
node
version managernvm
by running:> curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
- Install the required
node
andnpm
version:# uses existing `.nvmrc`-file to install required version > nvm install
- Use the required
node
andnpm
version:# uses `.nvmrc` to use required version > nvm use # ALTERNATIVE: make node 16.14.2 your default node version (version copied from `.nvmrc`, check there for most up to date node version) > nvm alias default 16.14.2
- Install a code editor (recommended: VS Code), get it here
- Uninstall or disable the old Vue VS Code extension
Vetur
, else conflicts may arise betweenvolar
andVetur
- Install the
volar
extension to supportvue
,nuxt
andtypescript
development help - Enable "take over mode" for volar for this project.
- documented here: johnsoncodehk/volar#471
- for VS Code:
- Run (CMD/CTRL + SHIFT + P): Extensions: Show Built-in Extensions
- Find "TypeScript and JavaScript Language Features"
- Right click and select "disable for workspace"
- Reload the editor
- A message "Take over mode enabled" (or similar) should appear
- Go to the top of this section and execute commands (start with
npm i
to get all packages!)
If you have type-problems after running npm i
for the first time:
- Ensure you have
vetur
disabled or uninstalled (see above), - Ensure you have the builtin
typescript
extention of VS Code disabled (see above), - Reload the
vue
volar server (VS Code command: "Volar: Restart Vue Server") - Close and re-open the file you have problems with
If none of this works, file an issue (preferrably with a reproduction) here.
nuxt-sidestream-parse
nuxt-sidestream-parse
to validate and deserialize data from theserver
in thefrontend
:- Define a zod-schema for the response of your endpoint, like so:
// file: ~/server/schemas/healthz.ts import { z } from '@sidestream-tech/nuxt-sidebase-parse' import { transformStringToDate } from './helpers' export const responseSchemaHealthCheck = z.object({ status: z.literal('healthy'), time: z.string().transform(transformStringToDate), nuxtAppVersion: z.string(), }) export type ResponseHealthcheck = z.infer<typeof responseSchemaHealthCheck>
- Define an endpoint that returns complex data (e.g.: date-objects), like so:
// file: ~/server/api/healthz.get.ts import { defineEventHandler } from 'h3' import type { ResponseHealthcheck } from '~/server/schemas/healthz' export default defineEventHandler((): ResponseHealthcheck => { return { status: 'healthy', time: new Date(), nuxtAppVersion: process.env.NUXT_APP_VERSION || 'unknown', } })
- Call it from the frontend, get free data validation, derserialization (e.g.: string-date is transformed to
Date
object) and typing, like so:// file: ~/pages/index.vue import { makeParser } from '@sidestream-tech/nuxt-sidebase-parse' import { responseSchemaHealthCheck } from '~/server/schemas/healthz' const transform = makeParser(responseSchemaHealthCheck) const { data } = await useFetch('/api/healthz', { transform }) console.log(data) // -> Object { status: "healthy", time: Date Thu Sep 15 2022 15:45:53 GMT+0200 (Central European Summer Time), nuxtAppVersion: "unknown" }
- That's it!
data
will be fully typed AND all data inside will be de-serialized, sotime
will be aDate
-object, and not a string, that you first need to deserialize - If an
error
is thrown, it's done using nuxtcreateError
, so it works well in frontend and on the server.data
will be null in that case. You can find zod-details about your error inerror.data
- Define a zod-schema for the response of your endpoint, like so:
- Use
nuxt-sidestream-parse
to validate data that the user has passed to your API endpoint:- Parse user data like this:
import { defineEventHandler } from 'h3' import type { CompatibilityEvent } from 'h3' import { parseBodyAs, z } from '@sidestream-tech/nuxt-sidebase-parse' export default defineEventHandler(async (event: CompatibilityEvent) => { // Parse the payload using the update schema. The parsing is important to avoid bad, incorrect or malicious data coming in const payload = await parseBodyAs(event, z.object({ requestId: z.string().uuid(), pleaseDoubleThisNumber: z.number() })) return { requestId: payload.requestId, doubledNumber: 2 * payload.pleaseDoubleThisNumber } })
- Other helpers like
parseQueryAs
,parseCookiesAs
,parseParamsAs
, ... are defined in@sidestream-tech/nuxt-sidebase-parse
. See a bigger example here
- Parse user data like this: