Skip to content

Commit cfd935d

Browse files
committed
feat: Add architecture diagram and quick access links in README.md
1 parent 7784af8 commit cfd935d

2 files changed

Lines changed: 173 additions & 0 deletions

File tree

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,18 @@ Rate limiting - DDoS protection
242242

243243
### **High-Level Architecture**
244244

245+
<div align="center">
246+
247+
[![View in Mermaid Live](https://img.shields.io/badge/📊_Open_Interactive_Viewer-Mermaid_Live-FF3670?style=for-the-badge&logo=mermaid)](https://mermaid.live/)
248+
[![Copy Diagram Code](https://img.shields.io/badge/📋_Copy_Code-Raw_File-2ea44f?style=for-the-badge)](https://raw.githubusercontent.com/NevilPatel01/CityPulse/main/architecture-diagram.mmd)
249+
250+
**Quick Access:** [📄 View Diagram Source](architecture-diagram.mmd) | **One-Click Copy:** Click "Copy Diagram Code" → Click "Select All" + Copy → Paste in Mermaid Live
251+
252+
</div>
253+
254+
<details>
255+
<summary><b>🔍 Click to expand/collapse architecture diagram</b></summary>
256+
245257
```mermaid
246258
flowchart TB
247259
%% ============================================
@@ -404,6 +416,8 @@ flowchart TB
404416
style HC fill:#fecaca,stroke:#b91c1c,stroke-width:2px
405417
```
406418

419+
</details>
420+
407421
**Architecture Highlights:**
408422

409423
🌐 **Request Flow**:

architecture-diagram.mmd

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
flowchart TB
2+
%% ============================================
3+
%% Internet & Client Layer
4+
%% ============================================
5+
CLIENT["🌐 Client Browser"]
6+
DOMAIN["🔗 city-pulse.app<br/>SSL/TLS (Let's Encrypt)"]
7+
8+
%% ============================================
9+
%% CI/CD Pipeline (GitHub Actions)
10+
%% ============================================
11+
subgraph CICD["⚡ GitHub Actions CI/CD Pipeline"]
12+
direction TB
13+
14+
TRIGGER["🔔 Triggers<br/>• Push: main, production<br/>• PR: main"]
15+
16+
subgraph JOB1["🧪 Job 1: Test & Quality"]
17+
direction LR
18+
T1["📦 Checkout<br/>actions/checkout@v4"]
19+
T2["🔧 Setup Node 20<br/>pnpm 10.10.0"]
20+
T3["📥 Install deps<br/>pnpm install"]
21+
T4["🔍 Lint<br/>ESLint + Prettier"]
22+
T5["🏗️ Build<br/>TypeScript + Vite"]
23+
end
24+
25+
subgraph JOB2["🐳 Job 2: Build Images"]
26+
direction LR
27+
B1["🔡 Prepare names<br/>REPO_LOWER"]
28+
B2["🏗️ Docker Buildx<br/>linux/amd64"]
29+
B3["🔐 Login GHCR<br/>ghcr.io"]
30+
B4["📦 Build Backend<br/>backend/Dockerfile.prod"]
31+
B5["📦 Build Frontend<br/>frontend/Dockerfile.prod"]
32+
B6["⬆️ Push to GHCR<br/>ghcr.io/citypulse-backend:v1.2.3<br/>ghcr.io/citypulse-frontend:v1.2.3"]
33+
end
34+
35+
subgraph JOB3["🚀 Job 3: Deploy"]
36+
direction LR
37+
D1["📁 Create package<br/>.env.prod + docker-compose.prod.yml"]
38+
D2["📦 Tar archive<br/>deploy-v1.2.3.tar.gz"]
39+
D3["📤 SCP Upload<br/>→ /opt/citypulse"]
40+
D4["🔐 SSH Deploy<br/>root@[Production Droplet]"]
41+
D5["🐳 Docker compose up<br/>--env-file .env.prod"]
42+
D6["✅ Health check<br/>timeout 300s"]
43+
end
44+
45+
JOB4["📢 Job 4: Notify<br/>✅ city-pulse.app/health"]
46+
47+
TRIGGER --> T1
48+
T1 --> T2 --> T3 --> T4 --> T5
49+
T5 -.-> B1
50+
B1 --> B2 --> B3 --> B4 --> B5 --> B6
51+
B6 -.-> D1
52+
D1 --> D2 --> D3 --> D4 --> D5 --> D6
53+
D6 -.-> JOB4
54+
end
55+
56+
%% ============================================
57+
%% DigitalOcean Droplet Infrastructure
58+
%% ============================================
59+
subgraph DROPLET["🟦 DigitalOcean Droplet<br/>Production Server • /opt/citypulse"]
60+
direction TB
61+
62+
subgraph NGINX_LAYER["🔀 Nginx Reverse Proxy"]
63+
NGINX["citypulse-nginx-prod<br/>nginx:1.25-alpine<br/>Ports: 80, 443<br/>nginx-domain.conf<br/>Rate Limit: 10r/s"]
64+
end
65+
66+
subgraph DOCKER_NET["🔗 Docker Network: citypulse-network"]
67+
direction TB
68+
69+
subgraph APP_SERVICES["🎯 Application Services"]
70+
direction LR
71+
72+
BACKEND["🔧 citypulse-backend-prod<br/>ghcr.io/citypulse-backend:v1.2.3<br/>Port: 5000<br/>JWT + WebSocket<br/>Health: /health"]
73+
74+
FRONTEND["⚛️ citypulse-frontend-prod<br/>ghcr.io/citypulse-frontend:v1.2.3<br/>Port: 3001→80<br/>Vite + Tailwind<br/>Health: localhost:80"]
75+
end
76+
77+
POSTGRES["🗄️ citypulse-postgres-prod<br/>postgres:15-alpine<br/>Port: 5432<br/>21+ Tables<br/>Health: pg_isready"]
78+
end
79+
80+
subgraph VOLUMES["💾 Persistent Volumes"]
81+
VOL1["postgres_data"]
82+
VOL2["uploads_data"]
83+
VOL3["letsencrypt"]
84+
end
85+
86+
NGINX --> BACKEND
87+
NGINX --> FRONTEND
88+
BACKEND <--> POSTGRES
89+
FRONTEND -.depends.-> BACKEND
90+
POSTGRES -.mount.-> VOL1
91+
BACKEND -.mount.-> VOL2
92+
NGINX -.mount.-> VOL3
93+
end
94+
95+
%% ============================================
96+
%% External Services
97+
%% ============================================
98+
subgraph EXTERNAL["🌍 External Services"]
99+
direction TB
100+
GOOGLE["🔐 Google OAuth"]
101+
EMAIL["📧 SendGrid API"]
102+
GHCR["📦 GitHub Container Registry<br/>ghcr.io/citypulse-*"]
103+
end
104+
105+
%% ============================================
106+
%% Main Flow Connections
107+
%% ============================================
108+
CLIENT -->|HTTPS| DOMAIN
109+
DOMAIN -->|443| NGINX
110+
BACKEND -->|OAuth| GOOGLE
111+
BACKEND -->|Emails| EMAIL
112+
113+
D4 -.SSH.-> DROPLET
114+
GHCR -.docker-pull.-> DOCKER_NET
115+
JOB2 -.images.-> GHCR
116+
117+
%% ============================================
118+
%% Environment & Health
119+
%% ============================================
120+
ENVVARS["⚙️ .env.prod<br/>JWT_SECRET • POSTGRES_*<br/>GOOGLE_* • EMAIL_*"]
121+
HC["❤️ Health Dashboard<br/>pg_isready • /health<br/>wget localhost • nginx"]
122+
123+
ENVVARS -.inject.-> BACKEND
124+
ENVVARS -.inject.-> FRONTEND
125+
ENVVARS -.inject.-> POSTGRES
126+
HC -.monitor.-> POSTGRES
127+
HC -.monitor.-> BACKEND
128+
HC -.monitor.-> FRONTEND
129+
HC -.monitor.-> NGINX
130+
131+
%% ============================================
132+
%% Production-Grade Color Scheme (High Contrast)
133+
%% ============================================
134+
style CLIENT fill:#dbeafe,stroke:#1e40af,stroke-width:3px
135+
style DOMAIN fill:#fef3c7,stroke:#b45309,stroke-width:3px
136+
style CICD fill:#f8fafc,stroke:#1e293b,stroke-width:3px
137+
style DROPLET fill:#fefce8,stroke:#a16207,stroke-width:4px
138+
style NGINX_LAYER fill:#dcfce7,stroke:#166534,stroke-width:2px
139+
style DOCKER_NET fill:#eff6ff,stroke:#1d4ed8,stroke-width:2px
140+
style APP_SERVICES fill:#fef3c7,stroke:#b45309,stroke-width:2px
141+
style VOLUMES fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
142+
style EXTERNAL fill:#fecaca,stroke:#b91c1c,stroke-width:2px
143+
144+
style NGINX fill:#10b981,stroke:#047857,stroke-width:3px,color:#000
145+
style BACKEND fill:#f97316,stroke:#c2410c,stroke-width:3px,color:#fff
146+
style FRONTEND fill:#3b82f6,stroke:#1d4ed8,stroke-width:3px,color:#fff
147+
style POSTGRES fill:#8b5cf6,stroke:#6d28d9,stroke-width:3px,color:#fff
148+
149+
style GOOGLE fill:#ef4444,stroke:#dc2626,stroke-width:2px,color:#fff
150+
style EMAIL fill:#10b981,stroke:#047857,stroke-width:2px,color:#fff
151+
style GHCR fill:#1f2937,stroke:#111827,stroke-width:2px,color:#fff
152+
153+
style JOB1 fill:#dcfce7,stroke:#166534,stroke-width:2px
154+
style JOB2 fill:#eff6ff,stroke:#1d4ed8,stroke-width:2px
155+
style JOB3 fill:#fef3c7,stroke:#b45309,stroke-width:2px
156+
style JOB4 fill:#10b981,stroke:#047857,stroke-width:2px,color:#fff
157+
158+
style ENVVARS fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
159+
style HC fill:#fecaca,stroke:#b91c1c,stroke-width:2px

0 commit comments

Comments
 (0)