NestJS + React + gRPC + MongoDB Boilerplate

A complete microservice architecture with modern technologies

Node.js
React
gRPC
MongoDB
Microservices

Backend Features

  • NestJS framework
  • gRPC communication
  • MongoDB integration
  • JWT Authentication
  • Validation pipes

Frontend Features

  • React with TypeScript
  • gRPC-Web client
  • Tailwind CSS
  • React Router
  • Authentication flow

DevOps Features

  • Docker setup
  • Environment config
  • Pre-commit hooks
  • API documentation
  • Logging system

Architecture Overview

Architecture Overview

Quick Start

Prerequisites

  • Node.js 16+
  • npm 8+ or yarn
  • Docker (for MongoDB)
  • Protobuf compiler (protoc)

1. Install NestJS CLI

npm install -g @nestjs/cli

2. Create new project

nest new backend --package-manager npm
cd backend

3. Install required packages

npm install @nestjs/microservices @grpc/grpc-js @grpc/proto-loader
npm install mongoose @nestjs/mongoose
npm install @nestjs/config
npm install bcrypt jsonwebtoken
npm install class-validator class-transformer

4. Create proto file (src/proto/auth.proto)

syntax = "proto3";

package auth;

service AuthService {
  rpc Register (RegisterRequest) returns (RegisterResponse) {}
  rpc Login (LoginRequest) returns (LoginResponse) {}
  rpc Validate (ValidateRequest) returns (ValidateResponse) {}
}

message RegisterRequest {
  string email = 1;
  string password = 2;
}

message RegisterResponse {
  int32 status = 1;
  string error = 2;
}

message LoginRequest {
  string email = 1;
  string password = 2;
}

message LoginResponse {
  int32 status = 1;
  string error = 2;
  string token = 3;
}

message ValidateRequest {
  string token = 1;
}

message ValidateResponse {
  int32 status = 1;
  string error = 2;
  string userId = 3;
}

5. Generate TypeScript interfaces from proto

npm install -g ts-proto
protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
  --ts_proto_out=./src/proto \
  --ts_proto_opt=nestJs=true \
  --proto_path=./src/proto \
  ./src/proto/auth.proto

6. Configure main.ts for gRPC

import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // gRPC microservice
  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.GRPC,
    options: {
      package: 'auth',
      protoPath: join(__dirname, 'proto/auth.proto'),
      url: '0.0.0.0:50051'
    }
  });

  await app.startAllMicroservices();
  await app.listen(3000);
}
bootstrap();

1. Create React app

npx create-react-app frontend --template typescript
cd frontend

2. Install required packages

npm install @grpc/grpc-web google-protobuf
npm install axios react-router-dom
npm install tailwindcss postcss autoprefixer
npx tailwindcss init -p

3. Configure tailwind.config.js

module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

4. Generate gRPC-Web client

# First copy the proto file from backend to frontend
cp ../backend/src/proto/auth.proto src/proto/

# Install protoc-gen-grpc-web
# Download from https://github.com/grpc/grpc-web/releases
# Then generate the client code
protoc -I=./src/proto auth.proto \
  --js_out=import_style=commonjs,binary:./src/proto \
  --grpc-web_out=import_style=typescript,mode=grpcwebtext:./src/proto

5. Create gRPC client service

import { AuthServiceClient } from './proto/auth_pb_service';
import { RegisterRequest, LoginRequest, ValidateRequest } from './proto/auth_pb';

const client = new AuthServiceClient('http://localhost:8080');

export const register = (email: string, password: string) => {
  const request = new RegisterRequest();
  request.setEmail(email);
  request.setPassword(password);

  return new Promise((resolve, reject) => {
    client.register(request, (err, response) => {
      if (err) return reject(err);
      resolve(response.toObject());
    });
  });
};

1. Create docker-compose.yml

version: '3.8'

services:
  mongodb:
    image: mongo:6.0
    container_name: mongodb
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
    volumes:
      - mongodb_data:/data/db

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
      - "50051:50051"
    depends_on:
      - mongodb
    environment:
      MONGO_URI: mongodb://root:example@mongodb:27017
      JWT_SECRET: your-secret-key

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    depends_on:
      - backend

  envoy:
    image: envoyproxy/envoy:v1.22.0
    volumes:
      - ./envoy.yaml:/etc/envoy/envoy.yaml
    ports:
      - "8081:8081"
      - "9901:9901"
    depends_on:
      - backend

volumes:
  mongodb_data:

2. Create backend Dockerfile

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000 50051

CMD ["npm", "run", "start:prod"]

3. Create frontend Dockerfile

FROM node:18-alpine as build

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM nginx:alpine

COPY --from=build /app/build /usr/share/nginx/html

COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

4. Create envoy.yaml for gRPC-Web

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8081 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: backend_service
                  timeout: 0s
                cors:
                  allow_origin_string_match:
                  - "*"
                  allow_methods: GET, PUT, DELETE, POST, OPTIONS
                  allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                  max_age: "1728000"
                  expose_headers: grpc-status,grpc-message
            http_filters:
            - name: envoy.filters.http.grpc_web
            - name: envoy.filters.http.cors
            - name: envoy.filters.http.router

  clusters:
  - name: backend_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    load_assignment:
      cluster_name: backend_service
      endpoints:
      - lb_endpoints:
        - endpoint:
          address:
            socket_address:
              address: backend
              port_value: 50051

5. Start the services

docker-compose up -d

Project Structure

Backend Structure

backend/
├── src/
│ ├── auth/ # Auth module
│ │ ├── dto/ # Data transfer objects
│ │ ├── entities/ # MongoDB schemas
│ │ ├── interfaces/ # Type interfaces
│ │ ├── auth.controller.ts # gRPC controller
│ │ ├── auth.service.ts # Business logic
│ │ └── auth.module.ts # NestJS module
│ ├── proto/ # Protobuf definitions
│ ├── app.module.ts # Root module
│ └── main.ts # Application entry
├── test/ # Test files
├── Dockerfile # Docker configuration
└── package.json # Dependencies

Frontend Structure

frontend/
├── src/
│ ├── components/ # React components
│ ├── pages/ # Page components
│ ├── proto/ # gRPC generated files
│ ├── services/ # API services
│ ├── store/ # State management
│ ├── App.tsx # Main component
│ └── index.tsx # Entry point
├── public/ # Static assets
├── Dockerfile # Docker configuration
└── package.json # Dependencies

Documentation

HTTP API Endpoints

Method Path Description
POST /api/auth/register Register a new user
POST /api/auth/login Login with credentials
GET /api/auth/validate Validate JWT token

Development Tips

  • Use npm run start:dev in backend for development with hot reload
  • For frontend development, proxy API requests to avoid CORS issues
  • Use BloomRPC or grpcurl to test gRPC services