# melvinthomas-dev/portfolio_website architecture

> Architecture diagram of the GitHub repository melvinthomas-dev/portfolio_website, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/melvinthomas-dev/portfolio_website
- Repository: https://github.com/melvinthomas-dev/portfolio_website

## Overview

#### Purpose and deployment shape
A recruiter-facing portfolio combines a static React public site with a stateful ASP.NET Core API. The frontend is built for GitHub Pages; the API is independently hosted on Render or Azure and owns contact delivery, analytics, and protected administration. Deployment definitions are in `.github/workflows/deploy-frontend.yml`, `render.yaml`, and `backend/Dockerfile`.

#### Frontend application shell
Vite boots the React app from `frontend/src/main.jsx`; `frontend/src/App.jsx` composes the public portfolio and the `/admin` area. Public page content is primarily data-driven from `frontend/src/data/resumeContent.js`, rendered by portfolio components such as `frontend/src/components/PortfolioPage.jsx` and `frontend/src/components/Contact.jsx`. The build-time API origin is supplied through `VITE_API_BASE_URL`.

#### Public engagement flows
The contact component submits form data through the API client in `frontend/src/services/api.js` to the backend contact endpoint. On page load/route changes, `frontend/src/hooks/useAnalytics.js` sends anonymous visit events; `frontend/src/utils/visitor.js` persists the local session UUID and `frontend/src/hooks/useDeviceInfo.js` provides client/device metadata. This keeps the GitHub Pages frontend stateless while the API enriches and records events.

#### API host and request boundary
`backend/Program.cs` is the composition root: it configures database selection, authentication/JWT, CORS, dependency injection, controllers, and `/health`. HTTP boundaries are controller-based: `backend/Controllers/ContactController.cs`, `backend/Controllers/AnalyticsController.cs`, and `backend/Controllers/AuthController.cs`. DTOs in `backend/DTOs/ApiDtos.cs` separate external request/response contracts from persistence entities.

#### Contact and analytics processing
Contact submissions enter `ContactController`, are validated/persisted, enriched with source context, and trigger email delivery through `backend/Services/EmailService.cs` (SendGrid). Analytics visits enter `AnalyticsController`, then use `backend/Services/DeviceParser.cs`, `backend/Services/GeoLocationService.cs`, and `backend/Services/TrafficSourceParser.cs` to classify client, location, and acquisition source before storage. Geo lookup reaches ipinfo.io or ip-api; email reaches SendGrid.

#### Persistence and identity
Entity Framework persistence is centralized in `backend/Data/PortfolioDbContext.cs`, with `backend/Models/ContactSubmission.cs` and `backend/Models/PageVisit.cs` representing operational records. Development uses SQLite; production is intended for PostgreSQL through `DATABASE_URL`. Admin credentials and JWT issuance are handled by `backend/Services/AuthService.cs` and `backend/Models/AdminUser.cs`; secrets and credentials remain environment-configured.

#### Private admin path
`frontend/src/admin/Login.jsx` posts credentials to `/api/auth/login`, stores/uses the returned JWT, and `frontend/src/admin/AdminRoute.jsx` gates dashboard access. `frontend/src/admin/Dashboard.jsx` calls the Bearer-protected analytics dashboard endpoint, which aggregates visits and contact submissions in `backend/Controllers/AnalyticsController.cs`. The admin UI is intentionally unlinked from public navigation but is deployed in the same static frontend artifact.

Main entry points: [`frontend/src/services/api.js`](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/services/api.js) (API client), [`frontend/src/App.jsx`](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/App.jsx) (App shell), [`backend/Program.cs`](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Program.cs) (API composition root), [`backend/Controllers/ContactController.cs`](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/ContactController.cs) (Contact controller)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Static frontend"]
  node_vite["Vite entry<br/>React bootstrap<br/>[main.jsx]"]
  node_app["App shell<br/>React routes<br/>[App.jsx]"]
  node_portfolio["Portfolio pages<br/>public UI<br/>[PortfolioPage.jsx]"]
  node_content["Resume content<br/>content data<br/>[resumeContent.js]"]
  node_contact_ui["Contact form<br/>public UI<br/>[Contact.jsx]"]
  node_analytics_client["Visit tracking<br/>client analytics<br/>[useAnalytics.js]"]
  node_api_client["API client<br/>HTTP client<br/>[api.js]"]
  node_admin_ui["Admin login and dashboard<br/>private UI<br/>[Login.jsx]"]
  node_frontend_deploy["Frontend deployment<br/>GitHub Pages workflow"]
end

subgraph group_api["ASP.NET Core API"]
  node_program["API composition root<br/>ASP.NET Core host<br/>[Program.cs]"]
  node_contact_api["Contact controller<br/>HTTP controller"]
  node_analytics_api["Analytics controller<br/>HTTP controller"]
  node_auth_api["Auth controller<br/>HTTP controller<br/>[AuthController.cs]"]
  node_auth_service["Auth service<br/>identity service<br/>[AuthService.cs]"]
  node_enrichment["Analytics enrichment<br/>processing services"]
  node_email["Email service<br/>delivery service<br/>[EmailService.cs]"]
  node_db[("Portfolio database<br/>EF Core persistence")]
  node_api_deploy["API deployment<br/>container hosting<br/>[render.yaml]"]
end

subgraph group_external["External services"]
  node_sendgrid{{"SendGrid<br/>email provider"}}
  node_geo{{"IP geolocation APIs<br/>location provider"}}
end

node_vite -->|"boots"| node_app
node_app -->|"renders"| node_portfolio
node_portfolio -->|"reads"| node_content
node_app -->|"includes"| node_contact_ui
node_contact_ui -->|"submits through"| node_api_client
node_app -->|"tracks load/routes"| node_analytics_client
node_analytics_client -->|"sends visits"| node_api_client
node_app -->|"/admin"| node_admin_ui
node_admin_ui -->|"login and Bearer calls"| node_api_client
node_api_client -->|"contact endpoint"| node_contact_api
node_api_client -->|"visits and dashboard"| node_analytics_api
node_api_client -->|"login"| node_auth_api
node_program -->|"hosts"| node_contact_api
node_program -->|"hosts"| node_analytics_api
node_program -->|"hosts"| node_auth_api
node_contact_api -->|"persists submissions"| node_db
node_contact_api -->|"triggers delivery"| node_email
node_analytics_api -->|"classifies visits"| node_enrichment
node_analytics_api -->|"stores and aggregates"| node_db
node_auth_api -->|"authenticates"| node_auth_service
node_enrichment -->|"looks up IP"| node_geo
node_email -->|"delivers via"| node_sendgrid
node_frontend_deploy -->|"builds and publishes"| node_vite
node_api_deploy -->|"deploys"| node_program

click node_vite "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/main.jsx"
click node_app "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/App.jsx"
click node_portfolio "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/components/PortfolioPage.jsx"
click node_content "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/data/resumeContent.js"
click node_contact_ui "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/components/Contact.jsx"
click node_analytics_client "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/hooks/useAnalytics.js"
click node_api_client "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/services/api.js"
click node_admin_ui "https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/admin/Login.jsx"
click node_program "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Program.cs"
click node_contact_api "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/ContactController.cs"
click node_analytics_api "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/AnalyticsController.cs"
click node_auth_api "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/AuthController.cs"
click node_auth_service "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/AuthService.cs"
click node_enrichment "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/GeoLocationService.cs"
click node_email "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/EmailService.cs"
click node_db "https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Data/PortfolioDbContext.cs"
click node_frontend_deploy "https://github.com/melvinthomas-dev/portfolio_website/blob/main/.github/workflows/deploy-frontend.yml"
click node_api_deploy "https://github.com/melvinthomas-dev/portfolio_website/blob/main/render.yaml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_vite,node_app,node_portfolio,node_content,node_contact_ui,node_analytics_client,node_api_client,node_admin_ui,node_frontend_deploy toneBlue
class node_program,node_contact_api,node_analytics_api,node_auth_api,node_auth_service,node_enrichment,node_email,node_db,node_api_deploy toneAmber
class node_sendgrid,node_geo toneMint
```

## Components

### Static frontend

GitHub Pages React artifact.

- [Vite entry](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/main.jsx): React bootstrap · `frontend/src/main.jsx`
- [App shell](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/App.jsx): React routes · Composes public portfolio and private admin area. · `frontend/src/App.jsx`
- [Portfolio pages](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/components/PortfolioPage.jsx): public UI · `frontend/src/components/PortfolioPage.jsx`
- [Resume content](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/data/resumeContent.js): content data · `frontend/src/data/resumeContent.js`
- [Contact form](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/components/Contact.jsx): public UI · `frontend/src/components/Contact.jsx`
- [Visit tracking](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/hooks/useAnalytics.js): client analytics · Uses local session UUID and device metadata. · `frontend/src/hooks/useAnalytics.js`
- [API client](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/services/api.js): HTTP client · Uses build-time VITE_API_BASE_URL. · `frontend/src/services/api.js`
- [Admin login and dashboard](https://github.com/melvinthomas-dev/portfolio_website/blob/main/frontend/src/admin/Login.jsx): private UI · Route guard stores JWT and calls protected dashboard APIs. · `frontend/src/admin/Login.jsx`
- [Frontend deployment](https://github.com/melvinthomas-dev/portfolio_website/blob/main/.github/workflows/deploy-frontend.yml): GitHub Pages workflow · `.github/workflows/deploy-frontend.yml`

### ASP.NET Core API

Independently hosted stateful backend.

- [API composition root](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Program.cs): ASP.NET Core host · Configures CORS, JWT, DI, controllers, health, and database. · `backend/Program.cs`
- [Contact controller](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/ContactController.cs): HTTP controller · `backend/Controllers/ContactController.cs`
- [Analytics controller](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/AnalyticsController.cs): HTTP controller · Accepts visits and serves protected dashboard aggregates. · `backend/Controllers/AnalyticsController.cs`
- [Auth controller](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Controllers/AuthController.cs): HTTP controller · `backend/Controllers/AuthController.cs`
- [Auth service](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/AuthService.cs): identity service · Validates admin credentials and issues JWTs. · `backend/Services/AuthService.cs`
- [Analytics enrichment](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/GeoLocationService.cs): processing services · Parses device and traffic source and resolves geolocation. · `backend/Services/GeoLocationService.cs`
- [Email service](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Services/EmailService.cs): delivery service · `backend/Services/EmailService.cs`
- [Portfolio database](https://github.com/melvinthomas-dev/portfolio_website/blob/main/backend/Data/PortfolioDbContext.cs): EF Core persistence · SQLite in development; PostgreSQL in production. · `backend/Data/PortfolioDbContext.cs`
- [API deployment](https://github.com/melvinthomas-dev/portfolio_website/blob/main/render.yaml): container hosting · Render or Azure deployment. · `render.yaml`

### External services

- **SendGrid**: email provider
- **IP geolocation APIs**: location provider · ipinfo.io or ip-api.

## Connections

- Vite entry → App shell: boots
- App shell → Portfolio pages: renders
- Portfolio pages → Resume content: reads
- App shell → Contact form: includes
- Contact form → API client: submits through
- App shell → Visit tracking: tracks load/routes
- Visit tracking → API client: sends visits
- App shell → Admin login and dashboard: /admin
- Admin login and dashboard → API client: login and Bearer calls
- API client → Contact controller: contact endpoint
- API client → Analytics controller: visits and dashboard
- API client → Auth controller: login
- API composition root → Contact controller: hosts
- API composition root → Analytics controller: hosts
- API composition root → Auth controller: hosts
- Contact controller → Portfolio database: persists submissions
- Contact controller → Email service: triggers delivery
- Analytics controller → Analytics enrichment: classifies visits
- Analytics controller → Portfolio database: stores and aggregates
- Auth controller → Auth service: authenticates
- Analytics enrichment → IP geolocation APIs: looks up IP
- Email service → SendGrid: delivers via
- Frontend deployment → Vite entry: builds and publishes
- API deployment → API composition root: deploys
