# traejiik/pocketbook architecture

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

- Interactive diagram: https://gitdiagram.com/traejiik/pocketbook
- Repository: https://github.com/traejiik/pocketbook

## Overview

Pocketbook is a self-hosted personal-finance tracker. A user signs in, reviews dashboard and ledger data, and records or imports transactions; recurring rules, renewals, categories, and settings support that ledger. Server-rendered pages read finance data, while Server Actions perform mutations and refresh cached views. Scheduled jobs sync FX rates, log due recurring charges, and can generate monthly insights; on-demand insights stream from a local Ollama model and are saved for history. The tree and excerpts support the main entry points and some handlers, but not every page-to-action connection.

Main entry points: [`lib/prisma.ts`](https://github.com/traejiik/pocketbook/blob/main/lib/prisma.ts) (PostgreSQL), [`app/api/insights/stream/route.ts`](https://github.com/traejiik/pocketbook/blob/main/app/api/insights/stream/route.ts) (Insight stream), [`app/api/insights/monthly/route.ts`](https://github.com/traejiik/pocketbook/blob/main/app/api/insights/monthly/route.ts) (Monthly generation), [`runtime/scheduler.ts`](https://github.com/traejiik/pocketbook/blob/main/runtime/scheduler.ts) (UTC scheduler)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_access["Access and finance UI"]
  node_login["Sign in<br/>[page.tsx]"]
  node_app["Finance workspace<br/>[layout.tsx]"]
  node_dashboard["Dashboard<br/>[page.tsx]"]
end

subgraph group_ledger["Ledger management"]
  node_transactions["Transactions<br/>[page.tsx]"]
  node_categories["Categories<br/>[page.tsx]"]
  node_recurring["Recurring rules<br/>[page.tsx]"]
  node_renewals["Renewal radar<br/>[page.tsx]"]
  node_import_ui["Import review"]
  node_recurring_import["Recurring import review"]
  node_actions_transactions["Transaction actions<br/>[transactions.ts]"]
  node_actions_import["Import actions<br/>[import.ts]"]
  node_actions_recurring["Recurring actions<br/>[recurring.ts]"]
  node_categories_action["Category actions<br/>[categories.ts]"]
end

subgraph group_insights["Private insights"]
  node_insights_page["Monthly insights<br/>[page.tsx]"]
  node_insight_stream["Insight stream<br/>[route.ts]"]
  node_insight_monthly["Monthly generation<br/>[route.ts]"]
  node_generation["Insight generation"]
end

subgraph group_operations["Scheduled operations"]
  node_scheduler["UTC scheduler<br/>[scheduler.ts]"]
  node_fx_route["FX sync endpoint<br/>[route.ts]"]
  node_fx_sync["FX rate sync<br/>[frankfurter.ts]"]
  node_recurring_route["Recurring sync endpoint<br/>[route.ts]"]
  node_recurring_sync["Due-rule processing<br/>[recurring-sync.ts]"]
  node_notification["Discord notifications<br/>[send.ts]"]
end

node_user(("Finance user"))
node_ollama{{"Ollama model"}}
node_database[("PostgreSQL<br/>[prisma.ts]")]

node_user -->|"signs in"| node_login
node_login -->|"opens"| node_app
node_app -->|"renders"| node_dashboard
node_dashboard -->|"reads finance data"| node_database
node_transactions -->|"reads ledger"| node_database
node_categories -->|"reads categories"| node_database
node_recurring -->|"reads rules"| node_database
node_renewals -->|"reads upcoming"| node_database
node_import_ui -->|"commits rows"| node_actions_import
node_recurring_import -->|"commits rules"| node_actions_import
node_recurring_import -->|"creates category"| node_categories_action
node_actions_transactions -->|"writes ledger"| node_database
node_actions_recurring -->|"writes rules"| node_database
node_categories_action -->|"writes categories"| node_database
node_actions_import -->|"writes imports"| node_database
node_insights_page -->|"requests stream"| node_insight_stream
node_insight_stream -->|"builds prompt"| node_generation
node_insight_stream -->|"streams generation"| node_ollama
node_insight_stream -->|"saves insight"| node_database
node_scheduler -->|"calls sync"| node_fx_route
node_fx_route -->|"syncs rates"| node_fx_sync
node_fx_sync -->|"stores rates"| node_database
node_scheduler -->|"calls sync"| node_recurring_route
node_recurring_route -->|"processes due rules"| node_recurring_sync
node_recurring_sync -->|"writes transactions"| node_database
node_scheduler -->|"triggers monthly"| node_insight_monthly
node_insight_monthly -->|"generates note"| node_generation
node_insight_monthly -->|"reads settings"| node_database
node_insight_monthly -->|"sends alert"| node_notification

click node_login "https://github.com/traejiik/pocketbook/blob/main/app/(auth)/login/page.tsx"
click node_app "https://github.com/traejiik/pocketbook/blob/main/app/(app)/layout.tsx"
click node_dashboard "https://github.com/traejiik/pocketbook/blob/main/app/(app)/dashboard/page.tsx"
click node_transactions "https://github.com/traejiik/pocketbook/blob/main/app/(app)/transactions/page.tsx"
click node_categories "https://github.com/traejiik/pocketbook/blob/main/app/(app)/categories/page.tsx"
click node_recurring "https://github.com/traejiik/pocketbook/blob/main/app/(app)/recurring/page.tsx"
click node_renewals "https://github.com/traejiik/pocketbook/blob/main/app/(app)/renewals/page.tsx"
click node_import_ui "https://github.com/traejiik/pocketbook/blob/main/components/import/TransactionImportReview.tsx"
click node_recurring_import "https://github.com/traejiik/pocketbook/blob/main/components/import/RecurringImportReview.tsx"
click node_actions_transactions "https://github.com/traejiik/pocketbook/blob/main/server-actions/transactions.ts"
click node_actions_import "https://github.com/traejiik/pocketbook/blob/main/server-actions/import.ts"
click node_actions_recurring "https://github.com/traejiik/pocketbook/blob/main/server-actions/recurring.ts"
click node_categories_action "https://github.com/traejiik/pocketbook/blob/main/server-actions/categories.ts"
click node_insights_page "https://github.com/traejiik/pocketbook/blob/main/app/(app)/insights/page.tsx"
click node_insight_stream "https://github.com/traejiik/pocketbook/blob/main/app/api/insights/stream/route.ts"
click node_insight_monthly "https://github.com/traejiik/pocketbook/blob/main/app/api/insights/monthly/route.ts"
click node_generation "https://github.com/traejiik/pocketbook/blob/main/lib/insights-generation.ts"
click node_scheduler "https://github.com/traejiik/pocketbook/blob/main/runtime/scheduler.ts"
click node_fx_route "https://github.com/traejiik/pocketbook/blob/main/app/api/fx/sync/route.ts"
click node_fx_sync "https://github.com/traejiik/pocketbook/blob/main/lib/frankfurter.ts"
click node_recurring_route "https://github.com/traejiik/pocketbook/blob/main/app/api/recurring/sync/route.ts"
click node_recurring_sync "https://github.com/traejiik/pocketbook/blob/main/lib/recurring-sync.ts"
click node_database "https://github.com/traejiik/pocketbook/blob/main/lib/prisma.ts"
click node_notification "https://github.com/traejiik/pocketbook/blob/main/lib/notifications/send.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_login,node_app,node_dashboard,node_user toneBlue
class node_transactions,node_categories,node_recurring,node_renewals,node_import_ui,node_recurring_import,node_actions_transactions,node_actions_import,node_actions_recurring,node_categories_action,node_database toneAmber
class node_insights_page,node_insight_stream,node_insight_monthly,node_generation toneMint
class node_scheduler,node_fx_route,node_fx_sync,node_recurring_route,node_recurring_sync,node_notification toneRose
class node_ollama toneIndigo
```

## Components

### Access and finance UI

- [Sign in](https://github.com/traejiik/pocketbook/blob/main/app/(auth)/login/page.tsx): `app/(auth)/login/page.tsx`
- [Finance workspace](https://github.com/traejiik/pocketbook/blob/main/app/(app)/layout.tsx): `app/(app)/layout.tsx`
- [Dashboard](https://github.com/traejiik/pocketbook/blob/main/app/(app)/dashboard/page.tsx): `app/(app)/dashboard/page.tsx`

### Ledger management

- [Transactions](https://github.com/traejiik/pocketbook/blob/main/app/(app)/transactions/page.tsx): `app/(app)/transactions/page.tsx`
- [Categories](https://github.com/traejiik/pocketbook/blob/main/app/(app)/categories/page.tsx): `app/(app)/categories/page.tsx`
- [Recurring rules](https://github.com/traejiik/pocketbook/blob/main/app/(app)/recurring/page.tsx): `app/(app)/recurring/page.tsx`
- [Renewal radar](https://github.com/traejiik/pocketbook/blob/main/app/(app)/renewals/page.tsx): `app/(app)/renewals/page.tsx`
- [Import review](https://github.com/traejiik/pocketbook/blob/main/components/import/TransactionImportReview.tsx): `components/import/TransactionImportReview.tsx`
- [Recurring import review](https://github.com/traejiik/pocketbook/blob/main/components/import/RecurringImportReview.tsx): `components/import/RecurringImportReview.tsx`
- [Transaction actions](https://github.com/traejiik/pocketbook/blob/main/server-actions/transactions.ts): `server-actions/transactions.ts`
- [Import actions](https://github.com/traejiik/pocketbook/blob/main/server-actions/import.ts): `server-actions/import.ts`
- [Recurring actions](https://github.com/traejiik/pocketbook/blob/main/server-actions/recurring.ts): `server-actions/recurring.ts`
- [Category actions](https://github.com/traejiik/pocketbook/blob/main/server-actions/categories.ts): `server-actions/categories.ts`

### Private insights

- [Monthly insights](https://github.com/traejiik/pocketbook/blob/main/app/(app)/insights/page.tsx): `app/(app)/insights/page.tsx`
- [Insight stream](https://github.com/traejiik/pocketbook/blob/main/app/api/insights/stream/route.ts): `app/api/insights/stream/route.ts`
- [Monthly generation](https://github.com/traejiik/pocketbook/blob/main/app/api/insights/monthly/route.ts): `app/api/insights/monthly/route.ts`
- [Insight generation](https://github.com/traejiik/pocketbook/blob/main/lib/insights-generation.ts): `lib/insights-generation.ts`

### Scheduled operations

- [UTC scheduler](https://github.com/traejiik/pocketbook/blob/main/runtime/scheduler.ts): `runtime/scheduler.ts`
- [FX sync endpoint](https://github.com/traejiik/pocketbook/blob/main/app/api/fx/sync/route.ts): `app/api/fx/sync/route.ts`
- [FX rate sync](https://github.com/traejiik/pocketbook/blob/main/lib/frankfurter.ts): `lib/frankfurter.ts`
- [Recurring sync endpoint](https://github.com/traejiik/pocketbook/blob/main/app/api/recurring/sync/route.ts): `app/api/recurring/sync/route.ts`
- [Due-rule processing](https://github.com/traejiik/pocketbook/blob/main/lib/recurring-sync.ts): `lib/recurring-sync.ts`
- [Discord notifications](https://github.com/traejiik/pocketbook/blob/main/lib/notifications/send.ts): `lib/notifications/send.ts`

### Other components

- **Finance user**
- **Ollama model**
- [PostgreSQL](https://github.com/traejiik/pocketbook/blob/main/lib/prisma.ts): `lib/prisma.ts`

## Connections

- Finance user → Sign in: signs in
- Sign in → Finance workspace: opens
- Finance workspace → Dashboard: renders
- Dashboard → PostgreSQL: reads finance data
- Transactions → PostgreSQL: reads ledger
- Categories → PostgreSQL: reads categories
- Recurring rules → PostgreSQL: reads rules
- Renewal radar → PostgreSQL: reads upcoming
- Import review → Import actions: commits rows
- Recurring import review → Import actions: commits rules
- Recurring import review → Category actions: creates category
- Transaction actions → PostgreSQL: writes ledger
- Recurring actions → PostgreSQL: writes rules
- Category actions → PostgreSQL: writes categories
- Import actions → PostgreSQL: writes imports
- Monthly insights → Insight stream: requests stream
- Insight stream → Insight generation: builds prompt
- Insight stream → Ollama model: streams generation
- Insight stream → PostgreSQL: saves insight
- UTC scheduler → FX sync endpoint: calls sync
- FX sync endpoint → FX rate sync: syncs rates
- FX rate sync → PostgreSQL: stores rates
- UTC scheduler → Recurring sync endpoint: calls sync
- Recurring sync endpoint → Due-rule processing: processes due rules
- Due-rule processing → PostgreSQL: writes transactions
- UTC scheduler → Monthly generation: triggers monthly
- Monthly generation → Insight generation: generates note
- Monthly generation → PostgreSQL: reads settings
- Monthly generation → Discord notifications: sends alert
