bookScan/
│
├── 📄 index.html # Main HTML entry point
├── 🎨 styles.css # Mobile-first CSS styling
│
├── 📦 Package Files
│ ├── package.json # Dependencies & scripts
│ ├── tsconfig.json # TypeScript configuration
│ └── .gitignore # Git ignore rules
│
├── 📚 Documentation
│ ├── README.md # Full project documentation
│ ├── QUICKSTART.md # Quick start guide
│ └── TODO.md # Remaining tasks & enhancements
│
├── 💻 Source Code (src/)
│ ├── app.ts # Main application logic & UI coordination
│ ├── types.ts # TypeScript interfaces (Book, Collection)
│ ├── storage.ts # localStorage management service
│ ├── scanner.ts # Barcode scanning service (Html5Qrcode)
│ ├── booksAPI.ts # Google Books API integration
│ └── utils.ts # UI utilities (toasts, modals, loading)
│
└── 🔨 Build Output (dist/)
└── [Compiled .js files] # Generated by TypeScript compiler
┌─────────────────────────────────────────────────────────┐
│ USER INTERFACE │
│ (index.html) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Collections │ │ Collection │ │ Scanner │ │
│ │ View │ │ Detail View │ │ View │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ APPLICATION LAYER │
│ (app.ts) │
│ │
│ • Event handling & user interactions │
│ • View switching & navigation │
│ • Coordinating services │
│ • UI state management │
└─────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌─────────────┐ ┌────────────────┐
│ StorageService │ │ ScannerSvc │ │ BooksAPIService│
│ (storage.ts) │ │(scanner.ts) │ │ (booksAPI.ts) │
├──────────────────┤ ├─────────────┤ ├────────────────┤
│ • CRUD │ │ • Camera │ │ • Fetch by ISBN│
│ operations │ │ access │ │ • Search books │
│ • Collections │ │ • Barcode │ │ • Parse API │
│ • Books │ │ scanning │ │ responses │
│ • localStorage │ │ • ISBN │ │ │
│ persistence │ │ validation│ │ │
└──────────────────┘ └─────────────┘ └────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌─────────────┐ ┌────────────────┐
│ localStorage │ │Html5Qrcode │ │ Google Books │
│ (Browser API) │ │ Library │ │ API │
└──────────────────┘ └─────────────┘ └────────────────┘
1. User clicks "Scan Book"
│
▼
2. ScannerService.startScanner()
│
▼
3. Camera opens, user points at barcode
│
▼
4. Html5Qrcode detects ISBN
│
▼
5. BooksAPIService.fetchBookByISBN(isbn)
│
▼
6. Google Books API returns book data
│
▼
7. StorageService.addBookToCollection()
│
▼
8. Data saved to localStorage
│
▼
9. UI refreshed with new book
1. App initializes
│
▼
2. StorageService.loadCollections()
│
▼
3. Data retrieved from localStorage
│
▼
4. Collections rendered in UI
│
▼
5. User clicks collection
│
▼
6. Books displayed for that collection
- Collections View - Grid of collection cards
- Collection Detail View - List of books in a collection
- Scanner View - Camera feed for barcode scanning
- New Collection Modal - Input for collection name
- Add Book Modal - Manual book entry form
- Collection Menu Modal - Rename/Delete options
- Toast Notifications - Temporary feedback messages
- Loading Overlay - Spinner for async operations
- App Header - Title and settings button
loadCollections(): Collection[]
saveCollections(collections: Collection[]): void
createCollection(name: string): Collection
updateCollection(id: string, updates: Partial<Collection>): void
deleteCollection(id: string): void
getCollection(id: string): Collection | null
addBookToCollection(collectionId: string, book: Omit<Book, 'id' | 'addedDate'>): Book
removeBookFromCollection(collectionId: string, bookId: string): voidfetchBookByISBN(isbn: string): Promise<Book | null>
searchBooks(query: string): Promise<Book[]>startScanner(elementId: string, onSuccess: callback, onError?: callback): Promise<void>
stopScanner(): Promise<void>
isRunning(): booleanshowToast(message: string, duration?: number): void
showLoading(message?: string): void
hideLoading(): void
showModal(modalId: string): void
hideModal(modalId: string): void
switchView(viewId: string): void
formatDate(dateString: string): string
escapeHtml(text: string): string{
id: string // Unique identifier
name: string // Collection name
books: Book[] // Array of books
createdDate: string // ISO 8601 date
modifiedDate: string // ISO 8601 date
}{
id: string // Unique identifier
isbn?: string // ISBN-10 or ISBN-13
title: string // Book title
authors?: string[] // Array of author names
publisher?: string // Publisher name
publishedDate?: string // Publication date
description?: string // Book description
thumbnail?: string // Cover image URL
addedDate: string // ISO 8601 date
}- Touch-friendly targets (48px minimum)
- Responsive grid layouts
- Large, clear buttons
- Optimized for one-handed use
- Works without JavaScript (basic HTML)
- Graceful degradation for older browsers
- Fallback to manual entry if scanning fails
- Minimal dependencies
- Local-first data storage
- Lazy loading of book images
- Efficient DOM updates
- Semantic HTML
- ARIA labels for icons
- Keyboard navigation support
- High contrast ratios
- XSS Prevention via
UIUtils.escapeHtml() - No sensitive data stored
- HTTPS required for camera access
- No backend = no server-side vulnerabilities
Source TypeScript (.ts)
│
▼
TypeScript Compiler (tsc)
│
▼
JavaScript (.js) + Source Maps (.js.map)
│
▼
Type Declarations (.d.ts)
│
▼
Output to dist/ folder
│
▼
index.html loads from dist/
When implementing planned features:
- Export/Import: Add
ExportServicefor JSON/CSV handling - Search: Add
SearchServicewith indexing - PWA: Add
ServiceWorkerand manifest.json - Sync: Consider
SyncServicefor cloud backup - Analytics: Optional
AnalyticsServicewrapper - Testing: Jest for unit tests, Playwright for E2E
This architecture prioritizes simplicity, maintainability, and mobile performance while remaining extensible for future enhancements.