How melvinthomas-dev/portfolio_website works
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: api.js API client · App.jsx App shell · Program.cs API composition root · ContactController.cs Contact controller
Components 20
Static frontend
GitHub Pages React artifact.
- Vite entry
frontend/src/main.jsx - App shell · Composes public portfolio and private admin area.
frontend/src/App.jsx - Portfolio pages
frontend/src/components/PortfolioPage.jsx - Resume content
frontend/src/data/resumeContent.js - Contact form
frontend/src/components/Contact.jsx - Visit tracking · Uses local session UUID and device metadata.
frontend/src/hooks/useAnalytics.js - API client · Uses build-time VITE_API_BASE_URL.
frontend/src/services/api.js - Admin login and dashboard · Route guard stores JWT and calls protected dashboard APIs.
frontend/src/admin/Login.jsx - Frontend deployment
.github/workflows/deploy-frontend.yml
ASP.NET Core API
Independently hosted stateful backend.
- API composition root · Configures CORS, JWT, DI, controllers, health, and database.
backend/Program.cs - Contact controller
backend/Controllers/ContactController.cs - Analytics controller · Accepts visits and serves protected dashboard aggregates.
backend/Controllers/AnalyticsController.cs - Auth controller
backend/Controllers/AuthController.cs - Auth service · Validates admin credentials and issues JWTs.
backend/Services/AuthService.cs - Analytics enrichment · Parses device and traffic source and resolves geolocation.
backend/Services/GeoLocationService.cs - Email service
backend/Services/EmailService.cs - Portfolio database · SQLite in development; PostgreSQL in production.
backend/Data/PortfolioDbContext.cs - API deployment · Render or Azure deployment.
render.yaml
External services
- SendGrid
- IP geolocation APIs · ipinfo.io or ip-api.
Connections 24
- 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