diff --git a/docs/.prettierignore b/docs/.prettierignore
new file mode 100644
index 0000000..b5f1a4a
--- /dev/null
+++ b/docs/.prettierignore
@@ -0,0 +1 @@
+*/**/*.mdx
diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index 91d493f..9738f1e 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -25,6 +25,11 @@ export default defineConfig({
path: '/reference/views',
autogenerate: { directory: 'reference/views', collapsed: true },
},
+ {
+ label: 'Frontend',
+ path: '/reference/frontend',
+ autogenerate: { directory: 'reference/frontend', collapsed: true },
+ },
],
},
],
diff --git a/docs/src/content/docs/guides/frontend-deployment.mdx b/docs/src/content/docs/guides/frontend-deployment.mdx
new file mode 100644
index 0000000..3fb7910
--- /dev/null
+++ b/docs/src/content/docs/guides/frontend-deployment.mdx
@@ -0,0 +1,132 @@
+---
+title: 'Frontend Deployment'
+description: How to deploy Adomin frontend
+sidebar:
+ order: 4
+---
+
+To deploy the Adomin frontend, you will need to:
+
+- run `yarn build` with correct VITE_API_URL env variable set
+- copy dist folder to your static files service
+- serve those files with a rule for SPAs (e.g. serving the index.html on 404)
+
+## S3 / Cloudfront
+
+```fish
+# copy dist files into your s3 bucket
+aws s3 sync ./dist s3://your-s3-bucket-name/
+
+# invalidate cloudfront distribution to serve the new files
+aws cloudfront create-invalidation --distribution-id YOUR_DISTRIB_ID --paths "/*"
+```
+
+### Github action for S3 / Cloudfront
+
+```yml
+name: Deploy staging ⚙️
+on:
+ push:
+ branches:
+ - does-not-exist # replace by e.g: staging
+
+jobs:
+ back-office:
+ runs-on: ubuntu-latest
+ env:
+ VITE_API_URL: https://api.staging.your-own-domain.fr/ # replace by your API url
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install dependencies
+ run: yarn
+ - name: Build
+ run: yarn build
+ - name: Configure AWS Credentials
+ uses: aws-actions/configure-aws-credentials@v2
+ with:
+ # you will have to create AWS_ACCESS_KEY and AWS_SECRET_KEY secrets in your repository settings
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
+ aws-region: eu-west-3
+ - name: Deploy
+ run: aws s3 sync ./dist s3://your-s3-bucket-name/ # replace by your s3 bucket name
+ - name: Invalidate dashboard cloudfront
+ run: aws cloudfront create-invalidation --distribution-id YOUR_DISTRIB_ID --paths "/*" # replace by your cloudfront distribution id
+```
+
+## Caddy
+
+Example of Caddy config to serve a SPA
+
+```
+example.com {
+ root * /usr/share/caddy/frontend
+ file_server
+ try_files {path} {path}/ /index.html
+}
+```
+
+### Github action for Caddy
+
+:::note
+This github action is taken from a project that uses [Galacrypt](https://github.com/galadrimteam/galacrypt) to encrypt/decrypt the env file
+:::
+
+```yml
+name: Deploy staging ⚙️
+on:
+ push:
+ branches:
+ - does-not-exist # replace by e.g: staging
+
+jobs:
+ frontend:
+ runs-on: ubuntu-latest
+ env:
+ VITE_API_URL: https://api.staging.your-own-domain.fr/ # replace by your API url
+ SERVER_IP: 1.2.3.4 # replace by your server IP
+ KEY_PATH: ./ssh_keys/staging/id_ed25519 # do not commit/push this file directly
+ SSH_USER: YOUR_SSH_USER # replace by your ssh user
+ SSH_PARAMS: -i ./ssh_keys/staging/id_ed25519 YOUR_SSH_USER@1.2.3.4 # replace dummy user / ip
+
+ steps:
+ - name: Checkout source code
+ uses: actions/checkout@v4
+
+ - name: Use Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+ cache: 'yarn'
+
+ - name: Dependencies installation
+ run: yarn
+
+ - name: Galacrypt decrypt # used to decrypt ssh key, you will have to create GALACRYPT_KEY in your repository secrets
+ run: yarn galacrypt use ${{ secrets.GALACRYPT_KEY }} && yarn galacrypt decrypt
+
+ - name: Generate build
+ run: yarn build
+
+ - name: Generate frontend zip
+ run: cd dist && zip -r ../frontend.zip .
+
+ - name: Setup SSH
+ run: |
+ mkdir -p ~/.ssh
+ ssh-keyscan $SERVER_IP 2>/dev/null > ~/.ssh/known_hosts
+ chmod 600 $KEY_PATH
+
+ - name: Copy files
+ run: scp -i $KEY_PATH ./frontend.zip $SSH_USER@$SERVER_IP:/home/$SSH_USER/frontend.zip
+
+ - name: Unzip
+ run: ssh $SSH_PARAMS "cd /home/$SSH_USER/ && rm -rf front-build && mkdir front-build && mv frontend.zip front-build/ && cd front-build && unzip frontend.zip && rm frontend.zip"
+
+ - name: Move website files
+ run: ssh $SSH_PARAMS "cd /home/$SSH_USER/ && (sudo mv /usr/share/caddy/frontend old_frontend || echo 'skipping mv old_frontend') && sudo mv front-build /usr/share/caddy/frontend && sudo rm -rf old_frontend"
+```
+
+## Nginx
+
+I don't want to deal with nginx anymore, but if you want to, you can find inspiration [here](https://sdickinson.com/nginx-config-for-single-page-applications/)
diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx
index 15b7c08..0645884 100644
--- a/docs/src/content/docs/index.mdx
+++ b/docs/src/content/docs/index.mdx
@@ -40,7 +40,7 @@ import { Card, CardGrid, LinkCard } from "@astrojs/starlight/components";
- - icons from tabler icons
+ - icons from [tabler icons](https://tabler.io/icons)
- folders and subfolders (with no limit)
diff --git a/docs/src/content/docs/reference/frontend/routing.mdx b/docs/src/content/docs/reference/frontend/routing.mdx
new file mode 100644
index 0000000..4a69764
--- /dev/null
+++ b/docs/src/content/docs/reference/frontend/routing.mdx
@@ -0,0 +1,134 @@
+---
+title: Frontend Routing
+description: Adomin frontend routing reference
+sidebar:
+ order: 0
+---
+
+You might have some questions:
+
+- how does the frontend routing work ?
+- how to add custom routes ?
+
+## Router file
+
+It all begins with the **react-router-dom** router
+
+import { FileTree } from '@astrojs/starlight/components'
+
+
+ - src
+ - [router.tsx](https://github.com/galadrimteam/adomin-frontend/blob/main/src/router.tsx) Frontend react-router-dom router
+
+
+Inside this file is all the routing
+
+If this documentation is up to date 😳, it will look like this:
+
+```tsx
+export const adominRoutes = createBrowserRouter([
+ {
+ path: '/',
+ element: ,
+ },
+ {
+ path: ADOMIN_HOME_PATH,
+ element: ,
+ },
+ {
+ path: ADOMIN_FOLDERS_PATH,
+ children: [
+ {
+ path: ':view',
+ element: ,
+ },
+ ],
+ element: ,
+ },
+ {
+ path: ADOMIN_STATS_PATH,
+ children: [
+ {
+ path: ':view',
+ element: ,
+ },
+ ],
+ element: ,
+ },
+ {
+ path: ADOMIN_MODELS_PATH,
+ children: [
+ {
+ path: ':view',
+ children: [
+ { index: true, element: },
+ { path: 'create', element: },
+ { path: ':primaryKeyValue', element: },
+ ],
+ element: ,
+ },
+ ],
+ element: ,
+ },
+ {
+ path: ADOMIN_LOGIN_PATH,
+ element: ,
+ },
+])
+```
+
+You can see that it is creating dynamic paths, those paths will be determined with your backend adomin config.
+
+To be clear, if you do not change the `ADOMIN_*_PATH` variables, the following paths are created:
+
+```bash
+/ # this path just redirects to /adomin, you can customize/remove this behaviour if you don't like it
+/login
+
+/backoffice/folders/:view # this dynamic path renders a folder view, which will redirect you to the nearest non-folder view
+/backoffice/stats/:view # this dynamic path renders a stat view
+
+/backoffice # this path adds a layout around the children of this route
+/backoffice/:model # this is the list page
+/backoffice/:model/create # this is the create page
+/backoffice/:model/:primaryKeyValue # this is the update page
+```
+
+and here is an example if you configured adomin with the User model
+
+```bash
+/backoffice/User
+/backoffice/User/create
+/backoffice/User/1 # page to update user with id = 1
+```
+
+## Custom routes and overrides
+
+If you want to override some page, let's say the create and the update page for your resource User, you will be able to do so by using the `makeOverridePage` helper, then put it somewhere in the router config, here is an example:
+
+```tsx
+export const adominRoutes = createBrowserRouter([
+ // default adomin config
+ // ...
+
+ // your config
+ makeOverridePage({ model: 'User', type: 'create' }, ),
+ makeOverridePage({ model: 'User', type: 'update' }, ),
+ makeOverridePage({ model: 'User', type: 'list' }, ),
+])
+```
+
+:::note
+💡 the `makeOverridePage` helper just creates a `RouteObject` wrapping the override component with a `CustomPage`, you can do it manually if you want more control:
+
+```tsx
+{
+ path: "/backoffice/User/create",
+ element:
+
+
+ ,
+}
+```
+
+:::