diff --git a/.github/workflows/ssh-build.yml b/.github/workflows/ssh-build.yml index e03d2a0..e70ae80 100644 --- a/.github/workflows/ssh-build.yml +++ b/.github/workflows/ssh-build.yml @@ -45,7 +45,7 @@ jobs: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.PROD_NAME }}-server:latest build-args: | BUILD_MODE=prod - SERVER_DOMAIN=${{ env.SERVER_DOMAIN }} + APP_DOMAIN=${{ env.SERVER_DOMAIN }} ADMIN_DOMAIN=${{ env.ADMIN_DOMAIN }} - name: 'Build Client' @@ -59,8 +59,8 @@ jobs: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.PROD_NAME }}-client:latest build-args: | BUILD_MODE=prod - SERVER_DOMAIN=${{ env.SERVER_DOMAIN }} - APP_DOMAIN=${{ env.APP_DOMAIN }} + NEXT_PUBLIC_SERVER_DOMAIN=${{ env.SERVER_DOMAIN }} + NEXT_PUBLIC_APP_DOMAIN=${{ env.APP_DOMAIN }} - name: 'Build Admin' if: contains(github.event.pull_request.labels.*.name, 'frontend-admin') @@ -73,5 +73,5 @@ jobs: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.PROD_NAME }}-admin:latest build-args: | BUILD_MODE=prod - SERVER_DOMAIN=${{ env.SERVER_DOMAIN }} - ADMIN_DOMAIN=${{ env.ADMIN_DOMAIN }} + NEXT_PUBLIC_SERVER_DOMAIN=${{ env.SERVER_DOMAIN }} + NEXT_PUBLIC_APP_DOMAIN=${{ env.ADMIN_DOMAIN }} diff --git a/.github/workflows/ssh-deploy.yml b/.github/workflows/ssh-deploy.yml index f3cd57f..1358bde 100644 --- a/.github/workflows/ssh-deploy.yml +++ b/.github/workflows/ssh-deploy.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Run deploy on SSH' - if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == ${{ env.BRANCH_NAME }} + if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == ${{ env.BRANCH }} uses: appleboy/ssh-action@v1.0.0 with: host: ${{ vars.SSH_HOST }} @@ -29,7 +29,7 @@ jobs: password: ${{ secrets.SSH_PASSWORD }} port: ${{ vars.SSH_PORT }} script: | - cd ${{ env.PROJECT_SSH_FOLDER_NAME }} + cd ${{ env.PROJECT_SSH_FOLDER }} echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin if [[ "${{ contains(github.event.pull_request.labels.*.name, env.LABEL_SERVER) }}" == "true" ]]; then diff --git a/.gitignore b/.gitignore index ae37740..9884f5e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules .turbo .next dist +out # Uploads apps/server/public diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..42061c0 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +README.md \ No newline at end of file diff --git a/README.md b/README.md index c73f27d..783adb8 100644 --- a/README.md +++ b/README.md @@ -1 +1,188 @@ # Next-Nest-js-CI-on-VPS-Boilerplate + +## Overview + +This repository provides a boilerplate for setting up a Next.js and Nest.js project with Continuous Integration (CI) on a Virtual Private Server (VPS). It includes configurations for various tools and libraries to help you quickly get started with a modern web development stack. + +## Features + +- Next.js for the frontend +- Nest.js for the backend +- TypeScript for type safety +- Docker for containerization +- CI/CD with GitHub Actions +- Monorepo structure with PNPM Workspaces +- Prisma ORM for database management +- TailwindCSS for styling +- NextAuth for authentication +- tRPC for type-safe APIs +- NextUI for UI components +- Next-Intl for internationalization + +## Getting Started + +### Prerequisites + +Ensure you have the following installed: + +- Node.js +- PNPM +- Docker + +### Installation + +1. **Clone the repository** + + ```bash + git clone https://github.com/dmytro-komlyk/Next-Nest-js-CI-on-VPS-Boilerplate.git + cd Next-Nest-js-CI-on-VPS-Boilerplate + ``` + +2. **Install dependencies** + + ```bash + pnpm install + ``` + +3. **Setup environment variables** + + ```bash + cp apps/admin/.env.local.example apps/admin/.env.local + cp apps/client/.env.local.example apps/client/.env.local + cp apps/server/.env.example apps/server/.env + ``` + +### Running the Project + +To start the development environment: + + ```bash + pnpm dev + ``` + +This will concurrently run the Next.js and Nest.js applications. + +### Building for Production + +1. **To build the project for production:** + + ```bash + pnpm build + ``` + +2. **To start the production build:** + + ```bash + pnpm start + ``` + +### Docker development + +To run the project using Docker, use the provided docker-compose files. + +1. **Set up environment variables** + + ```bash + cp apps/admin/.env.docker.local.example apps/admin/.env.docker.local + cp apps/client/.env.docker.local.example apps/client/.env.docker.local + cp apps/server/.env.docker.local.example apps/server/.env.docker.local + ``` + +2. **Build and run Docker containers** + + ```bash + docker compose -f docker-compose.local.yml up -d + ``` + +## Deploy + +### CI/CD Pipeline + +This project uses GitHub Actions for continuous integration and continuous deployment. The configuration files are located in the .github/workflows directory. + +1. πŸ”’ **Set up your secrets and variables in a GitHub repository** + + ```bash + SSH_PASSWORD + SSH_USERNAME + ``` + + ```bash + ADMIN_DOMAIN + APP_DOMAIN + SERVER_DOMAIN + BRANCH_DEPLOYMENT + PROD_NAME + SSH_FOLDER + SSH_HOST + SSH_PORT + ``` + +2. 🏷️ **Set up labels in a GitHub repository** + + ```bash + backend + frontend-client + frontend-admin + ``` + +### VPS Π‘onfiguration + +1. **Connect to your VPS and run the following commands to install the required dependencies:** + + ```bash + sudo apt update + sudo apt install docker.io + sudo apt install docker-compose + ``` + +2. **Create structure, copy files and set up environment variables:** + + ```markdown + PROD_NAME + . + β”‚ + β”œβ”€β”€ client + β”‚ └── .env.docker.prod # + β”œβ”€β”€ admin + β”‚ └── .env.docker.prod # + β”œβ”€β”€ server + β”‚ └── .env.docker.prod # + β”œβ”€β”€ database + β”‚ β”œβ”€β”€ conf + β”‚ β”‚ └── mongod.conf.orig + β”‚ β”œβ”€β”€ seed + β”‚ β”‚ └── *.json + β”‚ β”œβ”€β”€ Dockerfile + β”‚ └── init-seed.sh + └── docker-compose.prod-ci.yml # + ``` + +3. **Run Docker containers:** + + ```bash + docker login ghcr.io -u + docker compose -f docker-compose.prod-ci.yml -p PROD_NAME pull + docker compose -f docker-compose.prod-ci.yml -p PROD_NAME up -d + ``` + +## Folder Structure + +```markdown +. +β”œβ”€β”€ .github +β”‚ └── workflows # CI/CD configurations +β”œβ”€β”€ .vscode # VSCode settings +β”œβ”€β”€ apps +β”‚ β”œβ”€β”€ admin # Next.js app +β”‚ β”œβ”€β”€ client # Next.js app +β”‚ β”œβ”€β”€ database # MongoDB +β”‚ └── server # Nest.js app +β”œβ”€β”€ packages +β”‚ └── eslint-config # Shared ESLint configuration +β”œβ”€β”€ docker-compose*.yml # Docker configurations +β”œβ”€β”€ pnpm-workspace.yaml # pnpm workspace configuration +β”œβ”€β”€ README.md # Project documentation +└── ... + +``` diff --git a/apps/admin/.env.docker.local.example b/apps/admin/.env.docker.local.example index 2eec6fb..ac46cd2 100644 --- a/apps/admin/.env.docker.local.example +++ b/apps/admin/.env.docker.local.example @@ -2,11 +2,16 @@ APP_PORT=3002 NEXT_PUBLIC_BASE_URL=http://localhost:3001 NEXT_PUBLIC_SERVER_URL=http://localhost:3000 +NEXT_PUBLIC_DOCKER_SERVICE_URL="http://server" NEXT_PUBLIC_SERVER_API_URL=http://localhost:3000/api NEXT_PUBLIC_SERVER_TRPC_URL=http://localhost:3000/api/trpc -NEXTAUTH_SECRET= + +#Auth +NEXTAUTH_SECRET= #openssl rand -base64 32 NEXTAUTH_URL=http://localhost:3001/api/auth NEXTAUTH_JWT_ACCESS_TOKEN_EXPIRATION='1d' +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= # This was inserted by `prisma init`: # Environment variables declared in this file are automatically made available to Prisma. diff --git a/apps/admin/.env.docker.prod.example b/apps/admin/.env.docker.prod.example index 5aef1f2..548f6b8 100644 --- a/apps/admin/.env.docker.prod.example +++ b/apps/admin/.env.docker.prod.example @@ -1,14 +1,19 @@ APP_PORT=3002 -APP_DOMAIN= -SERVER_DOMAIN= -NEXT_PUBLIC_BASE_URL="https://${APP_DOMAIN}" -NEXT_PUBLIC_SERVER_URL="https://${SERVER_DOMAIN}" -NEXT_PUBLIC_SERVER_API_URL="https://${SERVER_DOMAIN}/api" -NEXT_PUBLIC_SERVER_TRPC_URL="https://${SERVER_DOMAIN}/api/trpc" -NEXTAUTH_SECRET= -NEXTAUTH_URL="https://${APP_DOMAIN}/api/auth" +NEXT_PUBLIC_APP_DOMAIN= +NEXT_PUBLIC_SERVER_DOMAIN= +NEXT_PUBLIC_BASE_URL="http://${NEXT_PUBLIC_APP_DOMAIN}" +NEXT_PUBLIC_SERVER_URL="http://${NEXT_PUBLIC_SERVER_DOMAIN}" +NEXT_PUBLIC_DOCKER_SERVICE_URL="https://server" +NEXT_PUBLIC_SERVER_API_URL="http://${NEXT_PUBLIC_SERVER_DOMAIN}/api" +NEXT_PUBLIC_SERVER_TRPC_URL="http://${NEXT_PUBLIC_SERVER_DOMAIN}/api/trpc" + +#Auth +NEXTAUTH_SECRET= #openssl rand -base64 32 +NEXTAUTH_URL="http://${NEXT_PUBLIC_APP_DOMAIN}/api/auth" NEXTAUTH_JWT_ACCESS_TOKEN_EXPIRATION='1d' +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= # This was inserted by `prisma init`: # Environment variables declared in this file are automatically made available to Prisma. diff --git a/apps/admin/.env.local.example b/apps/admin/.env.local.example index b47240b..efe414f 100644 --- a/apps/admin/.env.local.example +++ b/apps/admin/.env.local.example @@ -6,7 +6,7 @@ NEXT_PUBLIC_SERVER_API_URL=http://localhost:3000/api NEXT_PUBLIC_SERVER_TRPC_URL=http://localhost:3000/api/trpc #Auth -NEXTAUTH_SECRET= +NEXTAUTH_SECRET= #openssl rand -base64 32 NEXTAUTH_URL=http://localhost:3002/api/auth NEXTAUTH_JWT_ACCESS_TOKEN_EXPIRATION='1d' GOOGLE_CLIENT_ID= @@ -20,7 +20,7 @@ GOOGLE_CLIENT_SECRET= # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_USERNAME= DATABASE_PASSWORD= -DATABASE_HOST=127.0.0.1 +DATABASE_HOST=localhost DATABASE_PORT=27017 DATABASE_NAME= DATABASE_URL="mongodb://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?replicaSet=rs0&retryWrites=true&w=majority&directConnection=true&authSource=admin" \ No newline at end of file diff --git a/apps/admin/Dockerfile b/apps/admin/Dockerfile index 23f442c..3d05615 100644 --- a/apps/admin/Dockerfile +++ b/apps/admin/Dockerfile @@ -23,7 +23,8 @@ RUN turbo prune --scope=${APP_NAME} --docker FROM base AS builder ARG APP_NAME=admin ARG BUILD_MODE=local -ARG APP_DOMAIN +ARG NEXT_PUBLIC_APP_DOMAIN +ARG NEXT_PUBLIC_SERVER_DOMAIN WORKDIR /app @@ -37,7 +38,8 @@ COPY --from=pruner /app/tsconfig.json ./tsconfig.json # First install the dependencies (as they change less often) RUN pnpm install -ENV APP_DOMAIN=$APP_DOMAIN +ENV NEXT_PUBLIC_APP_DOMAIN=$NEXT_PUBLIC_APP_DOMAIN +ENV NEXT_PUBLIC_SERVER_DOMAIN=$NEXT_PUBLIC_SERVER_DOMAIN ENV NEXT_TELEMETRY_DISABLED 1 COPY apps/${APP_NAME}/.env.docker.${BUILD_MODE}.example ./apps/${APP_NAME}/.env.local diff --git a/apps/client/.env.docker.prod.example b/apps/client/.env.docker.prod.example index 64832d8..4fb2916 100644 --- a/apps/client/.env.docker.prod.example +++ b/apps/client/.env.docker.prod.example @@ -1,10 +1,10 @@ APP_PORT=3001 -APP_DOMAIN= -SERVER_DOMAIN= -NEXT_PUBLIC_BASE_URL="https://${APP_DOMAIN}" -NEXT_PUBLIC_SERVER_URL="https://${SERVER_DOMAIN}" -NEXT_PUBLIC_SERVER_TRPC_URL="https://${SERVER_DOMAIN}/api/trpc" +NEXT_PUBLIC_APP_DOMAIN= +NEXT_PUBLIC_SERVER_DOMAIN= +NEXT_PUBLIC_BASE_URL="http://${NEXT_PUBLIC_APP_DOMAIN}" +NEXT_PUBLIC_SERVER_URL="http://${NEXT_PUBLIC_SERVER_DOMAIN}" +NEXT_PUBLIC_SERVER_TRPC_URL="http://${NEXT_PUBLIC_SERVER_DOMAIN}/api/trpc" # This was inserted by `prisma init`: # Environment variables declared in this file are automatically made available to Prisma. diff --git a/apps/client/.env.local.example b/apps/client/.env.local.example index 6ec7a7a..3ceb8de 100644 --- a/apps/client/.env.local.example +++ b/apps/client/.env.local.example @@ -12,7 +12,7 @@ NEXT_PUBLIC_SERVER_TRPC_URL=http://localhost:3000/trpc # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_USERNAME= DATABASE_PASSWORD= -DATABASE_HOST=127.0.0.1 +DATABASE_HOST=localhost DATABASE_PORT=27017 DATABASE_NAME= DATABASE_URL="mongodb://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?replicaSet=rs0&retryWrites=true&w=majority&directConnection=true&authSource=admin" \ No newline at end of file diff --git a/apps/client/Dockerfile b/apps/client/Dockerfile index dea07f2..0ff1018 100644 --- a/apps/client/Dockerfile +++ b/apps/client/Dockerfile @@ -36,11 +36,11 @@ COPY --from=pruner /app/tsconfig.json ./tsconfig.json RUN pnpm install ARG BUILD_MODE=local -ARG APP_DOMAIN -ARG SERVER_DOMAIN +ARG NEXT_PUBLIC_APP_DOMAIN +ARG NEXT_PUBLIC_SERVER_DOMAIN -ENV APP_DOMAIN=$APP_DOMAIN -ENV SERVER_DOMAIN=$SERVER_DOMAIN +ENV NEXT_PUBLIC_APP_DOMAIN=$NEXT_PUBLIC_APP_DOMAIN +ENV NEXT_PUBLIC_SERVER_DOMAIN=$NEXT_PUBLIC_SERVER_DOMAIN ENV NEXT_TELEMETRY_DISABLED 1 COPY apps/${APP_NAME}/.env.docker.${BUILD_MODE}.example ./apps/${APP_NAME}/.env.local diff --git a/apps/server/.env.docker.prod.example b/apps/server/.env.docker.prod.example index 11c1fa7..43f4f84 100644 --- a/apps/server/.env.docker.prod.example +++ b/apps/server/.env.docker.prod.example @@ -1,12 +1,12 @@ APP_PORT=3000 APP_DOMAIN= -SERVER_DOMAIN= +ADMIN_DOMAIN= APP_API=api APP_TRPC=trpc APP_SWAGER=api-docs APP_STATIC_ASSETS=public -APP_BASE_URL="https://${APP_DOMAIN}" -APP_ADMIN_URL="https://${SERVER_DOMAIN}" +APP_BASE_URL="http://${APP_DOMAIN}" +APP_ADMIN_URL="http://${ADMIN_DOMAIN}" # This was inserted by `prisma init`: # Environment variables declared in this file are automatically made available to Prisma. @@ -17,6 +17,6 @@ APP_ADMIN_URL="https://${SERVER_DOMAIN}" DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST=mongo -DATABASE_PORT=27018 +DATABASE_PORT=27017 DATABASE_NAME= DATABASE_URL="mongodb://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?replicaSet=rs0&retryWrites=true&w=majority&directConnection=true&authSource=admin" \ No newline at end of file diff --git a/apps/server/.env.example b/apps/server/.env.example index 890d3f7..ef6e67d 100644 --- a/apps/server/.env.example +++ b/apps/server/.env.example @@ -14,7 +14,7 @@ APP_ADMIN_URL=http://localhost:3002 # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_USERNAME= DATABASE_PASSWORD= -DATABASE_HOST=127.0.0.1 +DATABASE_HOST=localhost DATABASE_PORT=27017 DATABASE_NAME= DATABASE_URL="mongodb://${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?authSource=admin" diff --git a/apps/server/Dockerfile b/apps/server/Dockerfile index cd05717..c3f63d1 100644 --- a/apps/server/Dockerfile +++ b/apps/server/Dockerfile @@ -40,6 +40,11 @@ COPY --from=pruner /app/out/full/ . COPY .gitignore .gitignore RUN pnpm db:generate RUN turbo build --filter=${APP_NAME} + +# +COPY apps/${APP_NAME}/migrate-and-start.sh ./apps/${APP_NAME}/migrate-and-start.sh +RUN chmod +x /app/apps/${APP_NAME}/migrate-and-start.sh + RUN --mount=type=cache,id=pnpm,target=~/.pnpm-store pnpm prune --prod --no-optional RUN rm -rf ./**/*/src @@ -51,6 +56,7 @@ USER node WORKDIR /app COPY --from=builder --chown=node:node /app . + WORKDIR /app/apps/${APP_NAME} ARG PORT=3000 diff --git a/apps/server/package.json b/apps/server/package.json index 3395c7f..cde4dc6 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -32,6 +32,7 @@ "bcryptjs": "^2.4.3", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", + "express": "^4.19.2", "openapi-types": "^12.1.3", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", diff --git a/docker-compose.local.yml b/docker-compose.local.yml index eca72aa..a1551a5 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -38,7 +38,6 @@ services: interval: 5s timeout: 30s start_period: 0s - start_interval: 1s retries: 30 mongo-seed: diff --git a/docker-compose.prod-ci.yml b/docker-compose.prod-ci.yml index 804e815..659b5db 100644 --- a/docker-compose.prod-ci.yml +++ b/docker-compose.prod-ci.yml @@ -6,7 +6,7 @@ services: dockerfile: ./database/Dockerfile args: MONGO_VERSION: 6 - container_name: mongo + container_name: mongo-boilerplate environment: - MONGO_INITDB_ROOT_USERNAME= #USERNAME - MONGO_INITDB_ROOT_PASSWORD= #PASSWORD @@ -38,7 +38,6 @@ services: interval: 5s timeout: 30s start_period: 0s - start_interval: 1s retries: 30 mongo-seed: @@ -48,7 +47,7 @@ services: dockerfile: ./database/Dockerfile args: MONGO_VERSION: 6 - container_name: mongo-seed + container_name: mongo-seed-boilerplate networks: - backend depends_on: @@ -69,13 +68,15 @@ services: server: image: ghcr.io/dmytro-komlyk/nextjs-nestjs-boilerplate-server:latest - container_name: server + container_name: server-boilerplate restart: unless-stopped env_file: ./server/.env.docker.prod environment: - NODE_ENV=production volumes: - - ./server/public/:/app/server/public + - ./server/public/:/app/apps/server/public + - /app/node_modules + - /app/apps/server/node_modules - shared-prisma:/app/apps/server/prisma ports: - 3000:3000 @@ -88,13 +89,16 @@ services: admin: image: ghcr.io/dmytro-komlyk/nextjs-nestjs-boilerplate-admin:latest - container_name: admin + container_name: admin-boilerplate restart: unless-stopped env_file: ./admin/.env.docker.prod stdin_open: true tty: true environment: - NODE_ENV=production + volumes: + - /app/node_modules + - /app/apps/admin/node_modules ports: - 3002:3002 networks: @@ -103,13 +107,16 @@ services: client: image: ghcr.io/dmytro-komlyk/nextjs-nestjs-boilerplate-client:latest - container_name: client + container_name: client-boilerplate restart: unless-stopped env_file: ./client/.env.docker.prod stdin_open: true tty: true environment: - NODE_ENV=production + volumes: + - /app/node_modules + - /app/apps/client/node_modules ports: - 3001:3001 networks: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index b94d738..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: "3.8" -services: - mongo: - image: mongo:6.0 - container_name: mongo - hostname: mongo - environment: - - MONGO_INITDB_ROOT_USERNAME= - - MONGO_INITDB_ROOT_PASSWORD= - volumes: - - ./apps/database/data:/data/db - ports: - - 27017:27017 - networks: - - backend - - server: - build: - context: . - dockerfile: ./apps/server/Dockerfile - container_name: server - restart: unless-stopped - env_file: ./apps/server/.env.example - environment: - - DATABASE_USERNAME= - - DATABASE_PASSWORD= - - DATABASE_NAME= - - JWT_SECRET_KEY= - - JWT_REFRESH_TOKEN_KEY= - # volumes: - # - ../apps/server/public/:/app/server/public - ports: - - 3000:3000 - networks: - - frontend - - backend - depends_on: - - mongo - links: - - mongo - - admin: - build: - context: . - dockerfile: ./apps/admin/Dockerfile - container_name: admin - restart: unless-stopped - env_file: ./apps/admin/.env.example - stdin_open: true - tty: true - environment: - - NEXTAUTH_SECRET= - - GOOGLE_CLIENT_ID= - - GOOGLE_CLIENT_SECRET= - ports: - - "3002:3002" - networks: - - frontend - - client: - build: - context: . - dockerfile: ./apps/client/Dockerfile - container_name: client - restart: unless-stopped - env_file: ./apps/client/.env.example - # environment: - ports: - - "3001:3001" - networks: - - frontend - -networks: - frontend: - driver: bridge - backend: - driver: bridge - -volumes: - database: - driver: local diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b0a381..cde136e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -285,6 +285,9 @@ importers: class-validator: specifier: ^0.14.0 version: 0.14.1 + express: + specifier: ^4.19.2 + version: 4.19.2 openapi-types: specifier: ^12.1.3 version: 12.1.3