# rsayyed591/photopia architecture

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

- Interactive diagram: https://gitdiagram.com/rsayyed591/photopia
- Repository: https://github.com/rsayyed591/photopia

## Overview

1. **Overall shape**
   - Photopia is a two-tier full-stack app: a **React/Vite frontend** and a **Node/Express backend** backed by **MySQL**.
   - The main runtime boundary is the browser talking to the backend API over HTTP, with the backend owning authentication, file metadata, and database access.

2. **Frontend subsystem**
   - `user-frontend/` is a client-side React app built with **Vite**, styled with **Tailwind CSS**, and making API calls through a shared utility in `src/utils/api.js`.
   - The app is organized into page-level screens (`Home`, `Login`, `Register`) and reusable UI components (`Navbar`, `Footer`, `AuthForm`, `FileUpload`).

3. **Frontend data flow**
   - User interactions begin in the page components, which delegate login/registration form handling to `AuthForm` and photo upload actions to `FileUpload`.
   - The frontend reads the backend base URL from `VITE_API_URL`, so the API target is environment-driven rather than hardcoded.
   - After authentication, the client likely stores or forwards a JWT for subsequent protected requests.

4. **Backend API layer**
   - `user-backend/` is an **Express** application with `index.js` acting as the entry point and route modules under `routes/`.
   - The API surface is split by concern: `login.js`, `register.js`, `User.js`, and `fileRoutes.js`, which makes auth and file handling distinct subsystems.

5. **Authentication and authorization boundary**
   - JWT-based protection is implemented through `routes/jwtMiddleware.js`, which sits between the public API and protected endpoints.
   - Public auth endpoints handle account creation and sign-in, while protected endpoints cover file upload, file listing, and password change.
   - This means the backend is the security boundary; the frontend is only a token consumer.

6. **User/account subsystem**
   - `models/User.js` represents the user data model, and the README’s schema shows a `users` table with `username`, `email`, `password`, and timestamps.
   - The `change-password` endpoint in the README suggests account lifecycle logic beyond simple registration/login.

7. **File upload subsystem**
   - `controllers/fileController.js` centralizes the upload logic, while `routes/fileRoutes.js` exposes the upload and file retrieval endpoints.
   - The database schema includes a `user_files` table with `user_id` and `file_path`, so the backend persists **file metadata** and ownership in MySQL.
   - The repo does not show a separate object-storage service, so the key persisted artifact is the file path/record rather than a cloud storage integration.

8. **Database and persistence**
   - `config/db.js` encapsulates the MySQL connection setup used by the backend.
   - `database_setup.sql` is the authoritative schema bootstrap: it creates the `users` and `user_files` tables and enforces referential integrity with `ON DELETE CASCADE`.
   - That cascade means deleting a user also removes their file records, which is an important architecture detail for data lifecycle.

9. **Request path through the system**
   - A typical flow is: browser submits credentials or file data → React calls the API via Axios → Express route validates the request → JWT middleware checks authorization for protected routes → controller/model logic reads or writes MySQL.
   - For uploads, the backend likely associates the uploaded file with the authenticated user and stores the resulting path in `user_files`.

10. **Deployment and environment boundaries**
   - The frontend is configured for deployment on **Vercel** (`vercel.json`) and is currently the hosted part of the system.
   - The backend is intended for local or separately hosted execution on port 5000, with environment variables for DB credentials and JWT secret.
   - Because frontend and backend are separately deployed/configured, the architecture is split across two independently runnable services.

11. **What to show in an architecture diagram**
   - Draw three main boxes: **Browser/React UI**, **Express API**, and **MySQL database**.
   - Inside the backend, separate **Auth routes**, **File routes/controller**, **JWT middleware**, and **DB config/model**.
   - Show the frontend using a single API utility layer to reach multiple endpoints, and show protected routes passing through JWT middleware before database access.

12. **Notable constraints**
   - The app’s functionality is centered on authentication and photo metadata management rather than a broad media platform.
   - The repository is structured like a classic REST API + SPA setup, with clear separation between presentation, authorization, and persistence.

Main entry points: [`user-frontend/src/App.jsx`](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/App.jsx) (App shell), [`user-backend/index.js`](https://github.com/rsayyed591/photopia/blob/main/user-backend/index.js) (Express app), [`user-backend/models/User.js`](https://github.com/rsayyed591/photopia/blob/main/user-backend/models/User.js) (User model), [`user-backend/config/db.js`](https://github.com/rsayyed591/photopia/blob/main/user-backend/config/db.js) (DB config)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend"]
  node_browser(("Browser UI<br/>runtime<br/>[main.jsx]"))
  node_app["App shell<br/>spa shell<br/>[App.jsx]"]
  node_home["Home<br/>page<br/>[Home.jsx]"]
  node_login["Login<br/>page<br/>[Login.jsx]"]
  node_register["Register<br/>page<br/>[Register.jsx]"]
  node_authform["Auth form<br/>[AuthForm.jsx]"]
  node_uploadui["Upload UI<br/>[FileUpload.jsx]"]
  node_apiutil["API client<br/>[api.js]"]
  node_navbar["Navbar<br/>[Navbar.jsx]"]
  node_footer["Footer<br/>[Footer.jsx]"]
end

subgraph group_backend["Backend"]
  node_server(("Express app<br/>runtime<br/>[index.js]"))
  node_loginrt["Login route<br/>[login.js]"]
  node_registerrt["Register route<br/>[register.js]"]
  node_userrt["User route<br/>[User.js]"]
  node_filert["File routes<br/>[fileRoutes.js]"]
  node_jwt{{"JWT guard<br/>middleware<br/>[jwtMiddleware.js]"}}
  node_filectl["File controller<br/>[fileController.js]"]
  node_usermodel["User model<br/>[User.js]"]
  node_dbconfig["DB config<br/>[db.js]"]
end

subgraph group_data["Persistence"]
  node_schema[("Schema setup<br/>sql schema<br/>[database_setup.sql]")]
end

node_browser -->|"loads"| node_app
node_app -->|"shows"| node_home
node_app -->|"shows"| node_login
node_app -->|"shows"| node_register
node_app -->|"uses"| node_navbar
node_app -->|"uses"| node_footer
node_login -->|"delegates"| node_authform
node_register -->|"delegates"| node_authform
node_home -->|"uses"| node_uploadui
node_authform -->|"calls"| node_apiutil
node_uploadui -->|"calls"| node_apiutil
node_apiutil -->|"http"| node_server
node_server -->|"routes"| node_loginrt
node_server -->|"routes"| node_registerrt
node_server -->|"routes"| node_userrt
node_server -->|"routes"| node_filert
node_filert -->|"protects"| node_jwt
node_userrt -->|"protects"| node_jwt
node_loginrt -->|"uses"| node_usermodel
node_registerrt -->|"uses"| node_usermodel
node_userrt -->|"uses"| node_usermodel
node_filert -->|"delegates"| node_filectl
node_filectl -->|"reads/writes"| node_dbconfig
node_usermodel -->|"reads/writes"| node_dbconfig
node_dbconfig -->|"matches"| node_schema
node_schema -->|"persists"| node_dbconfig

click node_browser "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/main.jsx"
click node_app "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/App.jsx"
click node_home "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Home.jsx"
click node_login "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Login.jsx"
click node_register "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Register.jsx"
click node_authform "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/AuthForm.jsx"
click node_uploadui "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/FileUpload.jsx"
click node_apiutil "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/utils/api.js"
click node_navbar "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/Navbar.jsx"
click node_footer "https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/Footer.jsx"
click node_server "https://github.com/rsayyed591/photopia/blob/main/user-backend/index.js"
click node_loginrt "https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/login.js"
click node_registerrt "https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/register.js"
click node_userrt "https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/User.js"
click node_filert "https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/fileRoutes.js"
click node_jwt "https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/jwtMiddleware.js"
click node_filectl "https://github.com/rsayyed591/photopia/blob/main/user-backend/controllers/fileController.js"
click node_usermodel "https://github.com/rsayyed591/photopia/blob/main/user-backend/models/User.js"
click node_dbconfig "https://github.com/rsayyed591/photopia/blob/main/user-backend/config/db.js"
click node_schema "https://github.com/rsayyed591/photopia/blob/main/user-backend/database_setup.sql"

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_browser,node_app,node_home,node_login,node_register,node_authform,node_uploadui,node_apiutil,node_navbar,node_footer toneBlue
class node_server,node_loginrt,node_registerrt,node_userrt,node_filert,node_jwt,node_filectl,node_usermodel,node_dbconfig toneAmber
class node_schema toneMint
```

## Components

### Frontend

React/Vite client app

- [Browser UI](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/main.jsx): runtime · User-facing SPA runtime in the browser · `user-frontend/src/main.jsx`
- [App shell](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/App.jsx): spa shell · Top-level client routing and composition · `user-frontend/src/App.jsx`
- [Home](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Home.jsx): page · Main authenticated landing page · `user-frontend/src/pages/Home.jsx`
- [Login](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Login.jsx): page · Sign-in screen · `user-frontend/src/pages/Login.jsx`
- [Register](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/pages/Register.jsx): page · Account creation screen · `user-frontend/src/pages/Register.jsx`
- [Auth form](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/AuthForm.jsx): Shared login and registration form handling · `user-frontend/src/components/AuthForm.jsx`
- [Upload UI](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/FileUpload.jsx): Client-side photo upload interaction · `user-frontend/src/components/FileUpload.jsx`
- [API client](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/utils/api.js): utility · Shared HTTP wrapper using environment base URL · `user-frontend/src/utils/api.js`
- [Navbar](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/Navbar.jsx): Top-level navigation · `user-frontend/src/components/Navbar.jsx`
- [Footer](https://github.com/rsayyed591/photopia/blob/main/user-frontend/src/components/Footer.jsx): Page footer · `user-frontend/src/components/Footer.jsx`

### Backend

Express API and data access

- [Express app](https://github.com/rsayyed591/photopia/blob/main/user-backend/index.js): runtime · Backend HTTP entrypoint · `user-backend/index.js`
- [Login route](https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/login.js): route · Public sign-in endpoint · `user-backend/routes/login.js`
- [Register route](https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/register.js): route · Public account creation endpoint · `user-backend/routes/register.js`
- [User route](https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/User.js): route · Account and profile actions such as password change · `user-backend/routes/User.js`
- [File routes](https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/fileRoutes.js): route · Upload and file retrieval endpoints · `user-backend/routes/fileRoutes.js`
- [JWT guard](https://github.com/rsayyed591/photopia/blob/main/user-backend/routes/jwtMiddleware.js): middleware · Protects authenticated API routes · `user-backend/routes/jwtMiddleware.js`
- [File controller](https://github.com/rsayyed591/photopia/blob/main/user-backend/controllers/fileController.js): controller · Upload handling and file metadata logic · `user-backend/controllers/fileController.js`
- [User model](https://github.com/rsayyed591/photopia/blob/main/user-backend/models/User.js): model · User data access model · `user-backend/models/User.js`
- [DB config](https://github.com/rsayyed591/photopia/blob/main/user-backend/config/db.js): config · MySQL connection setup · `user-backend/config/db.js`

### Persistence

MySQL schema and stored records

- [Schema setup](https://github.com/rsayyed591/photopia/blob/main/user-backend/database_setup.sql): sql schema · Creates users and user_files tables · `user-backend/database_setup.sql`

## Connections

- Browser UI → App shell: loads · Browser runs the SPA entry and app shell
- App shell → Home: shows · App composition includes the home screen
- App shell → Login: shows · App composition includes the login screen
- App shell → Register: shows · App composition includes the registration screen
- App shell → Navbar: uses · Shared navigation across screens
- App shell → Footer: uses · Shared footer across screens
- Login → Auth form: delegates · Login screen reuses the shared auth form
- Register → Auth form: delegates · Registration screen reuses the shared auth form
- Home → Upload UI: uses · Home screen exposes file upload actions
- Auth form → API client: calls · Authentication submits requests through the API client
- Upload UI → API client: calls · Uploads and related actions use the shared API client
- API client → Express app: http · Frontend talks to the backend API over HTTP
- Express app → Login route: routes · Express mounts the login endpoint
- Express app → Register route: routes · Express mounts the registration endpoint
- Express app → User route: routes · Express mounts account-related endpoints
- Express app → File routes: routes · Express mounts file-related endpoints
- File routes → JWT guard: protects · Protected file endpoints pass through JWT middleware
- User route → JWT guard: protects · Protected user endpoints pass through JWT middleware
- Login route → User model: uses · Login route accesses the user model
- Register route → User model: uses · Register route accesses the user model
- User route → User model: uses · Account actions access the user model
- File routes → File controller: delegates · File routes delegate upload handling to the controller
- File controller → DB config: reads/writes · Controller uses the MySQL connection to persist metadata
- User model → DB config: reads/writes · Model uses the MySQL connection for user records
- DB config → Schema setup: matches · Connection targets the database defined by the schema bootstrap
- Schema setup → DB config: persists · Schema underpins the backend data store
