# adrianhajdin/jsm_bookified architecture

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

- Interactive diagram: https://gitdiagram.com/adrianhajdin/jsm_bookified
- Repository: https://github.com/adrianhajdin/jsm_bookified

## Overview

Bookified is a Next.js app for browsing a book library and turning uploaded PDFs into searchable, voice-interactive companions. The primary flow is upload and parse a PDF, store book metadata and text segments, open the book, then start a Vapi conversation whose sessions are checked against subscription limits and recorded. The README also describes persona previews, summaries, transcripts, authentication, and subscriptions. Some of those capabilities are documented but their implementation is not shown in the excerpts, so their connections are marked unverified or omitted.

Main entry points: [`lib/actions/book.actions.ts`](https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/actions/book.actions.ts) (Book Operations), [`hooks/useVapi.ts`](https://github.com/adrianhajdin/jsm_bookified/blob/main/hooks/useVapi.ts) (Call Lifecycle), [`app/(root)/page.tsx`](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/page.tsx) (Library Page), [`components/UploadForm.tsx`](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/UploadForm.tsx) (PDF Upload Form)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_library["Library and Upload"]
  node_library_page["Library Page<br/>[page.tsx]"]
  node_search_ui["Library Search<br/>[Search.tsx]"]
  node_book_card["Book Card<br/>[BookCard.tsx]"]
  node_upload_page["New Book Page<br/>[page.tsx]"]
  node_upload_form["PDF Upload Form<br/>[UploadForm.tsx]"]
  node_pdf_processing["PDF Parsing<br/>[utils.ts]"]
  node_upload_api["Blob Upload Handler<br/>[route.ts]"]
end

subgraph group_conversation["Voice Conversations"]
  node_book_detail["Book Detail<br/>[page.tsx]"]
  node_voice_controls["Voice Controls<br/>[VapiControls.tsx]"]
  node_vapi_hook["Call Lifecycle<br/>[useVapi.ts]"]
  node_transcript["Live Transcript<br/>[Transcript.tsx]"]
  node_search_api["Book Context Search<br/>[route.ts]"]
end

subgraph group_data["Book and Session Data"]
  node_book_actions["Book Operations<br/>[book.actions.ts]"]
  node_session_actions["Session Operations<br/>[session.actions.ts]"]
  node_book_store[("Book Records<br/>[book.model.ts]")]
  node_segment_store[("Text Segments")]
  node_session_store[("Voice Sessions")]
  node_mongo["MongoDB Connection<br/>[mongoose.ts]"]
end

subgraph group_plans["Identity and Plans"]
  node_clerk["Clerk Identity"]
  node_subscription_hook["Plan Limits<br/>[useSubscription.ts]"]
  node_subscription_server["Server Plan Lookup"]
  node_subscription_page["Subscription Page<br/>[page.tsx]"]
end

node_reader(("Reader"))
node_blob_storage[("Vercel Blob")]
node_vapi["Vapi Voice Service"]
node_elevenlabs["ElevenLabs Voices"]

node_reader -->|"browses"| node_library_page
node_library_page -->|"loads books"| node_book_actions
node_library_page -->|"renders"| node_search_ui
node_library_page -->|"renders"| node_book_card
node_reader -->|"uploads book"| node_upload_page
node_upload_page -->|"renders"| node_upload_form
node_upload_form -->|"parses PDF"| node_pdf_processing
node_upload_form -->|"requests upload"| node_upload_api
node_upload_api -.->|"stores PDF"| node_blob_storage
node_upload_form -->|"creates book"| node_book_actions
node_book_actions -->|"inserts segments"| node_segment_store
node_book_actions -->|"reads and writes"| node_book_store
node_book_actions -->|"connects to"| node_mongo
node_reader -.->|"opens book"| node_book_detail
node_book_detail -.->|"loads book"| node_book_actions
node_book_detail -->|"renders"| node_voice_controls
node_voice_controls -->|"controls calls"| node_vapi_hook
node_voice_controls -->|"renders"| node_transcript
node_vapi_hook -.->|"starts voice calls"| node_vapi
node_vapi_hook -->|"records sessions"| node_session_actions
node_vapi_hook -->|"checks limits"| node_subscription_hook
node_vapi_hook -.->|"selects voice"| node_elevenlabs
node_search_api -.->|"searches context"| node_book_actions
node_session_actions -->|"reads and writes"| node_session_store
node_session_actions -->|"connects to"| node_mongo
node_session_actions -->|"checks plan"| node_subscription_server
node_subscription_hook -->|"reads plan"| node_clerk
node_subscription_server -.->|"looks up plan"| node_clerk
node_reader -.->|"manages subscription"| node_subscription_page

click node_library_page "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/page.tsx"
click node_search_ui "https://github.com/adrianhajdin/jsm_bookified/blob/main/components/Search.tsx"
click node_book_card "https://github.com/adrianhajdin/jsm_bookified/blob/main/components/BookCard.tsx"
click node_upload_page "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/books/new/page.tsx"
click node_upload_form "https://github.com/adrianhajdin/jsm_bookified/blob/main/components/UploadForm.tsx"
click node_pdf_processing "https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/utils.ts"
click node_upload_api "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/api/upload/route.ts"
click node_book_detail "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/books/%5Bslug%5D/page.tsx"
click node_voice_controls "https://github.com/adrianhajdin/jsm_bookified/blob/main/components/VapiControls.tsx"
click node_vapi_hook "https://github.com/adrianhajdin/jsm_bookified/blob/main/hooks/useVapi.ts"
click node_transcript "https://github.com/adrianhajdin/jsm_bookified/blob/main/components/Transcript.tsx"
click node_search_api "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/api/vapi/search-book/route.ts"
click node_book_actions "https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/actions/book.actions.ts"
click node_session_actions "https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/actions/session.actions.ts"
click node_book_store "https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/book.model.ts"
click node_segment_store "https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/book-segment.model.ts"
click node_session_store "https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/voice-session.model.ts"
click node_mongo "https://github.com/adrianhajdin/jsm_bookified/blob/main/database/mongoose.ts"
click node_subscription_hook "https://github.com/adrianhajdin/jsm_bookified/blob/main/hooks/useSubscription.ts"
click node_subscription_server "https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/subscription.server.ts"
click node_subscription_page "https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/subscriptions/page.tsx"

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_library_page,node_search_ui,node_book_card,node_upload_page,node_upload_form,node_pdf_processing,node_upload_api toneBlue
class node_book_detail,node_voice_controls,node_vapi_hook,node_transcript,node_search_api,node_blob_storage toneAmber
class node_book_actions,node_session_actions,node_book_store,node_segment_store,node_session_store,node_mongo,node_vapi toneMint
class node_clerk,node_subscription_hook,node_subscription_server,node_subscription_page toneRose
class node_reader,node_elevenlabs toneIndigo
```

## Components

### Library and Upload

- [Library Page](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/page.tsx): `app/(root)/page.tsx`
- [Library Search](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/Search.tsx): `components/Search.tsx`
- [Book Card](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/BookCard.tsx): `components/BookCard.tsx`
- [New Book Page](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/books/new/page.tsx): `app/(root)/books/new/page.tsx`
- [PDF Upload Form](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/UploadForm.tsx): `components/UploadForm.tsx`
- [PDF Parsing](https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/utils.ts): `lib/utils.ts`
- [Blob Upload Handler](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/api/upload/route.ts): `app/api/upload/route.ts`

### Voice Conversations

- [Book Detail](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/books/%5Bslug%5D/page.tsx): `app/books/[slug]/page.tsx`
- [Voice Controls](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/VapiControls.tsx): `components/VapiControls.tsx`
- [Call Lifecycle](https://github.com/adrianhajdin/jsm_bookified/blob/main/hooks/useVapi.ts): `hooks/useVapi.ts`
- [Live Transcript](https://github.com/adrianhajdin/jsm_bookified/blob/main/components/Transcript.tsx): `components/Transcript.tsx`
- [Book Context Search](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/api/vapi/search-book/route.ts): `app/api/vapi/search-book/route.ts`

### Book and Session Data

- [Book Operations](https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/actions/book.actions.ts): `lib/actions/book.actions.ts`
- [Session Operations](https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/actions/session.actions.ts): `lib/actions/session.actions.ts`
- [Book Records](https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/book.model.ts): `database/models/book.model.ts`
- [Text Segments](https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/book-segment.model.ts): `database/models/book-segment.model.ts`
- [Voice Sessions](https://github.com/adrianhajdin/jsm_bookified/blob/main/database/models/voice-session.model.ts): `database/models/voice-session.model.ts`
- [MongoDB Connection](https://github.com/adrianhajdin/jsm_bookified/blob/main/database/mongoose.ts): `database/mongoose.ts`

### Identity and Plans

- **Clerk Identity**
- [Plan Limits](https://github.com/adrianhajdin/jsm_bookified/blob/main/hooks/useSubscription.ts): `hooks/useSubscription.ts`
- [Server Plan Lookup](https://github.com/adrianhajdin/jsm_bookified/blob/main/lib/subscription.server.ts): `lib/subscription.server.ts`
- [Subscription Page](https://github.com/adrianhajdin/jsm_bookified/blob/main/app/(root)/subscriptions/page.tsx): `app/(root)/subscriptions/page.tsx`

### Other components

- **Reader**
- **Vercel Blob**
- **Vapi Voice Service**
- **ElevenLabs Voices**

## Connections

- Reader → Library Page: browses
- Library Page → Book Operations: loads books (evidence: `app/(root)/page.tsx`)
- Library Page → Library Search: renders (evidence: `app/(root)/page.tsx`)
- Library Page → Book Card: renders (evidence: `app/(root)/page.tsx`)
- Reader → New Book Page: uploads book
- New Book Page → PDF Upload Form: renders (evidence: `app/(root)/books/new/page.tsx`)
- PDF Upload Form → PDF Parsing: parses PDF (evidence: `components/UploadForm.tsx`)
- PDF Upload Form → Blob Upload Handler: requests upload (evidence: `components/UploadForm.tsx`)
- Blob Upload Handler → Vercel Blob: stores PDF
- PDF Upload Form → Book Operations: creates book (evidence: `components/UploadForm.tsx`)
- Book Operations → Text Segments: inserts segments (evidence: `lib/actions/book.actions.ts`)
- Book Operations → Book Records: reads and writes (evidence: `lib/actions/book.actions.ts`)
- Book Operations → MongoDB Connection: connects to (evidence: `lib/actions/book.actions.ts`)
- Reader → Book Detail: opens book
- Book Detail → Book Operations: loads book (evidence: `app/books/[slug]/page.tsx`)
- Book Detail → Voice Controls: renders (evidence: `app/books/[slug]/page.tsx`)
- Voice Controls → Call Lifecycle: controls calls (evidence: `components/VapiControls.tsx`)
- Voice Controls → Live Transcript: renders (evidence: `components/VapiControls.tsx`)
- Call Lifecycle → Vapi Voice Service: starts voice calls
- Call Lifecycle → Session Operations: records sessions (evidence: `hooks/useVapi.ts`)
- Call Lifecycle → Plan Limits: checks limits (evidence: `hooks/useVapi.ts`)
- Call Lifecycle → ElevenLabs Voices: selects voice
- Book Context Search → Book Operations: searches context (evidence: `app/api/vapi/search-book/route.ts`)
- Session Operations → Voice Sessions: reads and writes (evidence: `lib/actions/session.actions.ts`)
- Session Operations → MongoDB Connection: connects to (evidence: `lib/actions/session.actions.ts`)
- Session Operations → Server Plan Lookup: checks plan (evidence: `lib/actions/session.actions.ts`)
- Plan Limits → Clerk Identity: reads plan (evidence: `hooks/useSubscription.ts`)
- Server Plan Lookup → Clerk Identity: looks up plan
- Reader → Subscription Page: manages subscription
