-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
273 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*/**/*.mdx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [email protected] # 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/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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' | ||
|
||
<FileTree> | ||
- src | ||
- [router.tsx](https://github.com/galadrimteam/adomin-frontend/blob/main/src/router.tsx) Frontend react-router-dom router | ||
</FileTree> | ||
|
||
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: <Navigate to={ADOMIN_HOME_PATH} />, | ||
}, | ||
{ | ||
path: ADOMIN_HOME_PATH, | ||
element: <Navigate to={ADOMIN_FOLDERS_PATH} />, | ||
}, | ||
{ | ||
path: ADOMIN_FOLDERS_PATH, | ||
children: [ | ||
{ | ||
path: ':view', | ||
element: <FoldersPage />, | ||
}, | ||
], | ||
element: <HomePage />, | ||
}, | ||
{ | ||
path: ADOMIN_STATS_PATH, | ||
children: [ | ||
{ | ||
path: ':view', | ||
element: <StatsPage />, | ||
}, | ||
], | ||
element: <HomePage />, | ||
}, | ||
{ | ||
path: ADOMIN_MODELS_PATH, | ||
children: [ | ||
{ | ||
path: ':view', | ||
children: [ | ||
{ index: true, element: <ModelListPage /> }, | ||
{ path: 'create', element: <CreateModelPage /> }, | ||
{ path: ':primaryKeyValue', element: <EditModelPage /> }, | ||
], | ||
element: <ModelsPageLayout />, | ||
}, | ||
], | ||
element: <HomePage />, | ||
}, | ||
{ | ||
path: ADOMIN_LOGIN_PATH, | ||
element: <LoginPage />, | ||
}, | ||
]) | ||
``` | ||
|
||
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' }, <MyOverridePage />), | ||
makeOverridePage({ model: 'User', type: 'update' }, <MyOverridePage2 />), | ||
makeOverridePage({ model: 'User', type: 'list' }, <MyOverridePage3 />), | ||
]) | ||
``` | ||
|
||
:::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: | ||
<CustomPage currentView="User"> | ||
<MyOverridePage /> | ||
</CustomPage>, | ||
} | ||
``` | ||
|
||
::: |