How to setup a new basic multilanguage project from scratch
- for local development and production deplyoment on an Ubuntu server
- based on Directus and Nuxt with SSR
- with a lightweight sqlite3 database
- incl. multilanguage label management in Directus
- incl. preview mode in Directus
- incl. visual editor in Directus
- Ubuntu
- Access to GitHub repository
- Docker
- Docker Compose
- Node/npm
-
Get template files from GitHub and create a new project directory/repository:
-
Check https://hub.docker.com/r/directus/directus for latest Directus Docker image an consider changing the version in
docker-compose.yml -
Rename
.env.exmapleto.envand add credentials for local development:# Directus configuration DIRECTUS_SECRET={{ your secrect }} # No $ signs DIRECTUS_ADMIN_EMAIL={{ your e-mail }} DIRECTUS_ADMIN_PASSWORD={{ your passowrd }} # No $ signs DIRECTUS_PUBLIC_URL=http://localhost:8055 # Nuxt configuration NUXT_DIRECTUS_URL=http://directus:8055 NUXT_PUBLIC_DIRECTUS_URL=http://localhost:8055 # CORS CORS_ORIGIN=http://localhost:3000
-
Repeat the former step for the production environment by renaming
.env.prod.exmapleto.env.prodand adding production variables -
Add Directus directories for mounted Docker volumes with
mkdir -p directus/database directus/uploads directus/extensions -
Set the owner of these directories to UID 1000 (the Directus Docker user, usually the same as your local user) with
sudo chown -R 1000:1000 directus/ -
Set the permissions of the Directus directories so that everyone can read with
sudo chmod -R 755 directus/ -
Create a fresh
frontenddirectory with a SSR Nuxt project withnpx nuxi init frontend- Choose the minimal setup
- Do not add a Git repository
- do not install any of the official modules
__frontendcontains the basic project already but I prefer to start fresh with currenct npm versions for all packages. Keep the__frontenddirectory to copy composables, etc. later.
-
Navigate into the
frontenddirectory withcd frontend -
Run
npm install -
Run
npm install @css-render/vue3-ssrto handle SSR -
Run
npm i --save-dev @types/nodeso there will be less warnings in VSC -
Run
npm install @directus/sdkto communicate with Directus -
Run
npm install @directus/visual-editingfor Directus' visual edior feature -
Run
npm install @nuxtjs/i18nto add default i18n support -
Run
npm i -D naive-uito add NaiveUI -
Make sure the fresh
frontenddirectory contains the file as in__frontend, exceptpackage.json/package-lock.jsonandREADME.md:- Dockerfile.dev - nuxt.config.ts --> Check the actual PROD URL for the second frame-ancestors!! - ./app/* -
Navigate back to the root with
cd .. -
Remove the
__frontenddirectoy -
Start everything up with
docker compose up -d -
Vist http://localhost:8055, log in with the credentials from your .env file, and set the owner
-
Copy the demo database schema into the container with
docker compose cp ./seed/schema.yaml directus:/directus/schema.yaml -
Apply the demo database schema with
docker compose exec directus npx directus schema apply /directus/schema.yaml -
Remove the file for tidiness with
docker compose exec directus rm /directus/schema.yaml -
Go to Directus (http://localhost:8055) and log in
-
Make sure the
datasets,labels,pagescollections as well as their hidden translation collections are publicly available (read access is enough) -
Import the collections items from the
seeddirectory in the following order:- languages
- datasets
- labels
- pages
-
Remove the
seeddirectory -
Check http://localhost:3000 for the demo
-
Check
LICENSE.md -
Make sure
.gitignorelooks like this (WITHOUT ANY LEADING SPACES):# Environment .env .env.local .env.*.local # Directus directus/database/ directus/uploads/ # Nuxt frontend/node_modules/ frontend/.nuxt/ frontend/.output/ frontend/dist/ # IDE .vscode/ .idea/ # OS .DS_Store -
Add a proper Git repository with:
git init git add .gitignore git add . git commit -m "Initial commit" -
Review the basic project files and Directus setup and start developing
- Create all needed block collections first: Settings → Data Model → Create Collection
- block_richtext
- block_hero
- block_gallery
- block_cta ... etc.
- Add translations to each block:
- Settings → Data Model → Select
block_richtext - Add field → Translations (uses Translations interface)
- Save
- Directus creates
block_richtext_translationsautomatically
- Settings → Data Model → Select
- Add content fields to translation tables:
Go to the
_translationscollection for each block:block_richtext_translations:- Add field:
headline(text) - Add field:
content(WYSIWYG) ... etc.
- Add field:
- Now add M2A to your main page collection (might or might not be a singleton):
- Settings → Data Model → e.g. about
- Add field → Many to Any (M2A)
- Name:
blocks - Collections: Select block_richtext, block_hero, etc.
- Access to GitHub repository
- Ubuntu server with SSH access
- SSH into the server
- Update system with
sudo apt update && sudo apt upgrade -y - Install Docker with:
curl -fsSL https://get.docker.com | sudo shsudo usermod -aG docker $USER
- Install Docker Compose plugin with
sudo apt install docker-compose-plugin -y - Log out and back in for group changes
- Exit with
exit - Reconnect by SSHing into the server
- Exit with
- Install Nginx with
sudo apt install nginx -y - Install Certbot with
sudo apt install certbot python3-certbot-nginx -y - Configure firewall in this order:
sudo ufw allow OpenSSHsudo ufw allow 'Nginx Full'sudo ufw enable
- Make sure these ports are open in your Cloud Service's firewall if there is one:
- 80 (HTTP)
- 443 (HTTPS)
- SSH into the server
- Create a project directoy with:
sudo mkdir -p /opt/{{ project }} - Add the correct permissions with
sudo chown $USER:$USER /opt/{{ project }} - cd into the project with
cd /opt/{{ project }} - Add a Git repository with
git init - Add the remote with
git remote add origin https://github.com/{{ username }}/{{ project }}.git - Set
git branch --set-upstream-to=origin/main main - Pull files with
git pull origin main - Create an .env file on the server with
nano /opt/{{ project }}/.envand paste the prod variables- Ctrl + o
- Enter
- Ctrl + x
- Create Directus directories with
mkdir -p directus/database directus/uploads directus/extensions - Make sure you have a working database file on your server with correct data and credentials or start blank and add or import schema and data
- SSH into the server
- cd into project with
cd /opt/{{ project }} - Log in to Docker with
docker login -u {{ username }} - Build and start containers with
docker compose -f docker-compose.prod.yml up -d --build
-
Create an Nginx configuration file with
sudo nano /etc/nginx/sites-available/{{ project }}:# /etc/nginx/sites-available/{{ project }} server { listen 80; listen [::]:80; # Delete this line if you don't use IPv6 server_name {{ frontend domain }}; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } } server { listen 80; listen [::]:80; # Delete this line if you don't use IPv6 server_name {{ directus domain }}; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; } location / { proxy_pass http://127.0.0.1:8055; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; # Larger body size for Directus uploads client_max_body_size 100M; } }
- Ctrl + o
- Enter
- Ctrl + x
-
Create the Certbot directory with
sudo mkdir -p /var/www/certbot -
Enable the site with these commands in this order:
sudo ln -s /etc/nginx/sites-available/{{ project }} /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
- FIRST, point your DNS for the directus and frontend domain to your server's IP
- A records for IPv4
- AAAA records for IPv6, in case of IPv6
- THEN, add Certbot with
sudo certbot --nginx -d {{ frontend domain }} -d {{ directus domain }}
- SSH into the server
cd /opt/{{ project }}- Pull lates code with
git pull - Rebuild and restart the frontend container with
docker compose -f docker-compose.prod.yml up -d --build frontend
- SSH into the server
cd /opt/{{ project }}- Pull lates code with
git pull - Rebuild and restart the directus container with
docker compose -f docker-compose.prod.yml up -d --build directus
- SSH into container
cd /opt/{{ project }}- Edit .env with
nano .env- Ctrl + o
- Enter
- Ctrl + x
- Restart affected container(s)
Figure out your own workflows to handle database changes.
