# souleyfall/airpost architecture

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

- Interactive diagram: https://gitdiagram.com/souleyfall/airpost
- Repository: https://github.com/souleyfall/airpost

## Overview

airpost is a personal apprenticeship-job search and application tracker. The user signs in, configures a profile, reviews collected and matched offers, drafts and validates tailored letters, and tracks application status and replies. The README documents Gmail drafts as user-reviewed only—never sent automatically—and lists the collection sources and Gemini letter generation. Backend source excerpts are incomplete, so unsampled collection, statistics, and reply-sync internals are represented at their existing subsystem directories; uncertain implementation links are omitted.

Main entry points: [`apps/web/src/App.tsx`](https://github.com/souleyfall/airpost/blob/main/apps/web/src/App.tsx) (Web routes), [`apps/web/src/api/client.ts`](https://github.com/souleyfall/airpost/blob/main/apps/web/src/api/client.ts) (API client), [`apps/api/src/prisma/prisma.service.ts`](https://github.com/souleyfall/airpost/blob/main/apps/api/src/prisma/prisma.service.ts) (PostgreSQL database), [`apps/api/src/llm/llm.service.ts`](https://github.com/souleyfall/airpost/blob/main/apps/api/src/llm/llm.service.ts) (LLM service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web application"]
  node_webapp["Web routes<br/>[App.tsx]"]
  node_webclient["API client<br/>[client.ts]"]
  node_login["Login screen<br/>[LoginPage.tsx]"]
  node_profileui["Profile screen<br/>[ProfilePage.tsx]"]
  node_reviewui["Offer review<br/>[ReviewPage.tsx]"]
  node_trackingui["Application tracking<br/>[TrackingPage.tsx]"]
  node_sourcesui["Sources screen<br/>[SourcesPage.tsx]"]
  node_statsui["Statistics screen<br/>[StatsPage.tsx]"]
end

subgraph group_workflow["Offer workflow"]
  node_profile["User profile<br/>[profile.service.ts]"]
  node_collection["Offer collection"]
  node_offerstore["Offer catalog<br/>[offers.service.ts]"]
  node_matching["Offer matching<br/>[match.service.ts]"]
  node_applications["Application lifecycle"]
  node_letters["Letter generation<br/>[letter.service.ts]"]
  node_stats["Application statistics<br/>[stats.service.ts]"]
end

subgraph group_integrations["External integrations"]
  node_sources["Job sources"]
  node_llm["LLM service<br/>[llm.service.ts]"]
  node_gmail["Gmail drafts and replies<br/>[gmail.service.ts]"]
  node_replysync["Reply synchronization"]
end

subgraph group_platform["API and persistence"]
  node_auth["Authentication<br/>[auth.controller.ts]"]
  node_guard["Session guard<br/>[auth.guard.ts]"]
  node_db[("PostgreSQL database<br/>[prisma.service.ts]")]
end

node_user(("User"))
node_gemini["Gemini"]
node_gmailservice["Gmail"]
node_jobproviders["Job providers"]

node_user -->|"uses"| node_webapp
node_webapp -->|"routes to"| node_login
node_webapp -->|"routes to"| node_profileui
node_webapp -->|"routes to"| node_reviewui
node_webapp -->|"routes to"| node_trackingui
node_webapp -->|"routes to"| node_sourcesui
node_webapp -->|"routes to"| node_statsui
node_login -->|"calls"| node_webclient
node_profileui -->|"calls"| node_webclient
node_reviewui -->|"calls"| node_webclient
node_trackingui -->|"calls"| node_webclient
node_sourcesui -->|"calls"| node_webclient
node_statsui -->|"calls"| node_webclient
node_webclient -->|"HTTP requests"| node_auth
node_auth -->|"creates sessions"| node_guard
node_guard -->|"checks session"| node_db
node_profile -->|"reads and writes"| node_db
node_collection -.->|"collects from"| node_sources
node_sources -.->|"queries"| node_jobproviders
node_collection -.->|"updates offers"| node_offerstore
node_matching -->|"reads and writes"| node_db
node_matching -->|"requests matches"| node_llm
node_llm -.->|"generates JSON"| node_gemini
node_applications -->|"reads and writes"| node_db
node_applications -.->|"manages drafts"| node_gmail
node_letters -.->|"generates letters"| node_llm
node_gmail -.->|"creates drafts"| node_gmailservice
node_replysync -.->|"checks replies"| node_gmailservice
node_replysync -.->|"updates applications"| node_db
node_stats -.->|"reads statistics"| node_db

click node_webapp "https://github.com/souleyfall/airpost/blob/main/apps/web/src/App.tsx"
click node_webclient "https://github.com/souleyfall/airpost/blob/main/apps/web/src/api/client.ts"
click node_login "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/LoginPage.tsx"
click node_profileui "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/profile/ProfilePage.tsx"
click node_reviewui "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/review/ReviewPage.tsx"
click node_trackingui "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/tracking/TrackingPage.tsx"
click node_sourcesui "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/sources/SourcesPage.tsx"
click node_statsui "https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/stats/StatsPage.tsx"
click node_auth "https://github.com/souleyfall/airpost/blob/main/apps/api/src/auth/auth.controller.ts"
click node_guard "https://github.com/souleyfall/airpost/blob/main/apps/api/src/auth/auth.guard.ts"
click node_profile "https://github.com/souleyfall/airpost/blob/main/apps/api/src/profile/profile.service.ts"
click node_collection "https://github.com/souleyfall/airpost/tree/main/apps/api/src/collection"
click node_sources "https://github.com/souleyfall/airpost/tree/main/apps/api/src/sources"
click node_offerstore "https://github.com/souleyfall/airpost/blob/main/apps/api/src/sources/offers.service.ts"
click node_matching "https://github.com/souleyfall/airpost/blob/main/apps/api/src/matching/match.service.ts"
click node_applications "https://github.com/souleyfall/airpost/blob/main/apps/api/src/applications/applications.service.ts"
click node_letters "https://github.com/souleyfall/airpost/blob/main/apps/api/src/letters/letter.service.ts"
click node_llm "https://github.com/souleyfall/airpost/blob/main/apps/api/src/llm/llm.service.ts"
click node_gmail "https://github.com/souleyfall/airpost/blob/main/apps/api/src/gmail/gmail.service.ts"
click node_replysync "https://github.com/souleyfall/airpost/blob/main/apps/api/src/gmail/reply-sync.service.ts"
click node_stats "https://github.com/souleyfall/airpost/blob/main/apps/api/src/stats/stats.service.ts"
click node_db "https://github.com/souleyfall/airpost/blob/main/apps/api/src/prisma/prisma.service.ts"

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_webapp,node_webclient,node_login,node_profileui,node_reviewui,node_trackingui,node_sourcesui,node_statsui,node_user toneBlue
class node_profile,node_collection,node_offerstore,node_matching,node_applications,node_letters,node_stats toneAmber
class node_sources,node_llm,node_gmail,node_replysync toneMint
class node_auth,node_guard,node_db toneRose
class node_gemini,node_gmailservice,node_jobproviders toneIndigo
```

## Components

### Web application

- [Web routes](https://github.com/souleyfall/airpost/blob/main/apps/web/src/App.tsx): `apps/web/src/App.tsx`
- [API client](https://github.com/souleyfall/airpost/blob/main/apps/web/src/api/client.ts): `apps/web/src/api/client.ts`
- [Login screen](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/LoginPage.tsx): `apps/web/src/pages/LoginPage.tsx`
- [Profile screen](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/profile/ProfilePage.tsx): `apps/web/src/pages/profile/ProfilePage.tsx`
- [Offer review](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/review/ReviewPage.tsx): `apps/web/src/pages/review/ReviewPage.tsx`
- [Application tracking](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/tracking/TrackingPage.tsx): `apps/web/src/pages/tracking/TrackingPage.tsx`
- [Sources screen](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/sources/SourcesPage.tsx): `apps/web/src/pages/sources/SourcesPage.tsx`
- [Statistics screen](https://github.com/souleyfall/airpost/blob/main/apps/web/src/pages/stats/StatsPage.tsx): `apps/web/src/pages/stats/StatsPage.tsx`

### Offer workflow

- [User profile](https://github.com/souleyfall/airpost/blob/main/apps/api/src/profile/profile.service.ts): `apps/api/src/profile/profile.service.ts`
- [Offer collection](https://github.com/souleyfall/airpost/tree/main/apps/api/src/collection): `apps/api/src/collection`
- [Offer catalog](https://github.com/souleyfall/airpost/blob/main/apps/api/src/sources/offers.service.ts): `apps/api/src/sources/offers.service.ts`
- [Offer matching](https://github.com/souleyfall/airpost/blob/main/apps/api/src/matching/match.service.ts): `apps/api/src/matching/match.service.ts`
- [Application lifecycle](https://github.com/souleyfall/airpost/blob/main/apps/api/src/applications/applications.service.ts): `apps/api/src/applications/applications.service.ts`
- [Letter generation](https://github.com/souleyfall/airpost/blob/main/apps/api/src/letters/letter.service.ts): `apps/api/src/letters/letter.service.ts`
- [Application statistics](https://github.com/souleyfall/airpost/blob/main/apps/api/src/stats/stats.service.ts): `apps/api/src/stats/stats.service.ts`

### External integrations

- [Job sources](https://github.com/souleyfall/airpost/tree/main/apps/api/src/sources): `apps/api/src/sources`
- [LLM service](https://github.com/souleyfall/airpost/blob/main/apps/api/src/llm/llm.service.ts): `apps/api/src/llm/llm.service.ts`
- [Gmail drafts and replies](https://github.com/souleyfall/airpost/blob/main/apps/api/src/gmail/gmail.service.ts): `apps/api/src/gmail/gmail.service.ts`
- [Reply synchronization](https://github.com/souleyfall/airpost/blob/main/apps/api/src/gmail/reply-sync.service.ts): `apps/api/src/gmail/reply-sync.service.ts`

### API and persistence

- [Authentication](https://github.com/souleyfall/airpost/blob/main/apps/api/src/auth/auth.controller.ts): `apps/api/src/auth/auth.controller.ts`
- [Session guard](https://github.com/souleyfall/airpost/blob/main/apps/api/src/auth/auth.guard.ts): `apps/api/src/auth/auth.guard.ts`
- [PostgreSQL database](https://github.com/souleyfall/airpost/blob/main/apps/api/src/prisma/prisma.service.ts): `apps/api/src/prisma/prisma.service.ts`

### Other components

- **User**
- **Gemini**
- **Gmail**
- **Job providers**

## Connections

- User → Web routes: uses (evidence: `apps/web/src/App.tsx`)
- Web routes → Login screen: routes to (evidence: `apps/web/src/App.tsx`)
- Web routes → Profile screen: routes to (evidence: `apps/web/src/App.tsx`)
- Web routes → Offer review: routes to (evidence: `apps/web/src/App.tsx`)
- Web routes → Application tracking: routes to (evidence: `apps/web/src/App.tsx`)
- Web routes → Sources screen: routes to (evidence: `apps/web/src/App.tsx`)
- Web routes → Statistics screen: routes to (evidence: `apps/web/src/App.tsx`)
- Login screen → API client: calls (evidence: `apps/web/src/pages/LoginPage.tsx`)
- Profile screen → API client: calls (evidence: `apps/web/src/pages/profile/ProfilePage.tsx`)
- Offer review → API client: calls (evidence: `apps/web/src/pages/review/ReviewPage.tsx`)
- Application tracking → API client: calls (evidence: `apps/web/src/pages/tracking/TrackingPage.tsx`)
- Sources screen → API client: calls (evidence: `apps/web/src/pages/sources/SourcesPage.tsx`)
- Statistics screen → API client: calls (evidence: `apps/web/src/pages/stats/StatsPage.tsx`)
- API client → Authentication: HTTP requests (evidence: `apps/web/src/api/client.ts`)
- Authentication → Session guard: creates sessions (evidence: `apps/api/src/auth/auth.controller.ts`)
- Session guard → PostgreSQL database: checks session (evidence: `apps/api/src/auth/auth.guard.ts`)
- User profile → PostgreSQL database: reads and writes (evidence: `apps/api/src/profile/profile.service.ts`)
- Offer collection → Job sources: collects from (evidence: `apps/api/src/collection/collection.controller.ts`)
- Job sources → Job providers: queries
- Offer collection → Offer catalog: updates offers
- Offer matching → PostgreSQL database: reads and writes (evidence: `apps/api/src/matching/match.service.ts`)
- Offer matching → LLM service: requests matches (evidence: `apps/api/src/matching/match.service.ts`)
- LLM service → Gemini: generates JSON
- Application lifecycle → PostgreSQL database: reads and writes (evidence: `apps/api/src/applications/applications.service.ts`)
- Application lifecycle → Gmail drafts and replies: manages drafts (evidence: `apps/api/src/applications/applications.service.ts`)
- Letter generation → LLM service: generates letters
- Gmail drafts and replies → Gmail: creates drafts
- Reply synchronization → Gmail: checks replies
- Reply synchronization → PostgreSQL database: updates applications
- Application statistics → PostgreSQL database: reads statistics
