Skip to content

Commit f062913

Browse files
committed
feat: professional Node.js backend boilerplate with full-stack features
- Complete ES Modules migration (import/export) - Stripe payment integration with webhooks - Firebase Cloud Messaging for push notifications - Bull queues with Redis for background jobs - Product & Order management with full CRUD - Text search on products - Prometheus metrics for monitoring - Docker & Docker Compose setup - Jest testing framework with Supertest - ESLint, Prettier, Husky git hooks - GitHub Actions CI/CD pipeline - Comprehensive API documentation with Swagger - Database migrations with migrate-mongo - Email notifications with Nodemailer - Security: Helmet, XSS protection, rate limiting - Input validation with Joi - JWT authentication with refresh tokens - Role-based access control (RBAC) - Graceful shutdown handling - Complete README with installation instructions
0 parents  commit f062913

107 files changed

Lines changed: 7736 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Environment
2+
NODE_ENV=development
3+
4+
# Server
5+
PORT=3000
6+
BACKEND_IP=localhost
7+
8+
# Database
9+
MONGODB_URL=mongodb://localhost:27017/nodejs-backend
10+
11+
# Redis
12+
REDIS_HOST=localhost
13+
REDIS_PORT=6379
14+
REDIS_PASSWORD=
15+
16+
# JWT
17+
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
18+
JWT_ACCESS_EXPIRATION_MINUTES=30
19+
JWT_REFRESH_EXPIRATION_DAYS=30
20+
JWT_RESET_PASSWORD_EXPIRATION_MINUTES=10
21+
JWT_VERIFY_EMAIL_EXPIRATION_MINUTES=10
22+
23+
# Email (SMTP)
24+
SMTP_HOST=smtp.gmail.com
25+
SMTP_PORT=587
26+
SMTP_USERNAME=your-email@gmail.com
27+
SMTP_PASSWORD=your-app-password
28+
EMAIL_FROM=noreply@yourapp.com
29+
30+
# Stripe Payment
31+
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
32+
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
33+
34+
# Firebase Cloud Messaging
35+
FIREBASE_PROJECT_ID=your-firebase-project-id
36+
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYour Firebase Private Key\n-----END PRIVATE KEY-----\n"
37+
FIREBASE_CLIENT_EMAIL=firebase-adminsdk@your-project.iam.gserviceaccount.com
38+
39+
# AWS (Optional - for file uploads to S3)
40+
AWS_ACCESS_KEY_ID=your-aws-access-key
41+
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
42+
AWS_REGION=us-east-1
43+
S3_BUCKET_NAME=your-s3-bucket-name
44+
45+
# Client URL (for email links)
46+
CLIENT_URL=http://localhost:3000

.eslintrc.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"env": {
3+
"node": true,
4+
"es2022": true,
5+
"jest": true
6+
},
7+
"extends": ["airbnb-base", "prettier"],
8+
"plugins": ["jest"],
9+
"parserOptions": {
10+
"ecmaVersion": "latest",
11+
"sourceType": "module"
12+
},
13+
"rules": {
14+
"no-console": "warn",
15+
"no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
16+
"consistent-return": "off",
17+
"func-names": "off",
18+
"object-shorthand": "off",
19+
"no-process-exit": "off",
20+
"no-param-reassign": "off",
21+
"no-underscore-dangle": "off",
22+
"class-methods-use-this": "off",
23+
"prefer-destructuring": ["error", { "object": true, "array": false }],
24+
"no-unused-expressions": ["error", { "allowTaggedTemplates": true }],
25+
"import/extensions": ["error", "always"],
26+
"import/no-extraneous-dependencies": ["error", { "devDependencies": ["**/*.test.js", "**/*.spec.js", "tests/**/*"] }]
27+
}
28+
}

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Convert text file line endings to lf
2+
* text eol=lf
3+
*.js text

.github/workflows/ci-cd.yml

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [main, develop]
6+
pull_request:
7+
branches: [main, develop]
8+
9+
env:
10+
NODE_VERSION: '18.x'
11+
AWS_REGION: us-east-1
12+
13+
jobs:
14+
lint-and-test:
15+
name: Lint and Test
16+
runs-on: ubuntu-latest
17+
18+
services:
19+
mongodb:
20+
image: mongo:7.0
21+
ports:
22+
- 27017:27017
23+
redis:
24+
image: redis:7-alpine
25+
ports:
26+
- 6379:6379
27+
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
32+
- name: Setup Node.js
33+
uses: actions/setup-node@v4
34+
with:
35+
node-version: ${{ env.NODE_VERSION }}
36+
cache: 'npm'
37+
38+
- name: Install dependencies
39+
run: npm ci
40+
41+
- name: Run ESLint
42+
run: npm run lint
43+
44+
- name: Run Prettier check
45+
run: npm run format -- --check
46+
47+
- name: Run tests
48+
run: npm test
49+
env:
50+
NODE_ENV: test
51+
MONGODB_URL: mongodb://localhost:27017/test
52+
REDIS_HOST: localhost
53+
REDIS_PORT: 6379
54+
JWT_SECRET: test-secret-key
55+
56+
- name: Upload coverage reports
57+
uses: codecov/codecov-action@v3
58+
with:
59+
token: ${{ secrets.CODECOV_TOKEN }}
60+
files: ./coverage/lcov.info
61+
fail_ci_if_error: false
62+
63+
build:
64+
name: Build Docker Image
65+
runs-on: ubuntu-latest
66+
needs: lint-and-test
67+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
68+
69+
steps:
70+
- name: Checkout code
71+
uses: actions/checkout@v4
72+
73+
- name: Configure AWS credentials
74+
uses: aws-actions/configure-aws-credentials@v4
75+
with:
76+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
77+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
78+
aws-region: ${{ env.AWS_REGION }}
79+
80+
- name: Login to Amazon ECR
81+
id: login-ecr
82+
uses: aws-actions/amazon-ecr-login@v2
83+
84+
- name: Build, tag, and push image to Amazon ECR
85+
env:
86+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
87+
ECR_REPOSITORY: nodejs-backend-template
88+
IMAGE_TAG: ${{ github.sha }}
89+
run: |
90+
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
91+
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
92+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
93+
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
94+
95+
deploy:
96+
name: Deploy to AWS ECS
97+
runs-on: ubuntu-latest
98+
needs: build
99+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
100+
101+
steps:
102+
- name: Checkout code
103+
uses: actions/checkout@v4
104+
105+
- name: Configure AWS credentials
106+
uses: aws-actions/configure-aws-credentials@v4
107+
with:
108+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
109+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
110+
aws-region: ${{ env.AWS_REGION }}
111+
112+
- name: Deploy to Amazon ECS
113+
run: |
114+
aws ecs update-service \
115+
--cluster nodejs-backend-cluster \
116+
--service nodejs-backend-service \
117+
--force-new-deployment \
118+
--region ${{ env.AWS_REGION }}
119+
120+
- name: Wait for service to be stable
121+
run: |
122+
aws ecs wait services-stable \
123+
--cluster nodejs-backend-cluster \
124+
--services nodejs-backend-service \
125+
--region ${{ env.AWS_REGION }}

.gitignore

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Dependencies
2+
node_modules/
3+
package-lock.json
4+
yarn.lock
5+
6+
# Environment variables
7+
.env
8+
.env.local
9+
.env.*.local
10+
11+
# Logs
12+
logs/
13+
*.log
14+
npm-debug.log*
15+
yarn-debug.log*
16+
yarn-error.log*
17+
lerna-debug.log*
18+
.pnpm-debug.log*
19+
20+
# Runtime data
21+
pids
22+
*.pid
23+
*.seed
24+
*.pid.lock
25+
26+
# Coverage directory
27+
coverage/
28+
.nyc_output/
29+
*.lcov
30+
31+
# IDEs and editors
32+
.idea
33+
.vscode
34+
*.swp
35+
*.swo
36+
*~
37+
.DS_Store
38+
Thumbs.db
39+
40+
# Build outputs
41+
dist/
42+
build/
43+
tmp/
44+
out/
45+
46+
# Optional npm cache directory
47+
.npm
48+
49+
# Optional eslint cache
50+
.eslintcache
51+
52+
# Optional REPL history
53+
.node_repl_history
54+
55+
# Output of 'npm pack'
56+
*.tgz
57+
58+
# Uploads
59+
public/uploads/*
60+
!public/uploads/.gitkeep
61+
62+
# Docker
63+
.dockerignore
64+
65+
# Claude Code
66+
.claude/
67+
68+
# Misc
69+
.env.test
70+
.cache
71+
app.log*

.husky/commit-msg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
3+
4+
npx --no -- commitlint --edit ${1}

.husky/pre-commit

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
3+
4+
npm run lint
5+
npm run format

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
coverage
3+
dist
4+
build
5+
*.log
6+
.env*
7+
package-lock.json

.prettierrc.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "es5",
4+
"singleQuote": true,
5+
"printWidth": 120,
6+
"tabWidth": 2,
7+
"useTabs": false,
8+
"arrowParens": "always",
9+
"endOfLine": "lf"
10+
}

Dockerfile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Multi-stage build for production
2+
FROM node:18-alpine AS base
3+
4+
# Install dependencies only when needed
5+
FROM base AS deps
6+
WORKDIR /app
7+
8+
# Copy package files
9+
COPY package.json package-lock.json ./
10+
11+
# Install dependencies
12+
RUN npm ci --only=production && npm cache clean --force
13+
14+
# Development stage
15+
FROM base AS development
16+
WORKDIR /app
17+
18+
# Copy package files
19+
COPY package.json package-lock.json ./
20+
21+
# Install all dependencies (including dev dependencies)
22+
RUN npm ci
23+
24+
# Copy source code
25+
COPY . .
26+
27+
# Expose port
28+
EXPOSE 3000
29+
30+
# Start in development mode
31+
CMD ["npm", "run", "dev"]
32+
33+
# Production stage
34+
FROM base AS production
35+
WORKDIR /app
36+
37+
# Set NODE_ENV
38+
ENV NODE_ENV=production
39+
40+
# Copy dependencies from deps stage
41+
COPY --from=deps /app/node_modules ./node_modules
42+
43+
# Copy source code
44+
COPY . .
45+
46+
# Create non-root user
47+
RUN addgroup -g 1001 -S nodejs && \
48+
adduser -S nodejs -u 1001 && \
49+
chown -R nodejs:nodejs /app
50+
51+
# Switch to non-root user
52+
USER nodejs
53+
54+
# Expose port
55+
EXPOSE 3000
56+
57+
# Health check
58+
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
59+
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
60+
61+
# Start production server
62+
CMD ["node", "src/index.js"]

0 commit comments

Comments
 (0)