This is a suggested stack to build modern SPA.
It's hosted here : https://vite-insee-starter.demo-domain.ovh/
It's composed of:
- Docker
- Nginx
- Vite
- TypeScript
- React
- Tanstack Router - A better alternative to React Router.
- π react-dsfr - The React Toolkit for The French Design System (DSFR)
- MUI - As a backup component library to fallback to if you don't find the component you need in the DSFR library.
- π vite-envs - A solution to avoid having to re-build the app when you change the environment variables.
- π tss-react - A CSS-in-JS solution.
- π i18nifty - A solution to to make your app available in multiple languages.
- react-query - A solution to manage your API calls.
- π oidc-spa - A solution to integrate OpenID Connect in your app. (Keycloak)
- π tsafe - Type safety utilities.
- π ts-ci - GitHub Actions to manage the lifecycle of the project and publish automatically on Docker Hub.
- Prettier - Code formatter.
- Orval - A solution to generate API clients based on OpenAPI specs.
π: Made by us.
git clone https://github.com/InseeFrLab/vite-insee-starter
cd vite-insee-starter
cp .env.sample .env.local
yarn
yarn dev
You can use the Docker Image published here: https://hub.docker.com/r/inseefrlab/vite-insee-starter
You have to set the environment variables:
VITE_API_URL=https://insee-todo-api.up.railway.app
VITE_OIDC_ISSUER=https://auth.code.gouv.fr/auth/realms/playground
VITE_OIDC_CLIENT_ID=vite-insee-starter
The CI of this starter automatically publishes on dockerhub under <name of the github org>/<name of the repo>
For it to work you must have set the GitHub Actions secrets:
${{ secrets.DOCKERHUB_USERNAME }}
${{ secrets.DOCKERHUB_TOKEN }}
(It is configured in the option of the repo or the github org)
For demoing this stack we created a simple todo app REST API.
It's available here: https://github.com/InseeFrLab/todo-rest-api
and is deployed here: https://insee-todo-api.up.railway.app/doc
The client used to consume this API is automatically generated by Orval.
You can refresh it for the currently published version of the API by running:
yarn generate-todos-api-client
When authenticating you will notice that the login pages are DSFR themed.
We're using the custom keycloak theme of the DSFR: keycloak-theme-dsfr π.
It has been created using react-dsfr and Keycloakify.
![image](https://user-images.githubusercontent.com/6702424/231314534-2eeb1ab5-5460-4caa-b78d-55afd400c9fc.png)
![image](https://private-user-images.githubusercontent.com/6702424/268117172-aa06cc30-b2bd-4c8b-b435-2f875f53175b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQzOTQyMTgsIm5iZiI6MTcyNDM5MzkxOCwicGF0aCI6Ii82NzAyNDI0LzI2ODExNzE3Mi1hYTA2Y2MzMC1iMmJkLTRjOGItYjQzNS0yZjg3NWY1MzE3NWIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjNUMDYxODM4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MDcyZTkzYjYwZjZmNzhkMDdiYzg3MjA2NjVlYjczMTgxNDU2OGRmYmQwM2ZiNDNlNTliY2FhODZlNWMwMTFmZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.xw1VVDCRKAAmpgFPTg8PkBxJdKKXGXyMggHXIUxkVwY)
You might think that tss-react isn't the more obvious choice and I'm just pushing it because we made it but here me out.
It has approximately 900 000 downloads per month and is used by establish solution like Jitsi and
it integrates flawlessly with MUI. It's even mentioned in the official MUI documentation.
But more importantly. It's arguably the one of the most powerful styling solution. It enables to write styles as a function of the internal state of the component.
It let you express sophisticated styling logic in a way that is easy to read and maintain.
It's drawback is that, as it's a dynamic styling solution (as opposed to statically extracted ones like tailwind), it's doesn't have the same performance and is not compatible with Next.js Server Components. However at Insee we're building SPA and the performance hit is negligible (we're talking about a few milliseconds).