Skip to main content
The skeleton template includes a minimal demo application to demonstrate the infrastructure. This guide shows you how to replace it with your own application while preserving the production-ready infrastructure.

Understanding the Demo Application

The skeleton includes:
  • Backend (app/backend/): Minimal Express.js server with health check endpoints
  • Frontend (app/frontend/): React + Vite placeholder application
  • Database: PostgreSQL (local via Docker Compose, RDS in production)

Replacing the Backend

The backend is located in app/backend/ and uses Express.js by default.
1
Review the Existing Structure
2
The demo backend is minimal:
3
app/backend/
  src/
    app.js        # Express app configuration
    server.js     # Server entry point
  package.json    # Dependencies
  Dockerfile      # Container build configuration
4
Key file: app/backend/src/app.js:1
5
Add Your Application Code
6
Create your API routes in app/backend/src/routes/:
// app/backend/src/routes/users.js
const express = require('express');
const router = express.Router();

router.get('/users', async (req, res) => {
  // Your logic here
  res.json({ users: [] });
});

module.exports = router;
Import in app.js:
const usersRouter = require('./routes/users');
app.use('/api', usersRouter);
Add your services in app/backend/src/services/:
// app/backend/src/services/user.service.js
class UserService {
  async findAll() {
    // Your business logic
  }
}

module.exports = { UserService };
Update app/backend/package.json with your dependencies:
{
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "helmet": "^7.1.0",
    "pg": "^8.11.3",
    "your-other-dependencies": "^x.x.x"
  }
}
7
Preserve Required Health Check Endpoints
8
Critical: Kubernetes uses these endpoints to verify service health. Do not remove them.
9
You must keep these endpoints in app/backend/src/app.js:23:
10
  • GET /api/health - Basic health check
  • GET /api/health/database - Database connectivity check
  • GET /api/health/cloud - Cloud provider credentials check
  • 11
    // Required for Kubernetes liveness probe
    app.get('/api/health', (req, res) => {
      res.json({
        status: 'healthy',
        timestamp: new Date().toISOString(),
        provider: process.env.CLOUD_PROVIDER,
        uptime: process.uptime(),
      });
    });
    
    // Required for Kubernetes readiness probe
    app.get('/api/health/database', async (req, res) => {
      // Implement actual database check
      const db = require('./services/factory').getDatabaseService();
      const result = await db.ping();
      res.json(result);
    });
    
    // Cloud provider health check
    app.get('/api/health/cloud', (req, res) => {
      res.json({
        status: 'healthy',
        provider: process.env.CLOUD_PROVIDER,
        region: process.env.AWS_REGION || process.env.OCI_REGION || 'not-set',
      });
    });
    
    12
    Update the Dockerfile (if needed)
    13
    If you’re not using Node.js, replace app/backend/Dockerfile with your framework’s build process:
    14
    Node.js (default)
    FROM node:18-alpine
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --only=production
    COPY . .
    EXPOSE 3000
    CMD ["node", "src/server.js"]
    
    Python (Flask/FastAPI)
    FROM python:3.11-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    COPY . .
    EXPOSE 3000
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"]
    
    Go
    FROM golang:1.21-alpine AS builder
    WORKDIR /app
    COPY go.* ./
    RUN go mod download
    COPY . .
    RUN go build -o server .
    
    FROM alpine:latest
    WORKDIR /app
    COPY --from=builder /app/server .
    EXPOSE 3000
    CMD ["./server"]
    

    Replacing the Frontend

    The frontend is located in app/frontend/ and uses React + Vite by default.
    1
    Review the Existing Structure
    2
    app/frontend/
      src/
        App.jsx       # Main component (placeholder)
        main.jsx      # Entry point
      package.json    # Dependencies
      Dockerfile      # Nginx-based container
    
    3
    Key file: app/frontend/src/App.jsx:1
    4
    Replace with Your Frontend
    5
    React/Vite (existing)
    Copy your React application code to app/frontend/src/:
    # Remove demo app
    rm app/frontend/src/App.jsx
    
    # Copy your source files
    cp -r your-app/src/* app/frontend/src/
    
    # Update dependencies
    cp your-app/package.json app/frontend/package.json
    
    Vue.js
    Replace the build configuration in app/frontend/package.json:
    {
      "scripts": {
        "dev": "vite",
        "build": "vite build",
        "preview": "vite preview"
      },
      "dependencies": {
        "vue": "^3.3.4"
      },
      "devDependencies": {
        "@vitejs/plugin-vue": "^4.4.0",
        "vite": "^5.1.4"
      }
    }
    
    Create vite.config.js:
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    
    export default defineConfig({
      plugins: [vue()],
    })
    
    Angular
    Update app/frontend/package.json:
    {
      "scripts": {
        "build": "ng build --configuration production",
        "dev": "ng serve"
      },
      "dependencies": {
        "@angular/core": "^17.0.0"
      }
    }
    
    Update app/frontend/Dockerfile:
    FROM node:18-alpine AS build
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    FROM nginx:alpine
    COPY --from=build /app/dist/your-app-name /usr/share/nginx/html
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    
    Next.js
    Update app/frontend/package.json:
    {
      "scripts": {
        "build": "next build",
        "start": "next start",
        "dev": "next dev"
      },
      "dependencies": {
        "next": "^14.0.0",
        "react": "^18.2.0",
        "react-dom": "^18.2.0"
      }
    }
    
    Update app/frontend/Dockerfile:
    FROM node:18-alpine
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    EXPOSE 3000
    CMD ["npm", "start"]
    
    6
    Update the Dockerfile
    7
    The default Dockerfile uses a multi-stage build with Nginx:
    8
    # Build stage
    FROM node:18-alpine AS build
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
    # Production stage
    FROM nginx:alpine
    COPY --from=build /app/dist /usr/share/nginx/html
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    
    9
    Adjust the COPY --from=build path based on your framework’s output directory:
    10
  • Vite: /app/dist
  • Create React App: /app/build
  • Angular: /app/dist/your-app-name
  • Vue CLI: /app/dist
  • Testing Your Changes Locally

    After customizing the application, test locally with Docker Compose:
    # Rebuild containers
    docker-compose build
    
    # Start services
    docker-compose up -d
    
    # Check logs
    docker-compose logs -f backend
    docker-compose logs -f frontend
    
    # Test health checks
    curl http://localhost:3000/api/health
    curl http://localhost:3000/api/health/database
    curl http://localhost:3000/api/health/cloud
    
    # Access frontend
    open http://localhost:80
    

    Updating Kubernetes Manifests

    After replacing the demo app, update the Kubernetes deployment manifests:
    1
    Update Image References
    2
    Search for REEMPLAZAR comments in kubernetes/ manifests and update:
    3
    # kubernetes/backend/deployment.yaml
    spec:
      template:
        spec:
          containers:
          - name: backend
            image: your-registry/backend:v1.0  # REEMPLAZAR: your image
    
    4
    Update Resource Limits
    5
    Adjust resource requests/limits based on your application’s needs:
    6
    resources:
      requests:
        memory: "256Mi"  # Adjust based on your app
        cpu: "250m"
      limits:
        memory: "512Mi"
        cpu: "500m"
    
    7
    Update Environment Variables
    8
    Add any additional environment variables your app needs:
    9
    env:
    - name: CLOUD_PROVIDER
      valueFrom:
        configMapKeyRef:
          name: govtech-config
          key: cloud-provider
    - name: YOUR_CUSTOM_VAR
      value: "your-value"
    

    Next Steps

    Build docs developers (and LLMs) love