LibraRex

Your Book Kingdom
🐉 Flutter 3.x 📊 Google Sheets Backend 🌐 Web · iOS · Android 🏷️ v0.14 — Active Dev

📖 Project Overview

LibraRex is a cross-platform personal book collection tracker built with Flutter, targeting web, iOS, and Android from a single codebase. It uses Google Sheets as a cloud backend, giving users a human-readable, always-accessible spreadsheet they own — with no subscription fees, no proprietary database lock-in, and full data portability.

The app is designed for avid readers and collectors who want to track books they own, have borrowed, are on their wishlist, or have in digital formats — all in one organised, beautifully branded interface.

Mission: "Own your library data. Never lose track of a book again."

Target Platforms

🌐 Web (Chrome) ✅ Active
🍎 iOS 🔜 Pending test
🤖 Android 🔜 Pending test
🖥️ macOS / Windows 🗺 Roadmap

⚙️ Tech Stack

LayerTechnologyPurpose
UI FrameworkFlutter 3.x / Dart 3Cross-platform UI and state management
Backend / StorageGoogle Sheets API v4Persistent cloud data store, user-owned
AuthenticationGoogle Sign-In (OAuth 2.0)Secure identity, per-user sheets
State ManagementProvider (ChangeNotifier)App-wide reactive state
FontsGoogle Fonts — InterUI text throughout the app
Image Cachingcached_network_imageBook cover thumbnails with shimmer
Import / Exportcsv + file_pickerCSV round-trip for data portability
Book LookupGoogle Books + OpenLibrary APIsISBN / title search for metadata
Logo / ArtworkFlutter CustomPainterGeometric dragon — no SVG dependency
Loading Statesshimmer packageSkeleton screens while loading
Token Storageflutter_secure_storagePersists auth across app restarts

🗄️ Data Schema

Each book is a single row in Google Sheets with 18 columns. The sheet is created automatically on first sign-in with a header row.

ColFieldTypeDescription
AidStringUUID — unique stable identifier
BtitleStringBook title (required)
CauthorStringAuthor name (required)
DtypeEnumowned | borrowed | wishlist | digital
EstatusEnumavailable | lent_out | missing
FreadBooleantrue | false — Read / Unread flag
GlentToStringName of person the book is lent to
HisbnStringISBN-10 or ISBN-13
IcoverUrlStringURL to cover thumbnail image
JratingDouble0.5–5.0 in 0.5 increments (half-star support)
KnotesStringFree-text annotations
LgenreStringGenre label
MpublisherStringPublisher name
NyearIntegerPublication year
OblurbStringBook synopsis / description
PupdatedAtStringISO 8601 timestamp of last edit
QformatStringHardcover · Paperback · Large Print · eBook · Audiobook
RlocationStringShelf / room (physical) or service name (digital, e.g. Kindle)

🔐 Authentication

🔑
Google Sign-In

OAuth 2.0 via google_sign_in. Session persists across reloads via flutter_secure_storage.

👤
Per-User Sheets

Each Google account gets its own isolated spreadsheet. No data is shared between users.

🚪
Sign-Out

Confirmation dialog before sign-out. Clears session and returns to the auth screen.

🐉
Splash Screen

Branded auth screen with LibraRex dragon logo, wordmark, and "Your book kingdom" tagline.

📚 Book Collection Management

📗
Four Book Types

Owned, Borrowed, Wishlist, and Digital — each with appropriate icon and colour treatment.

📍
Physical Status

Available, Lent Out (with borrower name), or Missing. Status is filterable independent of type.

Read / Unread

Simple read flag displayed as a badge in grid cards and list items.

Half-Star Ratings

0.5 increments from 0.5 to 5.0 (e.g. 4.5 ★). Tap left half of a star for a half-star.

📝
Rich Metadata

Notes, genre, publisher, publication year, ISBN, cover URL, and full blurb storage.

🔗
Lent-To Tracking

Record who you've lent a book to. Shown prominently in card and list views.

🖥️ Library UI

Grid View

Card layout with cover art, title, author, and contextual status info at the bottom.

List View

Compact rows with thumbnail, title, author, rating, and type badge overlay on the cover.

🔍
Animated Search

Search bar slides in/out with ClipRect animation. Searches title, author, and ISBN.

🔽
Filter Pills

Two popup filter buttons — Type and Status. Status is always active regardless of type filter.

🔄
Pull-to-Refresh

Swipe down to re-sync the latest data from Google Sheets.

💀
Shimmer Skeletons

Animated loading placeholders for grid and list views during the initial data fetch.

✏️ Add / Edit & Detail

Quick Add Screen

Dedicated entry point via the library FAB. Search tab with live results (cover, series chip, author) or ISBN tab for direct entry. Tap any result to pre-fill the full form instantly.

Add Book Form

Full 18-field form with type picker, status selector, read toggle, format chip picker, location field, and half-star rating.

🔎
Book Lookup

Search by ISBN or title via Google Books / OpenLibrary. Auto-fills cover, publisher, year, series, and blurb.

📄
Detail Screen

Full read-only view with large cover. Inline editable rating and location. Series chip links directly to the Series Detail screen.

🗑️
Delete with Confirm

Confirmation dialog before removing a book from the library and Google Sheets.

🖼️
Bulk Scan

Scans all books to fetch/update cover artwork and blurbs. Progress dialog with per-book status.

🔖 Series Intelligence

LibraRex can discover, display, and track book series — showing you what you own, what's missing, and making it easy to fill the gaps.

📋
Series Detail Screen

Rich view of all books in a series in reading order. Owned books show with cover art; missing books appear as ghost slots with their order number and title.

🔍
Find Missing Books

4-tier API lookup: Google Books → WikiData SPARQL (exact + fuzzy) → OpenLibrary by series name → OL author + keyword supplement. Catches partial coverage across all sources.

👻
Ghost Row Slots

Missing series books shown as dim placeholders. One-tap "Add to Wishlist" CTA turns any gap into a tracked wishlist entry.

✏️
Editable Series Name

Series name editable directly from the Series Detail screen. Changes save to all owned books in the series at once.

🔢
Series Order Chips

Each book slot shows its reading order number. Owned books without a stored order are matched to slots by normalised title comparison.

🔎
Search Within Series

Filter bar inside the Series Detail screen to quickly find a specific book when a series spans many entries.

How the lookup works: The app queries Google Books first (fastest, best mainstream coverage), then WikiData SPARQL (excellent for classic and literary series), then OpenLibrary by series name, and finally OpenLibrary by author + series keyword as a final supplement. Results from all sources are merged and de-duplicated by series order — preferring entries with cover art.

↕️ Import / Export

⬇️
Export CSV

Downloads the full library as a CSV file. Smart decimal formatting (writes "4.5" not "4.5000").

⬆️
Import CSV

Maps CSV columns to book fields with row-level validation. Reports errors for malformed rows.

📁
File Picker

Native file picker on web and mobile via file_picker. Platform download utility handles save correctly per platform.

🎨 Brand & Themes

🐉
Dragon Logo

Geometric wyvern drawn entirely with Flutter CustomPainter. No external SVG package needed.

🟠
Amber / Cognac Palette

Primary #B5621E (warm cognac), accent #D4943A (gold). Inspired by aged leather and parchment.

☀️
Light Theme

Parchment background (#FDF5EC) with white card surfaces. Warm and readable.

🌙
Dark Theme

Deep brown background (#191410) with warm dark surfaces (#271D15). Easy on the eyes at night.

⚙️
System Theme

Follows the device OS preference. Switches automatically between light and dark.

🔁
Theme Toggle

Overflow menu (⋮) cycles System → Light → Dark → System. Updates the whole app instantly.

🗺️ Roadmap

The following are potential enhancements, not yet prioritised or scheduled. They are grouped by theme to aid planning conversations.

☁️ Alternative Backends & Sync

  • OneDrive / SharePoint — store the library as an Excel file in a user's OneDrive account, enabling Microsoft 365 users to use LibraRex without a Google account
  • Dropbox / iCloud Drive — JSON or CSV file sync for Apple-ecosystem users
  • Firebase Firestore — real-time multi-device sync, potential for social / sharing features
  • Supabase (PostgreSQL) — open-source Firebase alternative for self-hosters
  • Local-only mode — full offline use with no cloud backend required

📶 Offline & Performance

  • Hive / SQLite local cache — persist books locally so the app loads instantly and works without connectivity
  • Background sync — push local changes to the backend when connectivity is restored
  • Optimistic UI updates — reflect edits instantly without waiting for the API round-trip
  • Pagination — load books in pages for very large libraries (1,000+ books)

🔍 Book Discovery & Metadata

  • Camera barcode scanner — use device camera (vs. manual ISBN entry) to scan a physical book's barcode for instant add
  • Author pages — aggregate all books by an author, with bio from Open Library
  • Richer metadata — page count, language, subjects, awards
  • Book recommendations — suggest similar books based on genres and ratings in the library

📊 Reading Tracking

  • Reading progress — track current page or percentage complete per book
  • Reading dates — log when a book was started and finished
  • Annual reading goals — set a target number of books for the year
  • Statistics dashboard — charts for books read per month/year, genre breakdown, average rating, reading pace
  • Reading streaks — gamified daily reading habit tracking

📦 Collections & Organisation

  • Multiple shelves — custom named collections (e.g. "Holiday Reads", "Book Club")
  • Tagging system — flexible user-defined tags in addition to type/status
  • Bulk actions — select multiple books to move, tag, or delete at once
  • Custom sort orders — sort by title, author, rating, date added, year published

📥 Import from Other Services

  • Goodreads CSV import — map Goodreads export columns to LibraRex fields
  • Apple Books — import reading history
  • Kindle / Amazon — import purchased and read book lists
  • LibraryThing — support the LibraryThing export format

🔗 Export & Integrations

  • Notion export — push library as a Notion database
  • Airtable sync — two-way sync with an Airtable base
  • Push notifications — remind user when a lent book is overdue for return
  • Webhook support — trigger external automations on book events

👥 Social & Sharing

  • Public profile / shelf — opt-in shareable reading list URL
  • Book club mode — shared libraries for a group with per-member read status
  • Lend notifications — notify a friend via link when a book is lent
  • Book reviews — longer-form review text separate from the notes field

📱 Platform & UX

  • iPad / tablet layout — master-detail split view with sidebar navigation
  • macOS & Windows desktop — Flutter desktop targets with keyboard shortcuts
  • Apple Watch / Wear OS — quick "Mark as read" and lend/return companion actions
  • Home-screen widgets — iOS and Android widgets showing current read or recently added
  • Accessibility — full screen-reader support, dynamic text size, high-contrast mode
  • Internationalisation — multi-language UI (Spanish, French, German, Japanese)

📋 Change Log

All notable changes to LibraRex. Format inspired by Keep a Changelog.

v0.14 March 2026 Quick Add Screen & Smart Search
AddedQuickAddScreen — two-tab entry point (Search + ISBN) accessible from a new "Add Book" extended FAB on the Library screen
AddedSearch tab with 450 ms debounced live search, showing cover thumbnails, series chip, and author for each result — tap any result to pre-fill the full Add/Edit form
AddedISBN tab with auto-lookup triggered at 10 or 13 digits — preview card with cover, title, and author appears before committing the add
AddedquickSearch() method in BookLookupService — detects name-like queries and uses inauthor: prefix for better author results; single smart query with fallback only when primary returns empty, preserving API quota
Addedprefill: BookLookupResult? parameter on AddEditBookScreen — pre-populates all fields from a lookup result without requiring a second manual lookup
ChangedLibrary screen "Add Book" menu item and FAB now route to QuickAddScreen instead of the bare Add/Edit form
v0.13 March 2026 Find Missing Books — Multi-Source Lookup
Added4-tier series lookup: Google Books → WikiData SPARQL (exact match + fuzzy fallback) → OpenLibrary series name → OpenLibrary author + keyword supplement (always runs, catches partial-coverage sources)
AddedCross-source de-duplication by series order — when two sources return the same slot number, keeps the entry with a cover image; ties broken by shorter title
AddedBundle/omnibus filter — regex pattern removes box sets, collected editions, and multi-book sets from series results
FixedSeries with no WikiData coverage (e.g. Fractalverse) now discovered via OL author + keyword query using combined author:"name" seriesTitle syntax
FixedOpenLibrary results without a series field are now accepted when returned by the combined keyword query (trust the query filtering, not just the metadata field)
FixedDuplicate entries at the same series order (e.g. "Catching Fire" and "The Hunger Games: Catching Fire") now correctly collapsed to one slot
v0.12 March 2026 Series Detail Screen
AddedSeries Detail Screen — shows owned books grouped by series in reading order, with series order chips and a "Find Missing Books" action button
AddedGhost row slots for missing books — dim placeholder cards showing the book's order, title, and a one-tap "Add to Wishlist" CTA
AddedSearch / filter bar within the Series Detail screen
AddedEditable series name — pencil icon on the detail screen header saves changes to all books in the series
FixedOwned books with no stored seriesOrder now correctly matched to series API slots via normalised title comparison (_normTitle strips leading "Series: " prefix)
FixedOwned books no longer appear as both an owned row and a ghost row when seriesOrder is absent
v0.11 March 2026 Book Detail Polish & Light Mode Improvements
ChangedBook Detail Screen — inline editable rating row; no longer requires opening the full edit form to update a rating
ChangedBook Detail Screen — series name shown as a tappable chip that navigates directly to the Series Detail screen
ChangedBook Detail Screen — location field editable inline with a tap-to-edit interaction
DesignLight mode AppBar now uses warm cognac tones instead of white, aligning with the brand palette
DesignCard shadows added in light mode for improved visual depth and separation
v0.10 March 2026 Book Format & Library Location
AddedBook Format field — chip picker supporting Hardcover, Paperback, Large Print, eBook, and Audiobook; options filter by book type (e.g. Digital books only show eBook / Audiobook)
AddedLibrary Location field — free-text input with smart pre-populated suggestions based on type: physical books suggest shelf names, digital books suggest Kindle, Kobo, Apple Books, Audible, Scribd, Hoopla, Libby
AddedLocation suggestion chips appear below the location text field and tap-to-fill the input
ChangedGoogle Sheets schema expanded from 16 to 18 columns — format at column Q, location at column R; existing sheets are backwards-compatible (new columns read as empty)
ChangedGrid card now shows location (with shelf/cloud icon) when set, before falling through to stars or read/unread
ChangedList view status row now shows a secondary line with format (layers icon) and/or location (shelf/cloud icon) when either field is populated
v0.9 March 2026 Brand Identity & Theme System
DesignWarm Amber / Cognac primary colour (#B5621E), Gold accent (#D4943A) — replacing the original indigo/green palette
DesignLight theme: parchment background (#FDF5EC) and white card surfaces. Dark theme: deep brown background (#191410) with warm dark surfaces
AddedCustom LibraRex dragon logo — geometric wyvern drawn with Flutter CustomPainter; no external SVG package
AddedRexLogoFull (AppBar wordmark) and RexSplashLogo (auth screen hero) widgets
AddedLight / Dark / System theme toggle in the overflow (⋮) menu — cycles System → Light → Dark → System
AddedThemeMode state in LibraryProvider with cycleTheme() method
ChangedLibraRexApp now uses context.select to read ThemeMode from LibraryProvider, causing MaterialApp to rebuild on theme change
v0.8 March 2026 UI Polish — Cards, List View & Search Bar
FixedSearch bar semi-transparent bleed-through when hidden — replaced OverflowBox with ClipRect + AnimatedContainer so content is properly clipped to 0 height
ChangedGrid card layout: title/author pushed to top, contextual status info pushed to bottom using MainAxisAlignment.spaceBetween
Added_GridStatusLine widget — shows lent-to name, missing indicator, wishlist/borrowed labels, star rating, or Read/Unread in priority order
AddedType icon badge (_TypeBadge) overlaid on list view thumbnails for Borrowed, Wishlist, and Digital types
v0.7 March 2026 Half-Star Ratings (0.5 Increments)
ChangedBook.rating type: int? → double? — supports 0.5 increments from 0.5 to 5.0
ChangedRating parsing, validation, and serialisation updated across Book model, sheets service, and import/export service
FixedDart null-safety compile error on double? field — resolved with local variable pattern (final r = rating) for Dart field promotion
Addedstar_half_rounded icon in _MiniStarRow for fractional star display
AddedPosition-based half-star tap detection using GestureDetector.onTapDown + localPosition.dx in both detail screen and add/edit form
v0.6 March 2026 Filter UI Overhaul & Status Filter Fix
ChangedReplaced scrollable chip strip with two PopupMenuButton filter pills (Type + Status)
FixedStatus filter was visually greyed out whenever Type was not set to Owned — removed all muted/disabled logic; Status is now always equally usable
FixedStatus book counts now use countFor(_activeType, ...) rather than hardcoded BookType.owned
AddedLive book count in the filter row that updates as filters change
AddedPer-option book counts shown inside the popup menus
v0.5 Feb 2026 Import / Export & Bulk Scan
AddedExport full library to CSV; import from CSV with row-level validation and error reporting
AddedImport/Export screen with file picker
AddedBulk Scan dialog — fetches cover artwork and blurbs for all books with progress tracking
Addedplatform_download utility with web, mobile, and stub variants
v0.4 Feb 2026 Book Lookup, Detail Screen & Cover Art
AddedBook detail screen with cover image and inline editable star rating
AddedBookLookupService — searches Google Books and OpenLibrary by ISBN or title
AddedCachedNetworkImage for covers with shimmer placeholder
AddedUser profile avatar in the AppBar with initial fallback
v0.3 Jan 2026 Library UI — Grid, List & Add/Edit
AddedLibrary screen with AppBar, filter row, and book grid/list
AddedBookCard (grid) and BookListItem (list) widgets
AddedAnimated search bar with toggle button
AddedAdd/Edit book screen with all 16 fields; create and update flows
AddedShimmer loading skeletons for both grid and list views
AddedEmpty-state illustrations with contextual messaging per filter
AddedPull-to-refresh and error view with retry button
v0.2 Jan 2026 Google Sheets Backend & Data Model
AddedSheetsService with full CRUD over the Google Sheets API v4
AddedAuto-create sheet with header row on first sign-in
AddedLibraryProvider (ChangeNotifier) — books list, loading/error states, user session
AddedBook model with 16-column schema, BookType and PhysicalStatus enums
AddedfilteredBooks() method — filter by type and/or status
AddedUUID-based book IDs and updatedAt timestamp on every save
v0.1 Dec 2025 Project Foundation & Authentication
AddedFlutter project scaffolded for web, iOS, and Android
AddedGoogle Sign-In (OAuth 2.0) with session persistence via flutter_secure_storage
AddedAuthScreen and AuthService
AddedNamed route navigation and Material 3 MaterialApp
Addedpubspec.yaml with full dependency list and analysis_options.yaml

🚀 Getting Started

Prerequisites

Run locally

flutter pub get
flutter run -d chrome --web-port 3000
Always use --web-port 3000 to match the registered OAuth origin. Using a different port will trigger a Google origin_mismatch (Error 400).

Key Packages

PackageVersionPurpose
google_sign_in^6.2.1OAuth authentication
googleapis^13.2.0Sheets API client
provider^6.1.2State management
google_fonts^6.2.1Inter font family
cached_network_image^3.3.1Cover image caching
shimmer^3.0.0Loading skeleton effect
file_picker^8.0.3CSV import file dialog
csv^6.0.0CSV parse & serialise
flutter_secure_storage^9.2.2Token persistence

☁️ Deployment & Google Drive Setup

One of the most common questions is: "If I share this app with someone, what do they have to set up with Google Drive?" The short answer is nothing — end users just sign in with their Google account and the app does everything else automatically. The only one-time setup is done by the developer (you) when configuring the Google Cloud project.

👤 What end users do

From a user's perspective the setup is completely invisible:

  1. Open the app URL in their browser (or install the mobile app).
  2. Tap Sign in with Google and complete the standard OAuth consent screen.
  3. The app automatically creates a Google Sheet called LibraRex Library in their Google Drive.
  4. They can start adding books immediately — no spreadsheet configuration needed.
Users own their data. The sheet lives in their Google Drive account. They can open it, export it, or delete it at any time. LibraRex only requests the minimum required scopes: Sheets (read/write) and Drive (file metadata to locate the sheet).

🛠️ One-time developer / operator setup

Before the app can be shared, a developer needs to configure a Google Cloud project once. This is a ~15-minute process:

StepActionWhere
1Create a Google Cloud projectconsole.cloud.google.com
2Enable Google Sheets APIAPIs & Services → Enable APIs
3Enable Google Drive APIAPIs & Services → Enable APIs
4Create an OAuth 2.0 Web Client IDAPIs & Services → Credentials
5Add your deployment URL to Authorised JavaScript OriginsEdit the OAuth client
6Paste the Client ID into web/index.htmlFlutter project source
7(Optional) Create a Google Books API key and add it to the projectAPIs & Services → Credentials
Books API key tip. LibraRex uses the Google Books API for metadata lookups (Quick Add, book lookup, series search). Without a key it uses anonymous quota (~1,000 requests/day shared across all users of the app). For a multi-user deployment, create an API key, restrict it to your domain, and add it to lib/services/book_lookup_service.dart.

🌐 Self-hosting (web)

flutter build web --release
# Upload the build/web/ directory to any static host
# (Firebase Hosting, Netlify, Vercel, GitHub Pages, etc.)

Add your production URL (e.g. https://librarex.example.com) to the OAuth client's Authorised JavaScript Origins. That's it — no server-side component needed.

📱 Mobile (iOS / Android)

For native mobile builds, replace the web OAuth client ID with a platform-specific one (iOS client ID for iOS, Android client ID for Android) in the corresponding configuration files (ios/Runner/Info.plist, android/app/google-services.json). The Sheets and Drive API usage is identical; only the auth credential type differs.

🔒 OAuth consent screen & app verification

While in development, add test users to the OAuth consent screen so they can sign in without Google's verification process. For a wider public release, Google requires an app verification review (typically free, takes a few days) to remove the "unverified app" warning from the consent screen. The review verifies that the app only requests the scopes it actually uses.

⚠️ Known Limitations

No offline support (current). All reads and writes go directly to the Google Sheets API. The app requires connectivity to load or save books. Local caching (Hive) is a high-priority roadmap item.
Sheets API rate limits. The API allows ~300 read requests/min per project. For large libraries or frequent refreshes, a local cache is recommended to reduce API calls.
Single-user per sheet. Each signed-in Google account has its own sheet. There is no sharing or multi-user collaboration on a single library yet (see Roadmap §Social).