Pure Literature. Zero Paywalls. Zero API Keys Required.
An open-source, offline-first web application and reader for discovering, reading, and downloading public domain books (Project Gutenberg / CC0). Built with Next.js 16 App Router, Tailwind CSS, and Zustand persistence, deployed on the Vercel Edge Platform, developed with Google AI / Antigravity, and verified by a deterministic 7-Gateway Quality Engine.
Bookarium is powered by a self-hosted Supabase PostgreSQL catalog (78,000+ volumes) featuring GIN full-text search and pre-computed author lifespan indexes, delivering sub-50ms single-book lookups and dependable ~1β2s catalog page queries (compared to 20β60s queue delays on public APIs). To guarantee continuous uptime and zero-configuration setups, it includes an automatic failover to the upstream Gutendex REST API and Project Gutenberg mirrors whenever the database is unseeded, unreachable, or undergoing maintenance.
Bookarium's visual identity and tactile layout are deeply inspired by classical editorial typography, archival letterpress printing, and modern Figma bookstore design systems:
- Figma Editorial Concept: Inspired by the minimalist elegance of curated bookstore layouts, specifically referencing the Booksaw β Bookstore E-Commerce Website Design Template on the Figma Community.
- Open-Book Skeuomorphic Details: Custom open-book card spreads with subtle center spine creases (
.book-center-crease), realistic paper texture shadows (shadow-booksaw), and page depth elevation. - Warm Editorial Palettes & 100% Solid Surfaces:
- Day / Standard: Crisp cream-paper tones (
#fcfbf9,#ffffff) with rich obsidian ink typography and 100% solid, non-transparent surfaces. - Sepia / Cozy Coffee (Warm Midtone): Warm roasted espresso and cafe mocha tones (
#2b1d16,#3c281e,#332219) with steamed milk cream typography (#fef6eb) and warm caramel amber accents (#f59e0b) for eye comfort in ambient evening light. - Dark Mode: High-contrast slate obsidian canvas (
#0e1117,#161b26) preserving focus in low-light settings.
- Day / Standard: Crisp cream-paper tones (
- Refined Typography: Pairings of classic literary serifs, clean sans-serifs, and monospace archival metadata accents.
- Hardware-Accelerated Mobile Dock Auto-Fade (
src/components/presentation/StickyCatalogToolbar.tsx): Integrated scroll inactivity auto-fade transitioning the floating mobile catalog capsule dock toopacity-0 pointer-events-noneafter 1,400ms of inactivity, waking instantly (<180ms) upon scrolling, touching, or hovering. - Directional View Slide Transitions (
src/app/globals.css,src/app/page.tsx): Built 220ms hardware-accelerated slide-in transitions (animate-view-slide-leftfrom right on forward swipe,animate-view-slide-rightfrom left on backward swipe), with clean fallback to grounded Booksaw vertical fade (animate-page-turn) on manual tab taps and full@media (prefers-reduced-motion: reduce)accessibility support. - Biomechanical Touch-Swipe Ergonomics (
src/hooks/useMobileViewSwipe.ts): RelaxeddominanceRatiofrom 1.8 to 1.25 to natively support natural human thumb arcs (up to 38.6Β°), extendedmaxDurationMsfrom 500ms to 650ms for deliberate swipes, loweredminDistancePxfrom 50px to 40px for responsive flicks, and addedlastSwipeDirectionstate withonSwipeDirectioncallbacks. - Unified View-Transition Wrapper (
src/app/page.tsx): Consolidated view presentation containers across Catalog, Bookshelf, Favorites, Bookmarks, and Notebook into a unified dynamic transition wrapper with automatic direction cleanup on animation end. - Collection Sort Dropdown Icon Overlap (
src/components/presentation/CollectionSortDropdown.tsx): Replaced arbitrary Tailwind classes with standard spacing (pl-8 sm:pl-9 pr-7 sm:pr-8) and bounded width (min-w-[125px] sm:min-w-[145px] max-w-[165px] sm:max-w-[195px]), guaranteeing a clean 10px clear gutter from the ArrowUpDown icon.
π Complete Historical Ledger: For full chronological release notes, breaking changes, and migration details across all versions, see
CHANGELOG.md.
Bookarium runs on an open, decentralized architecture requiring Zero Paid Developer Keys:
| Service / Source | Endpoint / Provider | Description & Usage |
|---|---|---|
| Self-Hosted Supabase Catalog | public.books (PostgreSQL) |
Primary catalog provider hosting 78,000+ Project Gutenberg titles with automated GIN full-text search (search_vector) and pre-computed author lifespan indexes, delivering sub-50ms single-book copyright verification, consistent ~1β2s 32-volume catalog page searches, and zero-egress searches. |
| Gutendex REST API | gutendex.com β’ GitHub |
Resilient upstream search fallback created by Gareth B. Johnson indexing 70,000+ titles with strict copyright=false filtering. Engaged automatically when Supabase is unseeded or offline. |
| Project Gutenberg CDN & Mirrors | gutenberg.org β’ Mirrors |
Content delivery network and mirrors (aleph.gutenberg.org, gutenberg.readingroo.ms) providing plain text (.txt), official EPUB packages (.epub.images), Kindle/MOBI formats, and web-ready HTML. |
| Supabase (Auth, Sync & Catalog) | supabase.com |
Cloud authentication, user library synchronization (bookshelves, annotations, progress, streaks, accolades) with RLS user isolation, and self-hosted public domain catalog. |
| Vercel Edge Platform | vercel.com |
High-performance edge deployment, dynamic SSR route handlers, zero-config production caching, global CDN delivery, and cookie-less aggregate performance telemetry (Vercel Web Analytics & Speed Insights). |
| Public Domain Archive Proxies | /api/books & /api/books/content |
Next.js server-side route proxies providing caching, Strangler Fig dual-provider catalog resolution, Tier 1/Tier 2 content streaming, and guaranteed public domain integrity before client delivery. |
Bookarium is structured around five core engineering pillars:
- Booksaw Editorial Aesthetic: Classical typography inspired by fine art bookstore catalogues, featuring open-book card spreads with center spine creases, realistic paper shadows, and 100% solid non-transparent surfaces across Day (
#fcfbf9), Cozy Coffee Sepia (#2b1d16), and Dark Obsidian (#0e1117) themes. - Hourly Rotating 3D Featured Book (27-Masterwork Curated Anthology): Expanded pool of 27 verified public domain masterworks across world literature (Austen, Shelley, Tolstoy, Hugo, Dostoevsky, BrontΓ«, Kafka, Stevenson, Dumas, Machiavelli, Sun Tzu, Marcus Aurelius, Homer, Alcott, Poe, Verne, Thoreau, Twain) rotated every UTC hour with zero-cron deterministic synchronization.
- Synchronized Dynamic SSR & Zero-Flash Pre-Hydration: Edge-stamped geo-cookie (
bookarium-geo-country) extracted at the Next.jslayout.tsxboundary synchronously seeds the jurisdiction store and aligns server snapshots with the client, completely eliminating pre-hydration fallback swaps (e.g. Frankenstein #0 flashing before the hourly volume) and guaranteeing 0.00 Cumulative Layout Shift. - Interactive Open-Cover Physics: On desktop hover, the hardbound volume smoothly elevates and opens 180Β° on its spine hinge, displaying opening reflections on the Left Page and notable excerpts on the Right Page. Clicking pins the volume open or closed.
- Physical 60β120 FPS Page Turn: Shuffling passages flips a physical 3D leaf across the spine with synchronized ink reveals.
- Synchronized Dynamic SSR & Zero-Flash Pre-Hydration: Edge-stamped geo-cookie (
- Daily Rotating Editorial Classic of the Day & 36 Literary Quotes: Dedicated editorial showcase positioned beneath the catalog grid presenting a unified public domain masterpiece with authentic title, author, publication year, verbatim literary quote, and 1-click reader handoff. Evaluated directly on initial SSR with territorial copyright filtering (e.g. Life+100 Mexico protection) and dynamic anti-collision intelligence that automatically skips candidate books matching the current Hero spotlight to guarantee two unique masterworks on every visit. Supported by an expanded collection of 36 iconic literary passages in "Words That Shaped Humanity" (
LiteraryQuotes.tsx) with safe shuffling and author lifespan governance. - Interactive 3D Book Preview Modal: Clicking or tapping any book card cover launches a 3D hardcover preview modal with fluid FLIP geometry transitions, subpixel return landing, chapter shuffling, and 1-click reader handoff.
- Studio Bookshelf Bookcase & Catalog Spine Isolation: Hardwood shelf alcove with 8 authentic spine binding colorways (Oxblood, Navy, Emerald, Saddle, Plum, Charcoal, Teal, Espresso), convex specular curvature, gilded lettering, and pull-forward hover scaling. Dynamically isolates personal library management controls (custom multi-shelf tabs, "New Shelf", guest sync prompts, and batch offline downloading) strictly to the Bookshelf view (
/bookshelf), ensuring the Catalog spine view remains a distraction-free, pure 3D browsing bookcase with a Zero-CLS Floating Cloud Sync Badge that smoothly overlays real-time sync status. Features Deterministic Zero-Shift Shelf Capacity & Cloud Ordering: Viewport-clamped capacity calculation (calculateShelfCapacity) aligns initial render calculations tomax-w-7xl(1280px) container constraints, eliminating horizontal spine sliding and 29 β 18 book wrapping jumps on page refresh, paired with deterministic secondary PostgreSQL order tie-breakers (.order('book_id', { ascending: true })) in cloud sync queries and session-persistent auto-healing tracking insessionStorage. - Directional Stepped Scroll Navigation: Dynamic scroll detection (
useScrollDirection) smoothly hides the top header on scroll down, docks the catalog filter toolbar totop-0, and instantly reveals navigation on upward scroll gestures. Configurable in Account Settings between Smart Auto-Hide and Always Fixed. - Responsive Filter Drawer & Push-Content Layout: Persistent left-docked drawer on desktop & ultrawide viewports (β₯ 1280px /
xl:) shifting main content to the right (xl:pl-96) for non-blocking catalog browsing; smoothly adapts to a focused slide-out overlay with soft backdrop blur (backdrop-blur-xs) on laptops, vertical monitors, and mobile devicesβguaranteeing 100% unclipped facet typography with zero text truncation. - Tactile Mobile Single-Row Sticky Catalog Toolbar: Compact ~44px mobile toolbar unifying search filter triggers, real-time API health status, view mode toggling (Grid vs. Spine Shelf), and deep-archive pagination in a single horizontal row, maximizing vertical screen real estate for book covers. Features an enhanced tactile numeric page input with auto-selection on tap/focus (
inputMode="numeric"), decoupled blank editing state,aria-pressedsize states, and smooth scrolling to#catalog-sectionon page size change. - Windowed Chunk Sub-Pagination & Predictive Prefetching: Seamlessly reconciles upstream API batching with responsive client layouts by sub-slicing the catalog's native 32-volume batch into viewport-optimized pages (8 books/page on mobile
grid-cols-2, 16 books/page on desktopmd:grid-cols-4). Sub-page turns execute in 0ms directly from client memory without network delay. A widened predictive prefetch buffer triggers background loading on Sub-page 3 (mobile) or Sub-page 1 (desktop), providing a 15β25 second network lead time before reaching batch boundaries. - Explicit Catalog Search Activation & 2-Character Guardrail: Replaced keystroke debouncing with intentional search submission (Enter or clicking "Search") to eliminate redundant API spam against public upstream servers. Enforces a client-side and server-side 2-character minimum guardrail with accessible inline validation (
aria-live="polite"), preventing heavy 1-character full-table scans while fully permitting classical two-character literary titles (It, Oz, Up, Po). - Unified Native Input Architecture & Search Focus Harmonization: Standardized all search bars across Catalog, Bookshelf, Favorites, Bookmarks, Notebooks, and Reader Search Drawer to a native
<input>architecture withrounded-xlcurvature, subtle pre-hover warming (hover:border-primary/40), and a crisp 150ms outward primary ring bloom. The Catalog hero bar integrates floating inset controls (Search button and clearX) directly within the input's padding, delivering authentic native focus without enclosing action buttons inside the glow.
- Unabridged Reading Canvas (
/read/[id]): Full-screen, distraction-free reading with exact chapter and page coordinate auto-resume toasts and 1-click restart option. - Gutenberg Paragraph Reflow Engine: Normalizes legacy 70-character hard linebreaks into fluid prose across Narrow (
576px), Normal (768px), and Wide (1024px) layouts while preserving double-spaced paragraphs, dialogue, and indented poetry. - Granular Typography Popover (
Aa): Real-time font sizing (12pxβ36px) and dynamic line height (1.2β2.6) with 1-click presets (14px / 18px / 24pxand1.4 / 1.8 / 2.2), font family selection (Serif, Sans, Mono), and reading mode toggling (Paginated / Scroll). - Mobile Pinch-to-Zoom Scaling: Two-finger pinch gestures adjust font sizing with a transient HUD size badge.
- Global Sentence-Snapped Virtual Pagination: Virtual page engine with a 500-entry memory LRU cache for instant sub-millisecond virtual page turns without redundant calculation.
- Integrated Reading Drawers:
- Table of Contents (
ReaderTocDrawer): Instant chapter navigation with live start-page badges, read-time estimates, and front-matter anthology story detection. - In-Book Search (
ReaderSearchDrawer): Real-time regex scanner across the unabridged volume with highlighted matches (<mark>), chapter grouping, match counters, and keyboard shortcut invocation (Ctrl+F//). - Language Editions (
ReaderLanguageDrawer): Discovers authentic foreign language Gutenberg editions and translations with 1-click reading handoff.
- Table of Contents (
- Persistent Web Worker Lifecycle: Single long-lived Web Worker (
useGutenbergParserWorker) retained across typography tweaks, eliminating UI thread lag with non-blocking async fallback.
- Catalog & Archive Filtering (12 Primary Languages): Full catalog search and facet filtering across English, French, German, Spanish, Italian, Latin, Ancient & Modern Greek, Portuguese, Dutch, Russian, Chinese, and Romanian via the unified
<LanguageSelector />. - Authentic Project Gutenberg Historical Editions & Translations (
ReaderLanguageDrawer): In-reader discovery of authentic public domain translations and historical language editions indexed from Project Gutenberg catalog relations (FRBR work mapping). Readers can switch seamlessly between authentic translations with zero latency. - Native Browser Translation Guidance: Integrated guidance for Chrome, Edge, Safari, and Firefox built-in translation features for modern on-the-fly multi-language reading without third-party scrapers or ToS violations.
- Synchronized W3C Voice Read-Aloud (Text-to-Speech): Offline-first narration (
window.speechSynthesis) with automatic language-voice pairing, amber visual sentence highlight tracking, speed presets (0.85xβ2.0x), sentence navigation, and OS-level MediaSession lockscreen controls.
- Clean Path URL & Symmetric SSR Hydration Architecture: Canonical routes (
/,/bookshelf,/favorites,/notebook,/bookmarks) powered by Next.js server rewrites, client history synchronization, and symmetricparseFiltersFromUrlquery parsingβguaranteeing identical server-rendered HTML and client hydration on deep paginated URLs (e.g.?page=8) with zero layout shift and 0 CLS. - Bookmarks & Continue Reading Ledger (
/bookmarks): Dedicated reading ledger tracking active volumes with tactile bookmark cards, ribbon accents, live progress percentages, last-read coordinates, status filters (All, In Progress, Completed, On Hold), and 1-click chapter resume.- Authentic Reading Telemetry: Strictly enrolls volumes with active coordinates or progress, eliminating unopened placeholder clutter.
- Two-Way Dynamic Hydration: Resolves un-shelved book identities via TanStack React Query and automatically pre-seeds warm reader state for instant 0ms transitions.
- Completed Reading Progress Latch & "Read Again" Flow: Resuming a finished volume safely locks 100% progress and the "Completed" badge without regressions. Completed bookmark cards feature a dedicated "Read Again" action allowing readers to restart reading from Page 1 without destroying historical ledger completion achievements.
- In-Reader Highlighting & Literary Commonplace Notebook (
/notebook):- 4 editorial pastel highlighters (Canary Yellow, Vintage Amber, Calm Mint, Soft Rose) with coarse-pointer touch dismissal and chapter-scoped annotation drawer.
- Comprehensive reading journal organizing highlighted excerpts, personal reflections, pastel color filters, full-text search, volume grouping, and 1-click academic citation copying.
- Native IndexedDB Offline Book Storage: Zero-dependency browser storage bypassing the 5MB
localStoragelimit, enabling readers to download entire books for offline reading in airplane mode. Downloading a volume automatically links it to the user's personal bookshelf. - Authoritative Cloud State Reconciliation (
lastBookshelfSyncAt): Optional Supabase PostgreSQL cloud sync with Row Level Security (RLS). Initial sync migrates local guest books to the cloud; subsequent syncs treat Supabase as the authoritative source of truth, gracefully pruning titles deleted on another device while pre-sync outbox flushing (flushOutbox) safeguards offline additions. - High-Performance Database Query Planner Optimization: Implemented
{ count: 'estimated' }planner statistics insrc/lib/catalog/supabase-provider.tsacross 78,000+ catalog rows, completely eliminating PostgreSQL57014statement timeouts and slashing query latency from>3,000msdown to~275ms. - Sanitized Sign-Out & Account Isolation: Pre-logout outbox drain and clean state wipe (
clearBookshelf()) prevent cross-account contamination while raw downloaded texts in IndexedDB are preserved on device. - Bi-Directional Cloud Reading Progress: 2000ms debounced upsert to
public.reading_progress, restoring chapter and scroll coordinates across devices for authenticated accounts while remaining 0ms/zero-network for guest readers. - Reading Streaks, Dual Immersion Telemetry & Annual Reading Challenges (
/account): Offline-first literary activity tracking calculating consecutive daily streaks with a 5-minute active immersion threshold (300s), longest streaks, 7-day calendar activity indicators, and total literary immersion duration. Disentangles telemetry into distinct Reading Time (visual focus with 2-minute idle guard) and Listening Time (uninterrupted Text-to-Speech audio narration retaining time in background tabs). Includes an interactive annual reading challenge progress bar with user-adjustable volume targets, real-time pace tracking, dynamic countdown prompts (Xm / 5m logged today), and multi-device Supabase cloud synchronization with Last-Write-Wins (LWW) conflict resolution. - Full Data Sovereignty & Portability: Single-click RFC 4180 CSV export and portable JSON backup (
src/lib/library-backup.ts) with defensive schema validation and merge/replace restore strategies. - Zero-Tracking Privacy Architecture (
/privacy): Zero third-party trackers, zero advertising beacons, cookie-less operation (Art. 5(3) exempt), privacy-first anonymous aggregate telemetry (Vercel Web Analytics & Speed Insights), and self-service account data deletion in User Settings (/account). - Technical SEO, Social OpenGraph & Upstream Rate-Shielding: Native Next.js 16 crawl directives (
robots.ts) explicitly disallow search query parameters (?search=*,?topic=*) to protect public upstream catalog servers from bot query exhaustion. Dynamic server layouts (/read/[id]/layout.tsx) resolve book identities directly from self-hosted Supabase with an in-memory cache and 24-hour Next.js edge caching (revalidate: 86400) to generate rich OpenGraph and Twitter cards (summary_large_image) featuring authentic book covers, while injecting safe Schema.orgBook,WebSite, andWebApplication(isAccessibleForFree: true) JSON-LD structured data.
-
Autonomous Multi-Jurisdiction Engine (
src/lib/copyright-engine.ts): Decoupled, zero-dependency validation engine enforcing exact public domain thresholds based on the user's geographic jurisdiction (year 2026 cutoff calculations):-
United States (17 U.S.C. Β§ 304): Published on or before 1930 or cleared by Project Gutenberg US (
copyright === false). -
Life + 70 (EU 27, UK, Canada, Australia, New Zealand, Japan): Author and translator death year
$\le 1955$ ($2026 - 71$ ). -
Life + 100 (Mexico, CΓ΄te d'Ivoire): Author and translator death year
$\le 1925$ ($2026 - 101$ ). -
Life + 80 (Colombia, Spain pre-1987 deaths): Author and translator death year
$\le 1945$ ($2026 - 81$ ).
-
United States (17 U.S.C. Β§ 304): Published on or before 1930 or cleared by Project Gutenberg US (
-
Declarative Copyright Subsystem Encapsulation (
useBookCopyright.ts&CopyrightNoticeBanner.tsx): Unified copyright logic behind a single declarative facade hook (useBookCopyright) and a standardized presentation banner (CopyrightNoticeBanner), decoupling legal lifespan calculations from UI layouts and eliminating duplicated evaluation across 8 presentation components. -
Joint Authorship & Derivative Protection: Calculates protection from the death of the last surviving co-author (Berne Convention Art. 7bis) and independently validates translator derivative works (Berne Convention Art. 2(3)). Includes
partitionBooksByJurisdictionfor cleanly separating legal collections. -
Fail-Closed Longevity Heuristics: Applies a strict human longevity upper bound (
$birth_year \le currentYear - term - 101$ ) for missing death dates, and strictly fails closed outside the US when author lifespans cannot be verified. -
Next.js 16 Root Proxy Geo-Context & Dynamic SSR Seeding (
src/proxy.ts,src/app/layout.tsx): Automatically resolves the visitor's ISO 3166-1 alpha-2 country code via edge headers (x-vercel-ip-country,cf-ipcountry), stamps a non-trackingbookarium-geo-countrycookie, supports regional development overrides (?country=XX), and synchronously seeds the jurisdiction store during server-side rendering for instant zero-flash hydration. -
HTTP 451 Streaming Gatekeeper (
/api/books/content): Evaluates incoming text streaming requests against a 24h LRU metadata cache (src/app/api/books/content/metadata-cache.ts). If protected under the visitor's local law, the server returns anHTTP 451: Unavailable For Legal Reasonsresponse detailing the restricting author, local statute, and projected public domain entry date. -
Hyperlink Neutralization & Presentation Isolation:
-
Download Drawer (
DownloadDrawer.tsx): Direct download links are completely omitted from the DOM when restricted, satisfying European Court of Justice (GS Media) and UK hyperlink communication case law, replaced with a prominent legal restriction banner (CopyrightNoticeBanner). -
Book Cards (
BookCard.tsx): Displays an amber"Protected ([Country])"badge and disables the reading action as"Restricted". -
Dedicated Reader Legal View (
ReaderErrorView.tsx): Renders an archival shield view with full statutory rationale and a 1-click"Return to Library"action.
-
Download Drawer (
-
Edge CDN Cache Partitioning: Both
/api/booksand/api/books/contentroutes stampVary: x-vercel-ip-country, Accept-Encodingto guarantee zero regional cache poisoning across global CDN edge nodes. -
Confidential Notice & Takedown Intake Channel (
/copyright): When configured viaNEXT_PUBLIC_LEGAL_CONTACT_FORM, activates an official private intake portal (such as Google Forms or Tally) for authors, translators, and literary estates to submit copyright notices, DMCA inquiries, or territorial verification requests confidentially without requiring a developer GitHub account. Gracefully falls back to GitHub Issues if unconfigured.
flowchart TD
User["π€ Reader / Literature Enthusiast"]
subgraph FrontendSPA ["Client SPA Layer (Next.js 16 App Router)"]
Nav["Navbar.tsx\n(Brand Reset, View Switcher, Theme Cycler)"]
Hero["HeroSearch.tsx\n(Dynamic 3D Rotating Spotlight & Search)"]
Hero3D["HeroFeaturedBook3D.tsx\n(3D Open-Cover Hinge & Leaf-Flip Engine)"]
Toolbar["StickyCatalogToolbar.tsx\n(0px Flush Header, Filters Toggle, Tactile Numeric Jump)"]
FilterDrawer["AdvancedFilterDrawer.tsx\n(Left Push-Sidebar: Eras, Sort, Formats)"]
EditorialQuote["EditorialQuoteSection.tsx\n(Classic of the Day & Collision Guard)"]
LiteraryQuotes["LiteraryQuotes.tsx\n(Words That Shaped Humanity & Safe Shuffling)"]
CopyrightBanner["CopyrightNoticeBanner.tsx\n(Declarative Territorial Restriction & Public Domain Notice)"]
subgraph Views ["Primary Application Views (/ & Edge Rewrites)"]
Grid["Catalog View (/)\n(Editorial Card Grid & 3D Hardwood Shelf)"]
ShelfView["Bookshelf View (/bookshelf)\n(Curated Library & Custom Named Shelves)"]
FavView["Favorites View (/favorites)\n(Personal Masterworks Collection)"]
MarksView["Bookmarks View (/bookmarks)\n(Tactile Reading Ledger & Telemetry)"]
NoteView["Commonplace Notebook (/notebook)\n(Highlights, Reflections & Tags)"]
AccView["Account Hub (/account)\n(Library Stats, Cloud Sync & JSON Backup)"]
HabitsCard["AccountHabitsCard.tsx\n(Reading Streaks, Daily Progress, Annual Challenge)"]
AccoladesCard["AccountAccoladesCard.tsx\n(Literary Honors, Showcase & Ex-Libris Bookplates)"]
ReaderPage["Focus Reader Page (/read/[id])\n(Continuous Pagination, Subtitles, AST)"]
end
subgraph ReaderDrawers ["Portaled Mutual-Exclusion Dialogs (z-10000)"]
TocDrawer["ReaderTocDrawer\n(Rich Subtitles & Page Numbers)"]
SearchDrawer["ReaderSearchDrawer\n(In-Volume Live Text Search)"]
ControlsDrawer["ReaderControls\n(Typography, Speech & Themes)"]
LangDrawer["ReaderLanguageDrawer\n(International Editions Handoff)"]
DownDrawer["DownloadDrawer\n(EPUB, MOBI, TXT Direct Streams)"]
end
subgraph StateStores ["Zustand Persistent State & Offline Engine"]
StoreShelf[("β‘ useBookshelfStore\n(saved, likes, queue, history, shelves)")]
StoreReader[("π useReaderStore\n(typography, progress map, coordinates)")]
StoreTheme[("π¨ useThemeStore\n(day, sepia, obsidian)")]
StoreAuth[("π useAuthStore\n(session, cloud migration, profile)")]
StorePref[("βοΈ usePreferencesStore\n(sticky scroll, layout choices)")]
StoreAnnot[("ποΈ useAnnotationStore\n(pastel highlights, notes, tags)")]
StoreHabits[("π₯ useHabitsStore\n(streak, 5m threshold, dual immersion, cloud)")]
StoreAccolades[("ποΈ useAccoladesStore\n(accolades, showcase pinning, celebrations, cloud)")]
StoreJurisdiction[("π useJurisdictionStore\n(country, rule, dev override, cookie sync)")]
StoreOffline[("π¦ IndexedDB Engine\n(unabridged offline volume cache)")]
end
subgraph ReaderEngine ["Reader Runtime & Web Speech Subsystem"]
SpeechHook["π useReaderSpeech\n(SpeechSynthesis, Boundary Sync, Auto-Flip)"]
TimerHook["β±οΈ useReadingTimer\n(Dual Immersion: 2-min Idle Guard + TTS Audio Bypass)"]
WorkerHook["βοΈ useGutenbergParserWorker\n(Persistent Worker Chapter AST)"]
LedgerHook["π useContinueReadingLedger\n(Two-Way Hydration & 0ms Resume)"]
AnnotatorEngine["ποΈ reader-annotator.ts\n(Computational Interval Partitioning & Highlighter)"]
end
HookCopyright["βοΈ useBookCopyright\n(Declarative Facade: Rules, Lifespans & Status)"]
HookAutoHeal["π©Ί useCollectionAutoHeal\n(Author Lifespan Scanning & Auto-Rehydration)"]
QueryBooks["π useBooks & usePrefetchNextPage\n(Windowed Sub-Pages & Predictive Prefetch)"]
QueryContent["π useBookContent(url, bookId)\n(IndexedDB Check to CDN Stream)"]
QueryTranslate["π useBookTranslations\n(International Editions Aggregation)"]
Telemetry["π Vercel Telemetry\n(Analytics & Speed Insights)"]
end
subgraph ServerLayer ["Next.js Root Proxy & Edge Routing Layer"]
RootProxy["Next.js 16 Root Proxy (src/proxy.ts)\n(Edge Geo-IP: x-vercel-ip-country, Dev ?country=XX, Cookie Stamping)"]
ProxyBooks["GET /api/books\n(SWR 120s Cache, Latency Tracking, Rate Limit, Seam Controller)"]
CatalogSeam["Catalog Seam & Dual Providers (src/lib/catalog/)\n(supabase-provider.ts β’ gutendex-provider.ts)"]
ProxyContent["GET /api/books/content\n(Tier 1 Supabase DB β’ Tier 2 Gutenberg Multi-Mirror, Anti-SSRF)"]
ProxyBookTranslations["GET /api/books/translations\n(Edge SWR Cache, Zero False Positives, FRBR Work Mapping)"]
LayoutServer["Server Layout (/read/[id])\n(React.cache, ISR 24h, OpenGraph, JSON-LD)"]
end
subgraph LegalLayer ["Jurisdictional Copyright Engine (src/lib/copyright-engine.ts)"]
EngineCore["isBookPublicDomainInJurisdiction\n(US 1930 Cutoff, Life+70, Life+100, Life+80)"]
JointAuthors["Joint Authorship Guard (Berne Art. 7bis)"]
Translators["Translator Protection (Berne Art. 2(3))"]
ContributorFilter["Contributor Role Filter\n(Illustrator/Artist Non-Blocking Exclusion)"]
CountryResolver["Country Resolver (src/lib/country-resolver.ts)\n(Edge Geo-IP, Cookie Sync, Timezone Inference)"]
MetaCache["Metadata Lifespan Cache\n(metadata-cache.ts β’ 24h LRU)"]
end
subgraph UpstreamServices ["100% Public Domain & Cloud Infrastructure"]
Gutendex["π Gutendex Search API\n(Upstream Search Fallback)"]
GutenbergCDN["π Project Gutenberg Mirrors\n(aleph.gutenberg.org, gutenberg.readingroo.ms, www.gutenberg.org)"]
SupabaseCloud[("β‘ Supabase Cloud (PostgreSQL)\n(public.books catalog, profiles, shelves, progress, habits, accolades)")]
SyncEngine["π Gutenberg Catalog Sync Engine\n(scripts/sync-gutenberg-catalog.js β’ .github/workflows/catalog-sync.yml)"]
VercelEdge["β‘ Vercel Edge Platform\n(Cookie-less Analytics & Speed Insights)"]
end
User --> RootProxy
RootProxy --> Nav
RootProxy --> Hero
Hero --> Hero3D
RootProxy --> Toolbar
Toolbar --> FilterDrawer
Toolbar --> Grid
Grid --> CopyrightBanner
Grid --> HookCopyright
Grid --> EditorialQuote
Grid --> LiteraryQuotes
Nav --> Views
FavView --> HookAutoHeal
ShelfView --> HookAutoHeal
HookCopyright --> EngineCore
AccView --> HabitsCard
AccView --> AccoladesCard
Grid --> QueryBooks
QueryBooks --> ProxyBooks
ProxyBooks --> CatalogSeam
CatalogSeam --> EngineCore
CatalogSeam -->|"Primary: Estimated-Count Fast Scan / <50ms Single-Book"| SupabaseCloud
CatalogSeam -.->|Fallback on unseeded/offline| Gutendex
SyncEngine -->|Weekly Cron pg_catalog.csv.gz Stream| SupabaseCloud
QueryBooks -.->|Client Failover on 504| Gutendex
ReaderPage --> QueryContent
ReaderPage --> ReaderDrawers
ReaderPage --> ReaderEngine
ReaderPage --> TimerHook
ReaderPage --> AnnotatorEngine
AnnotatorEngine --> StoreAnnot
QueryContent --> ProxyContent
ProxyContent --> MetaCache
MetaCache -->|1. Supabase public.books check| SupabaseCloud
MetaCache -.->|2. Fallback to Gutendex| Gutendex
MetaCache --> EngineCore
EngineCore --> JointAuthors
EngineCore --> Translators
ProxyContent -->|Tier 1: Instant DB Text| SupabaseCloud
ProxyContent -->|Tier 2: Multi-Mirror Fallback| GutenbergCDN
ReaderPage --> QueryTranslate
QueryTranslate --> ProxyBookTranslations
ProxyBookTranslations --> SupabaseCloud
Views --> StateStores
HabitsCard --> StoreHabits
AccoladesCard --> StoreAccolades
TimerHook --> StoreHabits
ReaderEngine --> StateStores
StoreShelf -->|Cloud Sync via RLS| SupabaseCloud
StoreReader -->|Progress Sync| SupabaseCloud
StoreAuth -->|Session Auth| SupabaseCloud
StoreHabits -->|Habits Sync via RLS| SupabaseCloud
StoreAccolades -->|Accolades Sync via RLS| SupabaseCloud
Telemetry -.->|Anonymous Metrics| VercelEdge
flowchart LR
subgraph ReaderState ["Zustand Reader Store (useReaderStore)"]
ActiveBook["Active Book Metadata"]
FontSize["Font Size: 12px - 36px"]
FontFamily["Font Family: Serif | Sans | Mono"]
LineHeight["Line Height: 1.2 - 2.6"]
ColumnWidth["Column Width: Narrow (576px) | Normal (768px) | Wide (1024px)"]
ReadingMode["Reading Mode: Paginated | Scroll"]
Theme["Theme: Light | Dark | Sepia"]
Progress["Global Page & Book Progress %"]
Positions["Reading Positions Map\n(exact chapter & page restore)"]
end
subgraph ParsingEngine ["Gutenberg Typography & Segmentation AST"]
RawText["Raw Plain Text Stream"]
WorkerPool["Persistent Web Worker Thread\n(useGutenbergParserWorker)\nβ’ Kept alive across font/spacing tweaks\nβ’ Chunked async main-thread fallback"]
Reflow["reflowGutenbergParagraphs\n(Normalizes 70-col hard wraps)"]
TOCFilter["Front-Matter TOC Suppressor"]
Segmentation["Chapter Section Segmentation"]
VirtualPages["Virtual Continuous Page Spread (5600 chars/pg)"]
RawText --> WorkerPool
WorkerPool --> Reflow
Reflow --> TOCFilter
TOCFilter --> Segmentation
Segmentation --> VirtualPages
end
subgraph ReaderView ["Dedicated Focus Reader (src/app/read/[id]/page.tsx)"]
Toolbar["Top Editorial Reader Bar & Sliding Tray (ReaderHeader)"]
SubHeader["Sub-Header Status Ribbon (ReaderSubHeaderRibbon)"]
ContentArea["Book Page Rendering Area (Fluid Paragraph Wrap & Amber Sentence Highlight)"]
ProgressBar["Top Reading Progress Indicator"]
ResumeToast["Exact-Page Auto-Resume Toast"]
FooterBar["Sticky Bottom Pagination & Page Jump"]
TOC["Table of Contents Drawer (ReaderTocDrawer)"]
SearchDrawer["In-Book Search Drawer (ReaderSearchDrawer)"]
LangDrawer["Language Editions Drawer (ReaderLanguageDrawer)"]
Controls["Appearance & Typography Popover (ReaderControls)"]
AudioBar["Speech Narration Bar (ReaderAudioToolbar)\n(useReaderSpeech β’ SpeechSynthesis β’ 0.85x-2.0x)"]
TransBar["Bilingual Translation Bar (ReaderTranslationBar)\n(useBookTranslation β’ 40+ Languages)"]
AnnotDrawer["Annotations Drawer (ReaderAnnotationDrawer)\n(4 Pastel Highlighters β’ Canary, Amber, Mint, Rose)"]
InfoModal["Archival Metadata Modal (GutenbergInfoModal)"]
end
subgraph Persistence ["Browser LocalStorage, IndexedDB & Supabase Cloud"]
LSPrefs[("bookarium-reader-preferences\n(theme, font, spacing, readingProgress, readingPositions)")]
LSAnnot[("bookarium-annotations-storage\n(useAnnotationStore highlights & reflections)")]
IDBStorage[("IndexedDB (useOfflineBooks)\n(unabridged offline volumes)")]
CloudProgress[("β‘ Supabase Cloud\npublic.reading_progress\n(2s Debounced Sync & Restore)")]
end
Toolbar -->|"Adjust Size / Family / Width / Mode / Theme"| ReaderState
VirtualPages --> ReaderView
ReaderState --> ContentArea
ReaderState --> ProgressBar
ReaderState --> ResumeToast
FooterBar -->|"Page Flip / Jump"| ReaderState
TOC -->|"Select Chapter (p. X)"| ReaderState
SearchDrawer -->|"Jump to Match (p. X)"| ReaderState
LangDrawer -->|"Switch Translation"| ReaderState
Controls -->|"Tweak Settings"| ReaderState
AudioBar -->|"Sentence Highlight Sync"| ContentArea
TransBar -->|"Parallel Bilingual Text"| ContentArea
AnnotDrawer -->|"Render Highlights"| ContentArea
AnnotDrawer <--> LSAnnot
ReaderView <--> IDBStorage
ReaderState <--> LSPrefs
ReaderState <-->|"Authenticated"| CloudProgress
flowchart TD
subgraph Storage ["Persistent State Stores"]
RS["π useReaderStore\nβ’ readingPositions (exact coordinates & timestamp)\nβ’ readingProgress (0-100%)\nβ’ openReader(book) [warm cache]"]
BS["β‘ useBookshelfStore\nβ’ savedBooks []\nβ’ recentBooks [] (cached identity)\nβ’ bookStatuses {} ('currently_reading', etc.)"]
IDB["π¦ IndexedDB (useOfflineBooks)\nβ’ cached offline book bundles"]
end
subgraph LedgerHook ["useContinueReadingLedger Hook"]
FilterActive["Active Telemetry Filter\n(readingPositions exists OR readingProgress > 0)\nβ οΈ Excludes un-opened shelved books"]
MissingCheck{"Missing Cached\nIdentity?"}
QueryMissing["π useBooks(ids: missingIds)\n(TanStack Query - Catalog Seam)"]
EnrichDict["Enriched Book Dictionary\n(savedBooks + recentBooks + queryResults)"]
Parser["Canonical Utilities (@/lib/utils)\nβ’ formatAuthorNames (reverse 'Last, First' & strip dates)\nβ’ cleanBookTitle (strip Gutenberg prefixes)\nβ’ formatRelativeTime ('Recently', '2h ago')"]
Assembly["Assemble ActiveReadingVolume[]\nβ’ progress, chapter, coordinates, lastReadAt\nβ’ status (in_progress / completed / on_hold)\nβ’ isOffline badge"]
FilterSort["Client Search & Status Filter\nβ’ 'all' | 'in_progress' | 'completed' | 'on_hold'\nβ’ CollectionSearchBar token matching\nβ’ Recency sorting (lastReadAt desc)"]
end
subgraph UI ["Presentation Layer (BookmarksView.tsx)"]
Header["SectionHeader ('Continue Reading & Bookmarks')\nβ’ Eyebrow, Flank lines, Clear Bookmarks modal"]
Search["CollectionSearchBar (real-time filtering)"]
Tabs["Filter Tabs (All, In Progress, Completed, On Hold)"]
Cards["BookmarkCard.tsx\nβ’ Tactile ribbon accent\nβ’ Interactive cover thumbnail\nβ’ Cleaned title & normalized author\nβ’ Reading coordinates badge\nβ’ Offline pill badge\nβ’ Status dropdown selector"]
ResumeAction["1-Click Resume / Cover Tap\nβ’ Seed useReaderStore.openReader(book) [Warm Cache]\nβ’ router.push('/read/' + id)"]
end
RS --> FilterActive
FilterActive --> MissingCheck
BS --> MissingCheck
MissingCheck -->|"Yes (e.g. un-shelved #55179)"| QueryMissing
QueryMissing --> EnrichDict
MissingCheck -->|"No"| EnrichDict
BS --> EnrichDict
EnrichDict --> Parser
Parser --> Assembly
IDB --> Assembly
Assembly --> FilterSort
FilterSort --> Cards
Header --> UI
Search --> FilterSort
Tabs --> FilterSort
Cards --> ResumeAction
ResumeAction -->|"Warm Reader Transition (0 CLS)"| RS
- Node.js:
>= 20.0.0(Node 22 LTS recommended) - npm:
>= 10.0.0
# 1. Clone the repository and install dependencies
npm install
# 2. Start local development server (automatically launches browser)
npm run dev:open
# 3. Or launch full development environment with background test watcher
npm run dev:allThe application will be accessible at http://localhost:3000. (Bookarium operates seamlessly in 100% offline-first mode using browser storage with zero environment setup required).
Bookarium strictly enforces territorial copyright compliance in accordance with international public domain statutes:
-
In Production (Vercel): Automatically inspects the client's network connection via
x-vercel-ip-country(tamper-proof edge IP header). -
In Local Development (
localhost:3000): Automatically infers your country via your machine's System Timezone (e.g.Europe/Bucharest$\rightarrow$ RO/ Life+70), displaying the authentic regional catalog out-of-the-box (55,182 volumes in the EU vs. 78,500 in the U.S.). -
Testing Other Jurisdictions Locally:
- Append
?country=XXto the URL (e.g.http://localhost:3000/?country=USorhttp://localhost:3000/?country=MX). - Or define
DEV_COUNTRY=XXin.env.localto permanently anchor your local environment to any ISO 3166-1 country code.
- Append
Bookarium uses Supabase PostgreSQL for optional cloud authentication, cross-device bookshelf & favorites synchronization, and reading progress tracking. Follow these steps to provision your database in under 2 minutes:
- Go to supabase.com and create a new project.
- Note your Project URL and anon public API Key from Project Settings
$\to$ API. - Create a
.env.localfile in the project root:
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key- In your Supabase Dashboard, open the SQL Editor from the left sidebar.
- Click New Query, copy and paste the contents of
supabase/schema.sql, and click Run. - The script is 100% idempotent and safely provisions all database tables, Row Level Security (RLS) policies, indexes, and triggers:
| Database Object | Type | Purpose & Security Governance |
|---|---|---|
public.profiles |
Table (RLS) | User display name, unique @username handle, scholar bio, opt-in public switch, saved books and custom shelf visibility toggles (show_saved_books, show_custom_shelves), and telemetry visibility with zero-PII public RLS reads (is_public = true) and authenticated-only mutations with WITH CHECK integrity. |
public.bookshelves |
Table (RLS) | Master default 'General' shelf and custom user-created collection shelves with granular public/private privacy enforcement (is_public = true) and authenticated-only mutations with WITH CHECK integrity. |
public.bookshelf_items |
Table (RLS) | Volumes filed in specific bookshelves with uniqueness constraints, parent bookshelf ownership verification on insert/update/delete, public shelf isolation, and cascade-optimized foreign key index on user_id. |
public.user_favorites |
Table (RLS) | Cross-device synchronized favorited titles with authenticated-only user isolation. |
public.reading_progress |
Table (RLS) | Chapter coordinates, progress %, scroll offset, and cached volume metadata with authenticated-only WITH CHECK integrity. |
public.user_annotations |
Table (RLS) | Passage highlights (yellow, amber, mint, rose) and personal scholarly notes. |
public.user_book_curation |
Table (RLS) | Personal 1β5 star ratings and reading status classification. |
public.user_reading_habits |
Table (RLS) | Reading streaks, daily session dates, annual goal targets, and dual immersion duration (reading & listening). |
public.user_accolades |
Table (RLS) | Unlocked literary accolades, timestamps, showcase pinning, and personal bookplate metadata. |
public.books |
Table (RLS) | High-performance self-hosted public domain catalog with GIN full-text search (search_vector), indexed languages, subjects, download metrics, pre-computed author lifespan bounds (max_author_death_year, min_author_birth_year) for sub-50ms single-book copyright resolution and ~1β2s catalog searches, optional full plain-text caching (content) for instant reader streaming, and public read RLS (FOR SELECT USING (true)). |
public.book_translations |
Table (RLS) | Relational routing junction table linking Project Gutenberg volumes to canonical literary works and multi-language translations (FRBR model). Microscopic footprint (< 2.5 MB for 75,000 books), zero text duplication, foreign key cascading on book deletion, and public read RLS (FOR SELECT USING (true)). |
public.handle_new_user() |
Trigger | Automatically provisions profile and default General shelf on auth creation (RPC execution revoked from PUBLIC, anon, authenticated, immutable search_path). |
public.delete_current_user() |
RPC Function | Cascade user data erasure and complete self-service account deletion (authenticated-only execution, null session guard, immutable search_path). |
public.books_search_vector_trigger() |
Trigger | Automatically maintains search_vector on book insert/update (RPC execution revoked from PUBLIC, anon, authenticated, immutable search_path). |
To activate the self-hosted PostgreSQL book catalog and bypass third-party rate limits, you have three options:
Stream Project Gutenberg's complete official catalog dump directly into Supabase without copy-pasting SQL:
# 1. Quick test run (first 100 books, ~2 seconds):
npm run catalog:sync -- --limit=100
# 2. Full autonomous catalog population (78,000+ titles in ~2 minutes):
npm run catalog:syncTip
Hands-Free Weekly Sync & GitHub Actions Automation: Add NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY to your repository's GitHub Secrets (Settings -> Secrets and variables -> Actions). Two scheduled GitHub Actions workflows automate background catalog and translation updates while keeping your Supabase free tier active:
- Gutenberg Catalog Sync (
.github/workflows/catalog-sync.yml):- Schedule: Every Sunday at
02:00 UTC. - Action: Streams newly added Gutenberg titles and batch-upserts metadata into
public.books, then automatically chains relational translation clustering intopublic.book_translations. - Manual Dispatch: Can be triggered on-demand with custom inputs (
limit,update_existing,dry_run) directly from the GitHub Actions tab.
- Schedule: Every Sunday at
- Gutenberg Translations Sync (
.github/workflows/translations-sync.yml):- Schedule: Every Sunday at
03:00 UTC(1 hour after catalog sync). - Action: Dedicated standalone workflow that clusters Wikidata translation statements into canonical literary works without re-streaming the full 78,000-book catalog.
- Manual Dispatch: Can be triggered on-demand with custom inputs (
limit,update_existing,dry_run) directly from the GitHub Actions tab.
- Schedule: Every Sunday at
If you prefer a quick starter seed for local development:
# Generate curated SQL seed file with 10 masterworks
npm run catalog:ingest -- --curated --dry-runPaste and run supabase/seed_books.sql in your Supabase SQL Editor.
Populate verified relational book translations linking historical editions across languages:
# 1. Dry run / clustering validation (no database writes):
npm run translations:sync -- --dry-run
# 2. Quick test run (first 200 Wikidata translation clusters):
npm run translations:sync -- --limit=200
# 3. Full live translation clustering & Supabase upsert:
npm run translations:sync -- --all
# 4. Generate atomic offline SQL seed file (optional):
npm run translations:sync -- --limit=200 --output=supabase/seed_translations.sqlPaste and run supabase/seed_translations.sql in your Supabase SQL Editor if seeding offline.
Once seeded, /api/books automatically routes queries to your self-hosted Supabase PostgreSQL catalog with predictable ~1β2s catalog page responses and sub-50ms single-book lookups, eliminating the 20β60s wait times and timeouts common on public APIs.
- In your Supabase Dashboard, navigate to Authentication
$\to$ URL Configuration. - Set Site URL to:
-
http://localhost:3000(for local development) orhttps://your-app.vercel.app(for production)
-
- Under Redirect URLs, add the following allowed callback endpoints:
http://localhost:3000/auth/callbackhttp://localhost:3000/auth/confirm-deletionhttp://localhost:3000/accounthttps://your-app.vercel.app/auth/callbackhttps://your-app.vercel.app/auth/confirm-deletionhttps://your-app.vercel.app/account
Bookarium is architected for zero-config deployment on Vercel:
- Push your repository branch to GitHub.
- Import the project into the Vercel Dashboard.
- Under Environment Variables, optionally set:
NEXT_PUBLIC_SUPABASE_URL= your Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY= your Supabase public anon key
- Click Deploy β Vercel will automatically build the Next.js 16 production bundle, configure edge caching, and provision serverless API proxies.
Bookarium implements a defense-in-depth security model across the edge, serverless runtime, and client layers:
| Security Vector | Implementation & File Path | Protection Mechanism |
|---|---|---|
| Sliding-Window Rate Limiting |
src/lib/rate-limiter.ts & src/lib/api-utils.ts
|
Zero-dependency in-memory sliding-window rate limiter protecting upstream Project Gutenberg APIs (60 req/min on /api/books, 30 req/min on /api/books/content) with automatic 30s garbage collection, anti-spoofing IP resolution (prioritizing edge platform headers and rightmost hop extraction), and 429 Too Many Requests status with Retry-After. |
| Dual-Provider Failover & Cloud Outage Immunity |
src/lib/catalog/ & src/stores/useBookshelfStore.ts
|
Automatic Strangler Fig failover transparently degrading /api/books and /api/books/content from primary Supabase PostgreSQL to the upstream Gutendex REST API and secondary Gutenberg mirrors (aleph.gutenberg.org, gutenberg.readingroo.ms) upon database latency or cloud outages. Reading positions, bookmarks, audio telemetry, and downloaded texts remain 100% functional offline via IndexedDB and local Zustand storage, with non-blocking post-outage reconciliation (flushOutbox). |
| HTTP Security Headers | next.config.ts |
Enforces Content-Security-Policy (default-src 'self', frame-ancestors 'none'), Cross-Origin-Opener-Policy (same-origin), HSTS (max-age=63072000; includeSubDomains; preload), Clickjacking defense (X-Frame-Options: SAMEORIGIN), MIME-type sniffing prevention (X-Content-Type-Options: nosniff), Referrer Policy (strict-origin-when-cross-origin), and Permissions Policy (camera=(), microphone=(), geolocation=()). |
| SSRF & Upstream Stream Bounding |
src/app/api/books/content/route.ts & src/app/api/books/content/url-validator.ts
|
Upstream URL whitelisting (isSafeUpstreamUrl) restricting fetches strictly to official Project Gutenberg domains (gutenberg.org, www.gutenberg.org), strict numeric ID regex verification (^\d{1,8}$), redirect: 'manual' preventing open redirect hops, and a 15MB payload streaming threshold preventing memory exhaustion DoS. |
| Open Redirect Defense | src/app/auth/callback/route.ts |
Path sanitization (sanitizeRedirectPath) guaranteeing OAuth and magic-link redirect paths strictly originate from trusted relative roots (/^\/[^\/\\]/) preventing off-site phishing redirects. |
| Next.js Edge Session Proxy |
src/proxy.ts & src/lib/supabase/middleware.ts
|
Lightweight edge proxy invoking @supabase/ssr updateSession to seamlessly refresh auth tokens and cookies across route transitions with non-blocking fallback handling. |
| ReDoS & Main Thread Protection | src/lib/gutenberg-parser.ts |
Non-backtracking regular expressions ([^\n]{0,80}) and bounded passage analysis window (capped at 120,000 characters) eliminating regular expression denial of service (ReDoS) and event loop freezing on massive multi-megabyte classical tomes. |
| LRU Pagination Memory Cache | src/lib/gutenberg-parser.ts |
500-entry memory cache (Map<string, string[]>) for paginated chapter views, delivering instant sub-millisecond virtual page turns with zero redundant recalculation. |
| Relational Data Purge & Account Deletion | src/stores/useAuthStore.ts |
Comprehensive cascading cleanup across PostgreSQL tables (reading_progress, bookshelf_items, bookshelves, profiles) with fallback RPC delete_current_user execution and session revocation. |
| Anti-Enumeration Scholar Sanctuaries |
src/components/profile/PrivateProfileNotice.tsx & src/app/u/[username]/page.tsx
|
Strict opt-in privacy default (is_public = false), unified "Scholar Sanctuary Not Found" state preventing user enumeration across private and non-existent profiles, and zero-PII exposure ensuring emails and auth credentials are never queried or rendered. |
| Datacenter Proximity & Edge Optimization | vercel.json |
Pins serverless execution to iad1 (Washington D.C. / US-East) directly adjacent to Gutenberg/Gutendex nodes with dedicated memory and payload compression (gzip, deflate, br). |
| Jurisdictional Copyright & Geo-IP Resolution |
src/lib/country-resolver.ts & src/lib/copyright-engine.ts
|
Strict territorial copyright compliance enforcing U.S. 17 U.S.C. Β§ 304, Life+70 (EU/UK/CA/AU), Life+80 (CO/ES), and Life+100 (MX) rules with fail-closed author longevity heuristics. In production, Vercel edge IP headers (x-vercel-ip-country) strictly gate catalog filtering and return HTTP 451 Unavailable For Legal Reasons for protected text streams. In local development, automatically infers developer's physical country via System Timezone (Europe/Bucharest RO / Life+70) with optional .env.local (DEV_COUNTRY=XX) and browser query override (?country=XX) support. |
| Command | Action / Description |
|---|---|
npm run dev |
Starts Next.js development server at http://localhost:3000 |
npm run dev:open |
Starts dev server and opens your default browser concurrently |
npm run dev:all |
Starts dev server, Vitest test watcher, and browser concurrently |
npm run verify |
Runs the full 7-Gateway Quality Engine before commits |
npm test |
Runs the full Vitest suite with V8 code coverage report |
npm run test:fast |
Runs Vitest test suites without coverage calculation for rapid developer validation |
npm run test:ui |
Launches Vitest interactive visual testing UI |
npm run test:watch |
Runs Vitest in reactive watch mode for TDD |
npm run typecheck |
Validates TypeScript types across all .ts/.tsx files |
npm run lint |
Runs ESLint 9 rules and Core Web Vitals checks |
npm run knip |
Audits repository for unused exports and dead dependencies |
npm run docs:sync |
Auto-generates docs/ARCHITECTURE.md, docs/GUTENBERG_PARSER.md, CHANGELOG.md, and docs/QUALITY_AUDIT_REPORT.md from source AST |
npm run catalog:sync |
Streams Project Gutenberg's catalog dump (78,000+ titles) and batch-upserts into Supabase |
npm run catalog:ingest |
Generates curated SQL seed files (supabase/seed_books.sql) for local setup |
npm run translations:sync |
Clusters multilingual translations across Gutenberg volumes and batch-upserts into Supabase (--all, --limit=N, --dry-run, --output=file.sql) |
npm run adr:new -- "Title" |
Creates a new Architecture Decision Record in docs/DECISIONS.md |
npm run build |
Compiles optimized Next.js 16 production bundle |
The repository enforces a closed-loop quality verification engine before any release or commit:
+-----------------------------------------------------------------------------+
| 7-GATEWAY CLOSED-LOOP VERIFICATION |
+-----------------------------------------------------------------------------+
| Pass 0.5 | Secret Scanner | Checks repository files for exposed keys |
| Pass 1 | TypeScript Engine | Strict typecheck with 0 compile errors |
| Pass 2 | Vitest Server Mocks | Validates MSW v2 handlers and query hooks |
| Pass 3 | Vitest Client UI | Unit & integration tests (>= 80% coverage)|
| Pass 4 | Living Docs Sync | Auto-updates ARCHITECTURE, AUDIT, & CHANGE|
| Pass 5 | ADR Validation | Validates DECISIONS.md sequential schema |
| Pass 6 | Quality & Dead Code | ESLint check and Knip unused code audit |
| Pass 7 | Production Build | Compiles Next.js production bundle |
+-----------------------------------------------------------------------------+
π Pre-Commit Enforcement: Any failure in Passes 0.5 through 7 immediately halts execution, outputs exact error telemetry, and automatically blocks the commit from being created.
| Document / Artifact | Scope & Verification Status | Live Resource Link |
|---|---|---|
| π Quality Audit & Test Suite Catalog | 7-Gateway status summary, live coverage metrics, and complete index of all 1656 tests across 174 test suites. | docs/QUALITY_AUDIT_REPORT.md |
| π CI/CD Quality Telemetry | Machine-readable JSON summary of build metrics, test suites, and coverage passes. | docs/quality-audit-results.json |
| ποΈ Living Architecture Matrix (C4) | AST-driven component inventory, route handlers, Zustand state, and dependency graphs. | docs/ARCHITECTURE.md |
| π Gutenberg Parser & Segmentation Reference | AST-compiled specification of the Gutenberg parser subsystem, heuristic regex contracts, pagination limits, and subtitle extraction rules. | docs/GUTENBERG_PARSER.md |
| πΊοΈ Living Product Roadmap | AST-verified roadmap with 0% drift, feature milestone tracking, and live progress metrics. | ROADMAP.md |
| π Living Changelog | Keep a Changelog 1.0.0 & SemVer release history across all milestones. | CHANGELOG.md |
| βοΈ Architecture Decision Records (ADRs) | 40 validated ADRs (ADR-001 through ADR-040) governing zero-API keys, state architecture, SEO rate-shielding, Web Speech narration, offline IndexedDB engines, completed reading state latches, enterprise polymorphism/encapsulation, Vitest performance architecture, self-hosted Supabase catalog caching, and autonomous full-catalog Gutenberg ingestion. | docs/DECISIONS.md |
| π Security Policy & Responsible Disclosure | Supported versions, vulnerability reporting protocols, and architectural safeguards. | SECURITY.md |
| π€ Contributor Guidelines | Onboarding guide, local development quickstart, testing protocols, and conventional commits. | CONTRIBUTING.md |
| ποΈ Code of Conduct | Contributor Covenant v2.1 standards for an inclusive, welcoming community. | CODE_OF_CONDUCT.md |
| π CI/CD Pipeline Guide | Developer runbook and pipeline execution workflows. | docs/PIPELINE_GUIDE.md |
| π οΈ Developer Maintenance Hub | Local setup, environment configuration, and contributor commands. | DEVELOPMENT.md |
- Google AI / Antigravity: For powering the autonomous agentic engineering, architectural refactoring, and deterministic quality verification driving the development of this codebase.
- Project Gutenberg: For pioneering the public domain digitization movement and preserving thousands of classic literary masterpieces for humanity.
- Gutendex by Gareth B. Johnson: For creating and maintaining the high-performance, open-source RESTful JSON web API for Project Gutenberg metadata.
- Booksaw Bookstore Design Template (CC BY 4.0): For inspiring the warm, tactile bookstore aesthetic and skeuomorphic open-book layouts.
Licensed under the MIT License. All queried literature and book texts originate from Project Gutenberg and are in the Public Domain (Zero Copyright / CC0) in accordance with international public domain statutes. For detailed term calculations, Berne Convention rules, and our confidential notice & takedown portal, see our Copyright & Licensing policy.