gh repo clone giacomorebonato/fastrat-test # clone the repository
pnpm install # install dependencies
node --run dev # start the project in dev mode
To enable authentication and a production database, rename .env.example
to .env
and fill the fields properly.
In a production environment, you should set those environment variables directly.
- Authentication
- libSQL (SQLite fork) on Turso
- SSR and Routing
- tRPC
- Server side data fetching
- Testing
- Deploy
- Credits
- Fastify: a fast well maintained web framework
- Vite: for frontend tooling and bundling
- tRPC: for end points with E2E type safety
- Tanstack Router: for filesystem based routes with type safety
- Vavite: use Vite to compile and bundle both client and server code
- Fly.io: for deployment
Thanks to Vavite, any change to frontend or backend code will be reflected immediately, without manually restarting the server.
Provide GOOGLE_CLIENT_ID
and GOOGLE_CLIENT_SECRET
into the .env
file to allow Google authentication (instructions).
You can check how authentication is achieved in src/features/auth/google-auth.ts by leveraging fastify-oauth2.
It should be easy for you to re-use this example to add other authentication providers.
- install the turso CLI
- login and create a database
turso db create fastrat
- get an authentication token with
turso db tokens create fastrat
- set Fly.io secrets accordingly
SSR is achieved by following Tanstack router examples.
The page content is streamed and meta tags in <head />
are rendered following react-helmet-async examples.
This project comes with tRPC ready to be used.
Check note-router.ts to see how queries, mutations and subscriptions can be implemented.
All the routers are collected in api-router.ts, but you can organise files in the way you prefer.
Server side data fetching is needed if you want to render HTML on server side (for SEO for example).
It happens in the route loader function defined in Tanstack router.
As in the link you have to be mindful that the loader runs both server and client side, hence you should guard dynamic server only import inside of the if (import.meta.env.SSR)
condition.
You can then assign the fetched data to React-Query initialData
parameter, like this:
const loaderData = Route.useLoaderData()
const noteQuery = trpcClient.note.get.useQuery(
{ id: noteId },
{
initialData: loaderData?.note,
},
)
With this practice we ensure that:
- HTML is rendered if the page is accessed through server side routing
- a request is made to fetch data if the page is accessed through client side routing
This probably looks less magical than getServerSideProps
, but still gives you full control over the rendering process.
This starter contains a few unit tests and an E2E test.
node --run test # uses Vitest to run unit tests
node --run e2e # uses PlayWright to run E2E tests
node --run e2e:headed # uses PlayWright to run E2E tests opening the browser
The present E2E tests verify that the page is server rendered and that websockets are working.
You can deploy FastRat everywhere Docker runs.
- This website deploys automatically to Fly.io
- Environment variables
This project has been inspired by other starter kits: