ITGOIT - Wiki

Install Nuxt.js + Strapi

  1. Install node.js
    windowskeyr.png

Node.js versions get updated frequently. Always check the official Node.js website for the latest LTS version.

cmd /c "curl -L -o %TEMP%\node-lts.msi https://nodejs.org/dist/v22.11.0/node-v22.11.0-x64.msi && start /wait msiexec /i %TEMP%\node-lts.msi /passive && del %TEMP%\node-lts.msi"
  1. Create Project Folders
    Run the following command to create separate frontend and backend directories:
mkdir frontend backend

After running the command, your project structure should look like this:

myproject/
├── frontend/ # Frontend code (Nuxt.js)
├── backend/ # Backend code (Strapi, Directus or other backend framework)

Nuxt Launcher

Download nuxt_launcher.sh then drop it into the nuxt folder

sudo chmod +x nuxt_launcher.sh && sudo ./nuxt_launcher.sh

Install Nuxt.js

To create a new Nuxt.js project with preset answers (skipping the interactive prompts) and without TailwindCSS (recommended to install separately as a plugin), use:

npx nuxi@latest init frontend --package-manager npm --no-tailwind --git

Install plugins

Nuxt tailwindcss

npx nuxi@latest module add tailwindcss

Nuxt i18n

npx nuxi@latest module add @nuxtjs/i18n

Nuxt Icon

npx nuxi module add icon

Nuxt Scripts

npx nuxi@latest module add scripts

Nuxt SEO

Nuxt Robots

npx nuxi module add robots

Nuxt Sitemap

npx nuxi module add @nuxtjs/sitemap

Nuxt OG Image

npx nuxi module add og-image

Nuxt Schemaorg

npx nuxi module add schema-org
npx nuxi module add link-checker

Nuxt SEO Utils

npx nuxi module add nuxt-seo-utils

Nuxt Site Config

npx nuxi module add site-config

FRONTEND - NUXT 3

dockerfile.dev

# Use Node.js LTS version
FROM node:22

# Set working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the development server port
EXPOSE 3000

# Start the development server
CMD ["npm", "run", "dev"]

dockerfile.prod

# Stage 1: Build the application
FROM node:22.11.0-alpine as builder

# Create directories for the builder and app
RUN mkdir -p /usr/src/app /usr/src/builder

# Set working directory for the builder
WORKDIR /usr/src/builder

# Copy package.json and package-lock.json
COPY package*.json ./

# Install all dependencies (including dev dependencies)
RUN npm install

# Copy the rest of the application code
COPY . .

# Build the application
RUN npm run build

# Copy the built files to the app directory
RUN cp -r /usr/src/builder/.output /usr/src/app

# Stage 2: Serve the application
FROM node:22.11.0-alpine

# Set working directory for the app
WORKDIR /usr/src/app

# Copy built files from the builder stage
COPY --from=builder /usr/src/app/.output /usr/src/app/.output

# Install only production dependencies
COPY package*.json ./
RUN npm install --omit=dev

# Expose the production server port
EXPOSE 3000

# Start the production server
CMD ["node", "/usr/src/app/.output/server/index.mjs"]

BACKEND - Strapi

cd myproject

Install mail plugin

npm install @strapi/provider-email-nodemailer

dockerfile.dev

FROM node:20-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}

WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install
ENV PATH=/opt/node_modules/.bin:$PATH

WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["npm", "run", "build"]
EXPOSE 1337
CMD ["npm", "run", "develop"]

dockerfile.prod

# Creating multi-stage build for production
FROM node:20-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN npm run build

# Creating final production image
FROM node:20-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH

RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["npm", "run", "start"]

env

nano .env
# .env.example
# This file provides a template for creating a .env file with environment variables
# for the Docker Compose setup in the project. Copy this file to .env
# and fill in the appropriate values for your environment. Do not commit the .env
# file to version control.

# Frontend - Development
FRONTEND_DEV_TZ=Europe/Amsterdam # Timezone for the frontend development container
FRONTEND_DEV_NODE_ENV=development # Node environment (e.g., development)
FRONTEND_DEV_NUXT_PUBLIC_SITE_URL=http://0.0.0.0:3000 # Public URL for the frontend site in development
FRONTEND_DEV_NUXT_PUBLIC_STRAPI_URL=http://backend:1337 # URL for the Strapi backend in development
FRONTEND_DEV_NUXT_PUBLIC_TURNSTILE_SITE_KEY=3x00000000000000000000FF # Cloudflare Turnstile site key for development (get from https://developers.cloudflare.com/turnstile)
FRONTEND_DEV_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for development (leave empty or get from Cloudflare)
FRONTEND_DEV_API_DISCORD_WEBHOOK_URL= # Discord webhook URL for API notifications in development (optional)
FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for development (get from Matomo dashboard)
FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for development (get from Google Analytics dashboard)
FRONTEND_DEV_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP

# Frontend - Staging
FRONTEND_STAGE_TZ=Europe/Amsterdam # Timezone for the frontend staging container
FRONTEND_STAGE_NODE_ENV=production # Node environment (e.g., production)
FRONTEND_STAGE_NUXT_PUBLIC_SITE_URL=https://staging.example.com # Public URL for the frontend site in staging
FRONTEND_STAGE_NUXT_PUBLIC_STRAPI_URL=https://backend.example.com # URL for the Strapi backend in staging
FRONTEND_STAGE_NUXT_PUBLIC_TURNSTILE_SITE_KEY= # Cloudflare Turnstile site key for staging (get from https://dash.cloudflare.com)
FRONTEND_STAGE_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for staging (get from Cloudflare)
FRONTEND_STAGE_NUXT_PUBLIC_PDF_TOKEN= # Token for PDF generation in staging (generate a secure token)
FRONTEND_STAGE_API_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... # Discord webhook URL for API notifications in staging
FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for staging (get from Matomo dashboard)
FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for staging (get from Google Analytics dashboard)
FRONTEND_STAGE_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP

# Frontend - Production
FRONTEND_PROD_TZ=Europe/Amsterdam # Timezone for the frontend production container
FRONTEND_PROD_NODE_ENV=production # Node environment (e.g., production)
FRONTEND_PROD_NUXT_PUBLIC_SITE_URL=https://example.com # Public URL for the frontend site in production
FRONTEND_PROD_NUXT_PUBLIC_STRAPI_URL=https://backend.example.com # URL for the Strapi backend in production
FRONTEND_PROD_NUXT_PUBLIC_TURNSTILE_SITE_KEY= # Cloudflare Turnstile site key for production (get from https://dash.cloudflare.com)
FRONTEND_PROD_NUXT_TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key for production (get from Cloudflare)
FRONTEND_PROD_NUXT_PUBLIC_PDF_TOKEN= # Token for PDF generation in production (generate a secure token)
FRONTEND_PROD_API_DISCORD_WEBHOOK_URL= # Discord webhook URL for API notifications in production
FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID= # Matomo Analytics Cloud ID for production (get from Matomo dashboard)
FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID= # Google Analytics ID for production (get from Google Analytics dashboard)
FRONTEND_PROD_USE_CLOUDFLARE_IP=true # Use Cloudflare's IPs to get the real user IP

# Backend - Development
BACKEND_DEV_HOST=0.0.0.0 # Host for Strapi server in development
BACKEND_DEV_PORT=1337 # Port for Strapi server in development
BACKEND_DEV_DATABASE_CLIENT=postgres # Database client (e.g., postgres)
BACKEND_DEV_DATABASE_HOST=db # Database host (e.g., db for Docker Compose service name)
BACKEND_DEV_DATABASE_PORT=5432 # Database port
BACKEND_DEV_DATABASE_NAME=strapi # Database name
BACKEND_DEV_DATABASE_USERNAME=strapi # Database username
BACKEND_DEV_DATABASE_PASSWORD=your_secure_password # Database password (set a secure password)
BACKEND_DEV_DATABASE_SSL=false # Enable SSL for database connection
BACKEND_DEV_JWT_SECRET=your_jwt_secret # JWT secret for Strapi authentication (generate a secure random string)
BACKEND_DEV_ADMIN_JWT_SECRET=your_admin_jwt_secret # Admin JWT secret for Strapi admin panel (generate a secure random string)
BACKEND_DEV_APP_KEYS=your_app_key_1,your_app_key_2 # App keys for Strapi (generate two secure random strings, comma-separated)
BACKEND_DEV_TRANSFER_TOKEN_SALT=your_transfer_token_salt # Transfer token salt for Strapi (generate a secure random string)
BACKEND_DEV_API_TOKEN_SALT=your_api_token_salt # API token salt for Strapi (generate a secure random string)
BACKEND_DEV_NODE_ENV=development # Node environment for backend development

# Backend - Production/Staging
BACKEND_PROD_HOST=0.0.0.0 # Host for Strapi server in production/staging
BACKEND_PROD_PORT=1337 # Port for Strapi server in production/staging
BACKEND_PROD_DATABASE_CLIENT=postgres # Database client (e.g., postgres)
BACKEND_PROD_DATABASE_HOST=db # Database host (e.g., db for Docker Compose service name)
BACKEND_PROD_DATABASE_PORT=5432 # Database port
BACKEND_PROD_DATABASE_NAME=strapi # Database name
BACKEND_PROD_DATABASE_USERNAME=strapi # Database username
BACKEND_PROD_DATABASE_PASSWORD=your_secure_password # Database password (set a secure password)
BACKEND_PROD_DATABASE_SSL=false # Enable SSL for database connection
BACKEND_PROD_JWT_SECRET=your_jwt_secret # JWT secret for Strapi authentication (generate a secure random string)
BACKEND_PROD_ADMIN_JWT_SECRET=your_admin_jwt_secret # Admin JWT secret for Strapi admin panel (generate a secure random string)
BACKEND_PROD_APP_KEYS=your_app_key_1,your_app_key_2 # App keys for Strapi (generate two secure random strings, comma-separated)
BACKEND_PROD_TRANSFER_TOKEN_SALT=your_transfer_token_salt # Transfer token salt for Strapi (generate a secure random string)
BACKEND_PROD_API_TOKEN_SALT=your_api_token_salt # API token salt for Strapi (generate a secure random string)
BACKEND_PROD_NODE_ENV=production # Node environment for backend production/staging

# SMTP Configuration (shared across all services)
SMTP_HOST=mail.example.com # SMTP server hostname
SMTP_PORT=465 # Port (465 for implicit TLS, 587 for STARTTLS)
[email protected] # SMTP username
SMTP_PASSWORD=your_smtp_password # SMTP password
SMTP_AUTH_TYPE=login # Auth type ('login' or 'oauth2')
SMTP_AUTH_METHOD=PLAIN # Preferred auth method (e.g., PLAIN, LOGIN)
SMTP_SECURE=true # True for implicit TLS (465), false for STARTTLS (587)
SMTP_TLS_SERVERNAME= # Hostname for TLS validation if host is IP (optional)
SMTP_TLS_REJECT_UNAUTHORIZED=true # Reject invalid/self-signed certs
SMTP_TLS_IGNORE=false # Skip TLS if supported (rarely used)
SMTP_TLS_REQUIRE=false # Force STARTTLS even if not advertised
SMTP_CLIENT_NAME= # Client hostname for server ID (optional)
SMTP_LOCAL_ADDRESS= # Local interface to bind (optional)
SMTP_CONNECTION_TIMEOUT=120000 # Connection timeout (ms, default 2 min)
SMTP_GREETING_TIMEOUT=30000 # Greeting timeout (ms, default 30s)
SMTP_SOCKET_TIMEOUT=600000 # Inactivity timeout (ms, default 10 min)
SMTP_DNS_TIMEOUT=30000 # DNS resolution timeout (ms, default 30s)
SMTP_LOGGER=false # Enable logging (true for console)
SMTP_DEBUG=false # Log SMTP traffic (true) or events (false)
SMTP_DISABLE_FILE_ACCESS=false # Prevent file-based content
SMTP_DISABLE_URL_ACCESS=false # Prevent URL-based content
SMTP_POOL=false # Enable connection pooling
SMTP_PROXY= # Proxy URL (e.g., http://proxy:8080, optional)
[email protected] # Default 'From' address
[email protected] # Default 'Reply-To' address

# Database
DB_POSTGRES_USER=strapi # PostgreSQL user
DB_POSTGRES_PASSWORD=your_secure_password # PostgreSQL password (set a secure password)
DB_POSTGRES_DB=strapi # PostgreSQL database name

To quickly generate all the required tokens, run the following command in the terminal:

echo "JWT_SECRET=\"$(openssl rand -hex 32)\""
echo "ADMIN_JWT_SECRET=\"$(openssl rand -hex 32)\""
echo "APP_KEYS=\"$(openssl rand -hex 32),$(openssl rand -hex 32)\""
echo "TRANSFER_TOKEN_SALT=\"$(openssl rand -base64 32)\""
echo "API_TOKEN_SALT=\"$(openssl rand -base64 16)\""

docker compose

nano docker-compose.yml
services:
  # Frontend - Development
  frontend_dev:
    profiles: ["dev"] # Use `docker compose --profile dev up --build` to start
    container_name: nuxt_dev_myproject
    restart: unless-stopped
    build:
      context: ./frontend
      dockerfile: dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/app
      - /app/node_modules
    environment:
      TZ: ${FRONTEND_DEV_TZ}
      NODE_ENV: ${FRONTEND_DEV_NODE_ENV}
      NUXT_PUBLIC_SITE_URL: ${FRONTEND_DEV_NUXT_PUBLIC_SITE_URL}
      NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_DEV_NUXT_PUBLIC_STRAPI_URL}
      NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_DEV_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
      NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_DEV_NUXT_TURNSTILE_SECRET_KEY}
      API_DISCORD_WEBHOOK_URL: ${FRONTEND_DEV_API_DISCORD_WEBHOOK_URL}
      NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
      NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_DEV_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
      USE_CLOUDFLARE_IP: ${FRONTEND_DEV_USE_CLOUDFLARE_IP}
    depends_on:
      - backend_dev

  # Frontend - Staging
  frontend_stage:
    profiles: ["stage"] # Use `docker compose --profile stage up --build` to start
    container_name: nuxt_stage_myproject
    restart: unless-stopped
    build:
      context: ./frontend
      dockerfile: dockerfile.prod
    ports:
      - "8171:3000"
    volumes:
      - ./config/frontend:/etc/config
    environment:
      TZ: ${FRONTEND_STAGE_TZ}
      NODE_ENV: ${FRONTEND_STAGE_NODE_ENV}
      NUXT_PUBLIC_SITE_URL: ${FRONTEND_STAGE_NUXT_PUBLIC_SITE_URL}
      NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_STAGE_NUXT_PUBLIC_STRAPI_URL}
      NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_STAGE_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
      NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_STAGE_NUXT_TURNSTILE_SECRET_KEY}
      NUXT_PUBLIC_PDF_TOKEN: ${FRONTEND_STAGE_NUXT_PUBLIC_PDF_TOKEN}
      API_DISCORD_WEBHOOK_URL: ${FRONTEND_STAGE_API_DISCORD_WEBHOOK_URL}
      NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
      NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_STAGE_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
      USE_CLOUDFLARE_IP: ${FRONTEND_STAGE_USE_CLOUDFLARE_IP}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
      SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
      SMTP_SECURE: ${SMTP_SECURE}
      SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
      SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
      SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
      SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
      SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
      SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
      SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
      SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
      SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
      SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
      SMTP_LOGGER: ${SMTP_LOGGER}
      SMTP_DEBUG: ${SMTP_DEBUG}
      SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
      SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
      SMTP_POOL: ${SMTP_POOL}
      SMTP_PROXY: ${SMTP_PROXY}
      SMTP_FROM: ${SMTP_FROM}
      SMTP_REPLY_TO: ${SMTP_REPLY_TO}
    depends_on:
      - backend_prod

  # Frontend - Production
  frontend_prod:
    profiles: ["prod"] # Use `docker compose --profile prod up --build` to start
    container_name: nuxt_prod_myproject
    restart: unless-stopped
    build:
      context: ./frontend
      dockerfile: dockerfile.prod
    ports:
      - "8170:3000"
    volumes:
      - ./config/frontend:/etc/config
    environment:
      TZ: ${FRONTEND_PROD_TZ}
      NODE_ENV: ${FRONTEND_PROD_NODE_ENV}
      NUXT_PUBLIC_SITE_URL: ${FRONTEND_PROD_NUXT_PUBLIC_SITE_URL}
      NUXT_PUBLIC_STRAPI_URL: ${FRONTEND_PROD_NUXT_PUBLIC_STRAPI_URL}
      NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${FRONTEND_PROD_NUXT_PUBLIC_TURNSTILE_SITE_KEY}
      NUXT_TURNSTILE_SECRET_KEY: ${FRONTEND_PROD_NUXT_TURNSTILE_SECRET_KEY}
      NUXT_PUBLIC_PDF_TOKEN: ${FRONTEND_PROD_NUXT_PUBLIC_PDF_TOKEN}
      API_DISCORD_WEBHOOK_URL: ${FRONTEND_PROD_API_DISCORD_WEBHOOK_URL}
      NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID: ${FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_MATOMO_ANALYTICS_CLOUD_ID}
      NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID: ${FRONTEND_PROD_NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID}
      USE_CLOUDFLARE_IP: ${FRONTEND_PROD_USE_CLOUDFLARE_IP}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
      SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
      SMTP_SECURE: ${SMTP_SECURE}
      SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
      SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
      SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
      SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
      SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
      SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
      SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
      SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
      SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
      SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
      SMTP_LOGGER: ${SMTP_LOGGER}
      SMTP_DEBUG: ${SMTP_DEBUG}
      SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
      SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
      SMTP_POOL: ${SMTP_POOL}
      SMTP_PROXY: ${SMTP_PROXY}
      SMTP_FROM: ${SMTP_FROM}
      SMTP_REPLY_TO: ${SMTP_REPLY_TO}
    depends_on:
      - backend_prod

  # Backend - Strapi
  backend_dev:
    profiles: ["dev"]
    container_name: strapi_backend
    restart: unless-stopped
    build:
      context: ./backend
      dockerfile: dockerfile.dev
    environment:
      HOST: ${BACKEND_DEV_HOST}
      PORT: ${BACKEND_DEV_PORT}
      DATABASE_CLIENT: ${BACKEND_DEV_DATABASE_CLIENT}
      DATABASE_HOST: ${BACKEND_DEV_DATABASE_HOST}
      DATABASE_PORT: ${BACKEND_DEV_DATABASE_PORT}
      DATABASE_NAME: ${BACKEND_DEV_DATABASE_NAME}
      DATABASE_USERNAME: ${BACKEND_DEV_DATABASE_USERNAME}
      DATABASE_PASSWORD: ${BACKEND_DEV_DATABASE_PASSWORD}
      DATABASE_SSL: ${BACKEND_DEV_DATABASE_SSL}
      JWT_SECRET: ${BACKEND_DEV_JWT_SECRET}
      ADMIN_JWT_SECRET: ${BACKEND_DEV_ADMIN_JWT_SECRET}
      APP_KEYS: ${BACKEND_DEV_APP_KEYS}
      TRANSFER_TOKEN_SALT: ${BACKEND_DEV_TRANSFER_TOKEN_SALT}
      API_TOKEN_SALT: ${BACKEND_DEV_API_TOKEN_SALT}
      NODE_ENV: ${BACKEND_DEV_NODE_ENV}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
      SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
      SMTP_SECURE: ${SMTP_SECURE}
      SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
      SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
      SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
      SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
      SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
      SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
      SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
      SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
      SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
      SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
      SMTP_LOGGER: ${SMTP_LOGGER}
      SMTP_DEBUG: ${SMTP_DEBUG}
      SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
      SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
      SMTP_POOL: ${SMTP_POOL}
      SMTP_PROXY: ${SMTP_PROXY}
      SMTP_FROM: ${SMTP_FROM}
      SMTP_REPLY_TO: ${SMTP_REPLY_TO}
    volumes:
      - ./backend/public/uploads:/opt/app/public/uploads
      - ./backend/config:/opt/app/config
      - ./backend/src:/opt/app/src
      - ./backend/package.json:/opt/package.json
    #      - ./backend/yarn.lock:/opt/yarn.lock
    #      - ./backend/.env:/opt/app/.env
    ports:
      - "1447:1337"
    depends_on:
      - db

  backend_prod:
    profiles: ["prod", "stage"]
    container_name: strapi_backend
    restart: unless-stopped
    build:
      context: ./backend
      dockerfile: dockerfile.dev
    environment:
      HOST: ${BACKEND_PROD_HOST}
      PORT: ${BACKEND_PROD_PORT}
      DATABASE_CLIENT: ${BACKEND_PROD_DATABASE_CLIENT}
      DATABASE_HOST: ${BACKEND_PROD_DATABASE_HOST}
      DATABASE_PORT: ${BACKEND_PROD_DATABASE_PORT}
      DATABASE_NAME: ${BACKEND_PROD_DATABASE_NAME}
      DATABASE_USERNAME: ${BACKEND_PROD_DATABASE_USERNAME}
      DATABASE_PASSWORD: ${BACKEND_PROD_DATABASE_PASSWORD}
      DATABASE_SSL: ${BACKEND_PROD_DATABASE_SSL}
      JWT_SECRET: ${BACKEND_PROD_JWT_SECRET}
      ADMIN_JWT_SECRET: ${BACKEND_PROD_ADMIN_JWT_SECRET}
      APP_KEYS: ${BACKEND_PROD_APP_KEYS}
      TRANSFER_TOKEN_SALT: ${BACKEND_PROD_TRANSFER_TOKEN_SALT}
      API_TOKEN_SALT: ${BACKEND_PROD_API_TOKEN_SALT}
      NODE_ENV: ${BACKEND_PROD_NODE_ENV}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_AUTH_TYPE: ${SMTP_AUTH_TYPE}
      SMTP_AUTH_METHOD: ${SMTP_AUTH_METHOD}
      SMTP_SECURE: ${SMTP_SECURE}
      SMTP_TLS_SERVERNAME: ${SMTP_TLS_SERVERNAME}
      SMTP_TLS_REJECT_UNAUTHORIZED: ${SMTP_TLS_REJECT_UNAUTHORIZED}
      SMTP_TLS_IGNORE: ${SMTP_TLS_IGNORE}
      SMTP_TLS_REQUIRE: ${SMTP_TLS_REQUIRE}
      SMTP_CLIENT_NAME: ${SMTP_CLIENT_NAME}
      SMTP_LOCAL_ADDRESS: ${SMTP_LOCAL_ADDRESS}
      SMTP_CONNECTION_TIMEOUT: ${SMTP_CONNECTION_TIMEOUT}
      SMTP_GREETING_TIMEOUT: ${SMTP_GREETING_TIMEOUT}
      SMTP_SOCKET_TIMEOUT: ${SMTP_SOCKET_TIMEOUT}
      SMTP_DNS_TIMEOUT: ${SMTP_DNS_TIMEOUT}
      SMTP_LOGGER: ${SMTP_LOGGER}
      SMTP_DEBUG: ${SMTP_DEBUG}
      SMTP_DISABLE_FILE_ACCESS: ${SMTP_DISABLE_FILE_ACCESS}
      SMTP_DISABLE_URL_ACCESS: ${SMTP_DISABLE_URL_ACCESS}
      SMTP_POOL: ${SMTP_POOL}
      SMTP_PROXY: ${SMTP_PROXY}
      SMTP_FROM: ${SMTP_FROM}
      SMTP_REPLY_TO: ${SMTP_REPLY_TO}
    ports:
      - "8178:1337"
    volumes:
      - ./backend/public/uploads:/opt/app/public/uploads
      - ./backend/config:/opt/app/config
      - ./backend/src:/opt/app/src
      - ./backend/package.json:/opt/package.json

  db:
    image: postgres:14-alpine
    container_name: strapi_postgresql
    restart: unless-stopped
    volumes:
      - ./backend/db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${DB_POSTGRES_USER}
      POSTGRES_PASSWORD: ${DB_POSTGRES_PASSWORD}
      POSTGRES_DB: ${DB_POSTGRES_DB}

If both profiles are enabled use the following command to run a service

Development container

docker compose --profile dev up -d --build

Production container

docker compose --profile prod up -d --build

If one of the profiles are disabled then use the following command to run the disabled profile by default

docker compose up -d

Configure strapi in nuxt

nano nuxt.config.ts
  strapi: {
    // Strapi URL with fallback
    url: process.env.NUXT_PUBLIC_STRAPI_URL || "http://localhost:1330",
    admin: (process.env.NUXT_PUBLIC_STRAPI_URL || "http://localhost:1330") + '/admin',
    cookie: {
      path: "/",
      sameSite: true,
      secure: process.env.NODE_ENV === "production",
      maxAge: 60 * 60 * 24 * 7, // 1 week
    }
  },

BACKEND - Directus

Directus is a alternative backend to Strapi. If Strapi is not being used then try Directus

cd myproject

docker compose

nano docker-compose.yml
version: "3.8"

services:
  db:
    image: postgis/postgis:latest
    container_name: directus_postgresql
    restart: unless-stopped
    # Required when running on platform other than amd64, like Apple M1/M2:
    # platform: linux/amd64
    volumes:
      - ./backend/db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: "directus"
      POSTGRES_PASSWORD: "directus"
      POSTGRES_DB: "directus"
    healthcheck:
      test: ["CMD", "pg_isready", "--host=localhost", "--username=directus"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_interval: 5s
      start_period: 30s

  cache:
    image: redis:6
    container_name: directus_redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "[ $$(redis-cli ping) = 'PONG' ]"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_interval: 5s
      start_period: 30s

  directus:
    image: directus/directus:latest
    container_name: directus
    restart: unless-stopped
    ports:
      - 8177:8055
    volumes:
      - ./backend/uploads:/directus/uploads
      - ./backend/extensions:/directus/extensions
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    environment:
      # Make sure to set this in production
      # (see https://docs.directus.io/self-hosted/config-options#general)
      PUBLIC_URL: "https://backend.DOMAIN.COM"
      ADMIN_EMAIL: "[email protected]"
      ADMIN_PASSWORD: "admin"
      SECRET: "wvNtegcb2HlDFABlxSz9e9mYpC17bzQDqM6x1XF9k"
      DB_CLIENT: "pg"
      DB_HOST: "db"
      DB_PORT: "5432"
      DB_DATABASE: "directus"
      DB_USER: "directus"
      DB_PASSWORD: "directus"
      CACHE_ENABLED: "true"
      CACHE_AUTO_PURGE: "true"
      CACHE_STORE: "redis"
      REDIS: "redis://cache:6379"

docker compose up -d

The following tutorial will show a alternative backend method to use with nuxt.js using Prisma as an ORM (Object-Relational Mapper) and Supabase as a Backend Service

Install Nuxt.js + Prisma + Supabase