An assignment for a full stack microservice based project
Backend: Node.js, TypeScript, Express, Prisma, SQLite, Jest
Frontend: React, TypeScript, Vite, Tailwind CSS, shadcn/ui, Axios
DevOps: Docker, Kubernetes, AWS EC2
https://www.loom.com/share/35ad0a93d92b43cb89907f8afe19acd2
- Credential issuance success
- Duplicate credentials
- Credential verification success
kubectl get pods
Hosting
React Frontend (Vite + TypeScript)
↓ ↓
Issuance Service Verification Service
(Express + Prisma) (Express + Prisma)
↓ ↓
SQLite Database SQLite Database
Two independent microservices running in separate Kubernetes pods, each with its own database. Frontend communicates with both services via REST APIs.
zupple/
├── client/ # React frontend (Vite + TypeScript + Tailwind)
├── services/
│ ├── issuance/ # Credential issuance microservice
│ │ ├── src/
│ │ │ ├── api/issue/ # Controllers, services, routes
│ │ │ ├── config/ # Config & database setup
│ │ │ └── tests/ # Jest unit tests
│ │ ├── prisma/ # Database schema & migrations
│ │ └── Dockerfile
│ └── verification/ # Credential verification microservice
│ ├── src/
│ │ ├── api/verify/ # Controllers, services, routes
│ │ ├── config/ # Config & database setup
│ │ └── tests/ # Jest unit tests
│ ├── prisma/ # Database schema & migrations
│ └── Dockerfile
└── k8s/ # Kubernetes deployment manifests
- Lightweight, zero-config, perfect for free-tier deployment
- Prisma provides type-safe queries and automatic migrations
- Each service has its own database
- Credentials are SHA-256 hashed before storage
- Hash uniqueness constraint prevents duplicate issuance
- Enables fast duplicate detection without comparing full JSON
- Worker ID injected via Kubernetes (
metadata.name) - Each pod automatically gets unique identifier
- Stored with credentials for traceability
- Each microservice is independently deployable and scalable
- Separate databases ensure no shared state
- RESTful APIs for communication (Webhook)
# Issuance Service
cd services/issuance
npm install
npx prisma generate
npm run dev # Runs on port 3000
# Verification Service
cd services/verification
npm install
npx prisma generate
npm run dev # Runs on port 3001
# Frontend
cd client
npm install
npm run dev # Runs on port 5173# Build images
docker build -t <username>/issuance-service:1.0 services/issuance
docker build -t <username>/verification-service:1.0 services/verification
# Push to registry
docker push <username>/issuance-service:1.0
docker push <username>/verification-service:1.0# Deploy services
kubectl apply -f k8s/issuance-deployment.yaml
kubectl apply -f k8s/issuance-service.yaml
kubectl apply -f k8s/verification-deployment.yaml
kubectl apply -f k8s/verification-service.yaml
# Check status
kubectl get pods
kubectl get services- AI Generated Unit Tests
# Issuance service tests
cd services/issuance
npm test
# Verification service tests
cd services/verification
npm test- SQLite is sufficient - Production would use PostgreSQL for better concurrency
- No authentication - Production would implement JWT based auth
- Flexible credential schema - Any valid JSON accepted as credential
- CORS enabled for all origins - Production would whitelist specific domains
- No data expiration - Credentials stored indefinitely
- Hash-based duplicate detection - Same JSON content = duplicate credential
- Services scale independently - Each maintains its own database