Skip to content

Latest commit

 

History

History
2048 lines (1398 loc) · 31.2 KB

SPECIFICATION.md

File metadata and controls

2048 lines (1398 loc) · 31.2 KB

Bookify PWA — Implementation Specification

1. Product Summary

Build Bookify, a lightweight installable PWA that turns long-form webpages into an ebook-like reading experience.

Bookify should allow a user to:

  1. Open a long webpage in Safari.
  2. Invoke a bookmarklet.
  3. Either:
    • read the current webpage immediately in paginated mode, or
    • save/import the article into the Bookify PWA.
  4. Read saved articles from a unified Bookify library.
  5. Resume at approximately the same sentence regardless of:
    • font-size changes,
    • viewport changes,
    • device orientation,
    • repagination.
  6. Read saved articles offline.
  7. Install Bookify to the iOS Home Screen as a standalone PWA.

The initial version must require no backend and must be deployable entirely using GitHub Pages.

The application should be designed so a backend sync service and Safari Web Extension can be added later without rewriting the reader or data model.


2. Primary Design Principle

Bookify must distinguish between:

Capture

Getting readable content out of an arbitrary webpage already loaded in Safari.

Reading

Displaying that content in a persistent ebook-style library and reader.

The initial architecture is:

Safari webpage
      |
      | Bookify bookmarklet
      |
      +---------------------+
      |                     |
      v                     v
  Read Here          Save to Bookify
      |                     |
Bookmarklet reader      PWA import
                            |
                            v
                        IndexedDB
                            |
                            v
                    Bookify reader

Long term:

Bookmarklet
    |
Safari Web Extension
    |
    +------ Bookify Import Protocol ------+
                                          |
                                          v
                                     Bookify PWA
                                          |
                                       Sync API

The PWA reader and stored article format should therefore not depend on the bookmarklet implementation.


3. Target Platforms

Initial priority:

  1. iPhone Safari / Home Screen PWA
  2. iPad Safari / Home Screen PWA
  3. macOS Safari
  4. Chrome/Edge/Firefox desktop

The reader should use standards-based HTML/CSS/JavaScript wherever possible.

Do not introduce native iOS code for v1.


4. Technology Stack

Use:

TypeScript
Vite
HTML/CSS
IndexedDB
Service Worker
Web App Manifest
GitHub Actions
GitHub Pages

Prefer a lightweight architecture.

Do not use a heavy application framework unless it materially simplifies the project.

A small component framework is acceptable, but plain TypeScript or a lightweight library is preferred.

Suggested dependencies:

idb
vite
typescript
vitest
playwright

Optional:

dompurify

If DOMPurify is used, sanitize imported HTML before storing/rendering.

Avoid runtime CDN dependencies.

Everything required for the app should be bundled locally so the installed PWA works offline.


5. Repository Structure

Suggested structure:

bookify/
├── README.md
├── package.json
├── tsconfig.json
├── vite.config.ts
├── index.html
├── public/
│   ├── manifest.webmanifest
│   ├── icons/
│   │   ├── icon-192.png
│   │   ├── icon-512.png
│   │   └── apple-touch-icon.png
│   └── favicon.ico
│
├── src/
│   ├── main.ts
│   ├── app.ts
│
│   ├── library/
│   │   ├── library.ts
│   │   ├── library-view.ts
│   │   └── library.css
│
│   ├── reader/
│   │   ├── reader.ts
│   │   ├── paginator.ts
│   │   ├── position.ts
│   │   ├── typography.ts
│   │   ├── reader.css
│   │   └── toc.ts
│
│   ├── storage/
│   │   ├── db.ts
│   │   ├── articles.ts
│   │   ├── positions.ts
│   │   ├── annotations.ts
│   │   └── preferences.ts
│
│   ├── import/
│   │   ├── importer.ts
│   │   ├── protocol.ts
│   │   ├── sanitize.ts
│   │   └── normalize.ts
│
│   ├── bookmarklet/
│   │   ├── bookmarklet.ts
│   │   ├── extractor.ts
│   │   ├── inline-reader.ts
│   │   └── build-bookmarklet.ts
│
│   ├── pwa/
│   │   ├── service-worker.ts
│   │   └── install.ts
│
│   ├── settings/
│   │   └── settings.ts
│
│   └── types.ts
│
├── tests/
│   ├── unit/
│   └── e2e/
│
└── .github/
    └── workflows/
        └── deploy-pages.yml

6. Core User Experience

6.1 Library Screen

The PWA home screen should resemble a simple ebook library.

Example:

Bookify

Recently Read

Language models and the Transformer
Deep Learning with Python
28% complete
Last read 12 min ago

Attention Is All You Need
61% complete

Santos-Dumont
Finished

Each saved item should display:

  • title,
  • source/domain,
  • reading progress,
  • last-read date,
  • optional estimated reading time.

Actions:

  • open,
  • delete,
  • mark unread,
  • mark finished,
  • open original webpage.

Sort options:

  • recently read,
  • recently added,
  • title,
  • progress.

Initial release does not require folders or tags.


7. Reader UX

The reader should feel closer to Kindle/Apple Books than a web browser.

7.1 Layout

Standalone PWA:

+--------------------------------+
| x      Article Title      A- A+ |
+--------------------------------+
|                                |
|                                |
|       paginated article        |
|                                |
|                                |
+--------------------------------+
|       <    36 / 129    >       |
+--------------------------------+

The page-turn buttons are the only normal way to change pages.

Critical behavior

DO NOT TURN PAGES WHEN THE USER:

  • swipes horizontally,
  • swipes vertically,
  • taps the left side,
  • taps the right side,
  • taps the article background.

Page navigation occurs only when the explicit:

<
>

buttons are pressed.

Keyboard page navigation should also be disabled initially.

Escape may close the reader on desktop.

This requirement exists because:

  • tables may require horizontal scrolling,
  • code blocks may require scrolling,
  • images or diagrams may be explored using touch gestures,
  • accidental page turns are disruptive.

8. Pagination Engine

Use CSS multi-column layout.

Conceptually:

.reader-content {
    height: var(--page-height);
    column-width: var(--page-width);
    column-gap: var(--page-gap);
    column-fill: auto;
}

The reader viewport must clip the complete column set.

Changing pages should update the content offset immediately.

Avoid animated scrolling by default.

Especially on e-ink-like devices and mobile browsers:

instant page change

is preferable to:

smooth horizontal animation

The paginator must calculate:

pageWidth
columnGap
columnStride
totalPages
currentPage

Do not assume:

pageStride === window.innerWidth

because margins and gaps affect layout.


9. Repagination

Repaginate when:

  • viewport changes,
  • device rotates,
  • font size changes,
  • line-height changes,
  • margins change,
  • fonts finish loading,
  • an image affecting layout finishes loading.

Repagination must restore the user's semantic reading position, not merely the previous numeric page.

Example:

Before font-size change:

Page 36 / 129

After font-size increase:

Page 47 / 168

The visible text should still begin at approximately the same sentence.


10. Reading Position Model

Do not treat page number as the authoritative reading position.

Pages are ephemeral.

Store a semantic anchor.

Suggested representation:

interface ReadingPosition {
    articleId: string;

    progress: number;

    quote?: {
        exact: string;
        prefix?: string;
        suffix?: string;
    };

    textOffset?: number;

    headingId?: string;

    lastKnownPage?: number;
    lastKnownTotalPages?: number;

    updatedAt: number;
}

Primary recovery order:

1. exact quote + prefix/suffix
2. text offset
3. heading + local offset
4. normalized percentage
5. previous page number

The goal is to survive:

  • typography changes,
  • screen changes,
  • moderate source HTML changes.

11. Text Anchor Creation

When saving reading position, determine a text range near the beginning of the visible page.

Store approximately:

prefix:  20–50 chars
exact:   40–120 chars
suffix:  20–50 chars

Example:

{
  "prefix": "representation of the source sequence. We can achieve this with a ",
  "exact": "Bidirectional layer.",
  "suffix": " Next, let's add the decoder"
}

Normalize:

  • repeated whitespace,
  • non-breaking spaces,
  • line breaks.

On restoration:

  1. generate normalized article text,
  2. search for exact,
  3. disambiguate using prefix/suffix,
  4. map match back to DOM,
  5. find the generated CSS column containing it,
  6. navigate to that column.

12. Article Data Model

Use a versioned stored representation.

interface Article {
    id: string;

    schemaVersion: number;

    title: string;
    author?: string;

    sourceUrl: string;
    canonicalUrl?: string;
    sourceDomain: string;

    html: string;
    plainText: string;

    headings: ArticleHeading[];

    savedAt: number;
    updatedAt: number;
    lastReadAt?: number;

    estimatedMinutes?: number;
}

Use a deterministic ID when practical.

For example:

SHA-256(canonical URL)

or use a UUID plus a canonical URL uniqueness index.

Do not create duplicate copies every time an article is saved.

If the same canonical URL already exists, prompt/update appropriately.


13. IndexedDB

Use IndexedDB rather than localStorage for application content.

Suggested stores:

articles
positions
annotations
preferences
imports

Possible schema:

articles
  key: id
  indexes:
    canonicalUrl
    savedAt
    lastReadAt

positions
  key: articleId

annotations
  key: annotationId
  index:
    articleId

preferences
  key: name

Use a schema version and explicit migrations.


14. Reader Preferences

Persist globally:

interface ReaderPreferences {
    fontSize: number;
    lineHeight: number;

    marginSize:
        | "small"
        | "medium"
        | "large";

    theme:
        | "system"
        | "light"
        | "dark";

    font:
        | "serif"
        | "sans";
}

Initial UI only requires:

A-
A+

but design the data model for future settings.


15. Dark Mode

Dark mode must be intentionally styled.

Do not rely on arbitrary source-page CSS.

Reader-owned CSS should override imported colors where necessary.

Suggested variables:

--reader-bg
--reader-fg
--reader-muted
--reader-panel
--reader-border
--reader-link
--reader-code
--reader-inline-code

In dark mode:

  • body text must be light,
  • captions must remain readable,
  • code-block text must not remain black,
  • table borders must remain visible,
  • links must remain distinguishable,
  • inline code may use a contrasting accent.

Imported source styles should not be allowed to make text invisible.

SVG handling may require a white background where the source assumes black-on-white rendering.


16. Code Blocks

Code blocks must remain usable.

Default behavior may wrap code where practical:

white-space: pre-wrap;
overflow-wrap: anywhere;

However, preserve semantic code formatting.

Later configuration may allow:

Wrap code: ON/OFF

If horizontal scrolling is used, scrolling the code must never trigger page navigation.


17. Tables

This requirement is important.

Wide tables must be independently horizontally scrollable.

Wrap tables as:

<div class="bookify-table-scroll">
    <table>...</table>
</div>

Use:

.bookify-table-scroll {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
}

The table itself may use:

width: max-content;
min-width: 100%;

A horizontal finger drag over a table must scroll the table.

It must never turn the ebook page.


18. Images and Figures

Images should:

  • scale down to page width,
  • preserve aspect ratio,
  • avoid splitting across pages when possible.

Use:

break-inside: avoid;
max-width: 100%;
height: auto;

Figures and captions should generally remain together.

Large images should remain viewable without forcing article width beyond the page.

Future enhancement:

tap image -> fullscreen image viewer

Not required for v1.


19. Table of Contents

Generate a TOC from:

h1
h2
h3

Normalize missing IDs.

Example:

Chapter 15
  Sequence-to-sequence learning
  RNN-based sequence models
  Transformers
    Self-attention
    Multi-head attention

Selecting a heading should:

  1. find the DOM heading,
  2. determine the containing CSS column,
  3. jump directly to that page.

20. Bookmarklet

Maintain the existing ability to run Bookify directly inside an arbitrary webpage.

The bookmarklet should present:

Bookify

[ Read Here ]

[ Save to Bookify ]

The exact menu styling may evolve.


21. Bookmarklet: Read Here

Read Here should recreate the existing Bookify behavior:

  • overlay reader,
  • CSS pagination,
  • dark mode,
  • A-/A+ controls,
  • page count,
  • local reading position,
  • horizontal table scrolling,
  • explicit page-turn buttons.

Navigation requirement

Do not include:

  • swipe page turning,
  • tap-edge page turning.

Only the previous/next buttons turn pages.


22. Bookmarklet Character Encoding

The bookmarklet URL itself should be generated in an ASCII-safe form.

Previous prototypes exposed mojibake such as:

×
‹
›

when Unicode UI symbols were stored inside Safari bookmark URLs.

Avoid literal non-ASCII punctuation inside bookmarklet source.

Use either:

&times;
&lsaquo;
&rsaquo;

or plain ASCII equivalents.

The bookmarklet build should include an automated assertion:

if (!bookmarkletIsAscii) {
    throw new Error(...)
}

23. Bookmarklet Build

Maintain readable source:

src/bookmarklet/bookmarklet.ts

Generate:

dist/bookmarklet.txt

The output should be:

javascript:(()=>{...})();

minified to one line.

Provide a development page in Bookify that displays:

Install Bookmarklet

1. Bookmark this page.
2. Edit the bookmark.
3. Replace its URL with:
   [Copy Bookmarklet]

Include a one-tap copy button where browser permissions permit.


24. Article Extraction

The bookmarklet must determine the primary content area.

Candidate order:

article
main
[role="main"]
known content containers
body fallback

Use a scoring heuristic if necessary.

Prefer semantic content containing substantial:

p
h1
h2
h3
pre
code
figure
table
img

Remove obvious:

nav
footer
aside
cookie banners
advertising
share widgets
site headers

Do not aggressively remove legitimate technical content.

The Deep Learning with Python chapter should be included as a regression fixture/test case because it contains:

  • prose,
  • headings,
  • code,
  • captions,
  • inline code,
  • links.

25. Imported HTML Security

Never execute scripts from imported articles.

Remove:

script
iframe
object
embed
form
input
button
textarea

unless explicitly required later.

Strip:

onload
onclick
onerror
...

and other event-handler attributes.

Do not preserve arbitrary executable JavaScript.

Sanitize URLs.

The reader should display imported content as inert document content.


26. URL Normalization

Resolve relative resource URLs before storing.

Given:

<img src="../images/foo.png">

convert it to an absolute URL based on the source page.

Do the same for:

img src
source src
a href

Preserve original article links.

Clicking a normal article link should open Safari/the external browser rather than navigate the PWA away from its application shell.


27. Save-to-PWA Import Protocol

Define a versioned protocol independent of the bookmarklet.

Example:

interface BookifyImportMessage {
    protocol: "bookify-import";
    version: 1;

    article: {
        sourceUrl: string;
        canonicalUrl?: string;

        title: string;
        author?: string;

        html: string;
        plainText?: string;
    };
}

This same format should eventually be usable by:

  • bookmarklets,
  • Safari extension,
  • Chrome extension,
  • desktop utility,
  • backend fetcher.

28. Bookmarklet → PWA Transport

Implement transport defensively.

Preferred automatic path:

bookmarklet
     |
window.open(Bookify import page)
     |
     v
PWA loads
     |
BOOKIFY_READY
     |
     v
bookmarklet sends import payload via postMessage

Validate:

origin
protocol
version
payload structure

Do not use postMessage(..., "*") for the final implementation.

The expected Bookify origin should be configured at build time.


29. Import Transport Fallback

Mobile Safari behavior around opened windows should be treated as something that must be empirically tested.

Therefore provide a fallback path.

Suggested fallback:

  1. serialize the Bookify import payload,
  2. copy it to clipboard,
  3. open Bookify /import,
  4. provide an Import from Clipboard button.

Do not depend on extremely long query strings or URL fragments for full article HTML.

The application should present a useful error instead of silently losing an article.


30. PWA Manifest

Configure an installable web application.

Example behavior:

{
  "name": "Bookify",
  "short_name": "Bookify",
  "display": "standalone",
  "start_url": "./",
  "scope": "./"
}

Be careful about GitHub Pages subdirectory hosting.

The app may initially be deployed at:

https://USERNAME.github.io/bookify/

All paths must work under /bookify/.

Do not hardcode root-relative paths that assume /.

Use Vite's configured base path.


31. GitHub Pages

Deployment must work through GitHub Actions.

A push to:

main

should:

  1. install dependencies,
  2. run lint,
  3. run unit tests,
  4. build production assets,
  5. deploy dist/ to GitHub Pages.

README should document:

Settings
-> Pages
-> GitHub Actions

where applicable.


32. Service Worker

The service worker should cache the application shell.

At minimum:

index.html
JS bundles
CSS
icons
manifest

Saved article HTML lives in IndexedDB rather than requiring service-worker URL caching.

The installed application should launch while offline.


33. Offline Acceptance Test

This flow must work:

1. User opens Bookify online.
2. User saves an article.
3. User reads several pages.
4. User closes Bookify.
5. Device is put into airplane mode.
6. User launches Bookify from Home Screen.
7. Saved article appears.
8. User opens it.
9. Reader resumes near the previous location.
10. User continues reading.

34. Reading Progress

Calculate progress semantically rather than simply:

current page / total pages

when practical.

The page count changes with typography.

Store normalized text progress:

character offset / total normalized characters

or equivalent.

The UI may display:

36 / 129

for the current layout while the library displays:

28%

for persistent progress.


35. Deduplication

When importing an article whose canonical URL already exists:

Default behavior:

Update saved article

while preserving:

  • reading position,
  • annotations,
  • date first saved.

If new text is substantially different, preserve old annotations as best possible via quote anchors.

A sophisticated diff engine is not required for v1.


36. Highlights and Notes

Design the schema now but implementation may be milestone 2.

Suggested representation:

interface Annotation {
    id: string;
    articleId: string;

    type:
        | "highlight"
        | "bookmark"
        | "note";

    quote: TextQuoteSelector;

    note?: string;

    createdAt: number;
    updatedAt: number;
}

Use quote selectors rather than DOM XPath-only anchors.


37. Search

Milestone 2 feature.

Search locally across:

title
domain
plain article text
notes

No backend required.


38. Export

Future-friendly design.

Eventually support:

Markdown
HTML
EPUB
JSON backup

For v1, provide at minimum:

Export Library JSON
Import Library JSON

This gives the user a backup mechanism before cloud sync exists.


39. No Backend in V1

The production PWA must be a fully static GitHub Pages deployment.

Do not add:

Node server
Django
Firebase
Supabase
Cloudflare Workers
AWS
database server
login/authentication

for v1.

All state is local.

The application architecture should make later sync possible.


40. Future Sync Interface

Create an abstraction such as:

interface SyncProvider {
    push(...): Promise<void>;
    pull(...): Promise<void>;
}

but implement:

LocalOnlySyncProvider

for now.

Do not prematurely implement network synchronization.


41. Safari Extension Future Compatibility

The bookmarklet extractor/import protocol must be separated from UI code so a future Safari Web Extension can do:

rendered webpage
     |
extension content script
     |
Bookify import payload
     |
PWA/local database

without changing article storage or reader behavior.


42. Accessibility

Use real buttons.

Controls must include appropriate:

aria-label

values.

Respect system text rendering.

Use adequate contrast in:

light
dark

themes.

Do not make essential functionality gesture-only.

The explicit page-turn buttons should have large touch targets.


43. Performance

Target smooth operation on long technical articles.

Do not rerun expensive full-document calculations on every touch event.

Debounce:

resize
orientation changes
font changes

Repagination should generally complete within a fraction of a second for ordinary articles.

Articles containing very large DOM trees should remain usable.


44. Browser Behavior

Do not prevent ordinary horizontal touch interaction inside:

tables
code scrollers
images/viewers

Do not globally intercept touch events except where strictly necessary.

The reader page itself should not use swipe navigation.


45. Required Regression Tests

Create test fixtures covering:

Basic prose

Multiple paragraphs/headings.

Code

Long code block.

Wide table

Table wider than viewport.

Verify horizontal scrolling does not turn page.

Dark mode

Verify:

body text visible
code visible
caption visible
links visible

Images

Large image and caption.

Rotation

Repaginate and restore semantic position.

Font resize

Increase/decrease font while staying at approximately same sentence.

Persistence

Close/open article and restore position.

Offline

Open stored content with network disabled.

Unicode

Article text may contain Unicode.

Bookmarklet itself must remain ASCII-safe.


46. End-to-End Test Page

Include a local development fixture:

/test-article.html

containing:

  • 20+ paragraphs,
  • h1/h2/h3,
  • long code,
  • wide table,
  • image,
  • links,
  • inline code,
  • blockquote,
  • list,
  • Unicode punctuation.

Use it for automated browser testing.


47. README Requirements

README should include:

What Bookify is

Short explanation.

Development

npm install
npm run dev

Test

npm test
npm run test:e2e

Build

npm run build

GitHub Pages deployment

Exact steps.

Installing the PWA on iOS

Safari
Share
Add to Home Screen

Installing the bookmarklet

Exact instructions.

Architecture

Diagram explaining:

Bookmarklet -> Import Protocol -> PWA -> IndexedDB

Limitations

Explain that a PWA cannot directly inspect arbitrary Safari tabs and that the bookmarklet currently performs capture.


48. Development Milestones

Milestone 1 — Scaffold

Implement:

  • Vite/TypeScript app,
  • GitHub Pages configuration,
  • manifest,
  • service worker,
  • installable PWA shell,
  • basic README.

Acceptance:

npm run build

works and app deploys to GitHub Pages.

Commit:

milestone-1-pwa-scaffold

Milestone 2 — IndexedDB Library

Implement:

  • database schema,
  • articles,
  • positions,
  • preferences,
  • sample article import,
  • library screen.

Acceptance:

Saved sample articles survive browser reload.

Commit:

milestone-2-local-library

Milestone 3 — Pagination Engine

Implement:

  • CSS columns,
  • page count,
  • previous/next buttons,
  • reader chrome,
  • font resizing,
  • light/dark mode.

Explicit requirement:

NO SWIPE PAGE TURNING
NO TAP-EDGE PAGE TURNING

Acceptance:

Only the page buttons change pages.

Commit:

milestone-3-reader-pagination

Milestone 4 — Technical Content

Implement proper handling for:

  • code,
  • inline code,
  • tables,
  • figures,
  • captions,
  • links,
  • SVG,
  • dark mode.

Acceptance:

Wide table can be finger-scrolled left/right without page navigation.

Commit:

milestone-4-technical-content

Milestone 5 — Semantic Positioning

Implement:

  • normalized article text,
  • quote anchors,
  • position persistence,
  • repagination restoration.

Acceptance:

User opens an article, navigates into it, enlarges font, rotates device, closes/reopens article, and returns to approximately the same sentence.

Commit:

milestone-5-semantic-position

Milestone 6 — Bookmarklet Read Here

Implement:

  • article extraction,
  • current-page overlay reader,
  • ASCII-safe build,
  • explicit page buttons,
  • table scrolling.

Acceptance:

Bookmarklet works on the Deep Learning with Python chapter and does not produce mojibake.

Commit:

milestone-6-bookmarklet-reader

Milestone 7 — Save to Bookify

Implement:

  • import protocol,
  • bookmarklet article extraction,
  • PWA import receiver,
  • postMessage handshake,
  • origin verification,
  • fallback clipboard import.

Acceptance:

User can invoke bookmarklet on an external page and add the article to Bookify.

Commit:

milestone-7-bookmarklet-import

Milestone 8 — Offline

Implement:

  • app shell caching,
  • reliable offline startup,
  • saved article availability offline.

Acceptance:

Complete airplane-mode test succeeds.

Commit:

milestone-8-offline

Milestone 9 — TOC and Polish

Implement:

  • generated TOC,
  • progress display,
  • recently-read ordering,
  • delete confirmation,
  • open original link,
  • responsive iPhone/iPad layout.

Commit:

milestone-9-reader-polish

Milestone 10 — Tests and Documentation

Implement:

  • Vitest unit tests,
  • Playwright E2E tests,
  • fixture article,
  • GitHub Actions test/build/deploy,
  • complete README.

Commit:

milestone-10-release

49. Definition of Done for V1

V1 is complete when the following works on an iPhone:

1. Visit Bookify on GitHub Pages.
2. Add Bookify to Home Screen.
3. Install Bookify bookmarklet.
4. Visit a long technical webpage in Safari.
5. Invoke Bookify.
6. Choose Save to Bookify.
7. Article appears in Bookify library.
8. Open article.
9. Article is ebook-paginated.
10. Press > to advance one page.
11. Swipe article horizontally: page does NOT change.
12. Swipe a wide table horizontally: table scrolls.
13. Increase font size: approximately same sentence remains visible.
14. Close Bookify.
15. Reopen Bookify.
16. Article resumes near same sentence.
17. Put device into airplane mode.
18. Reopen Bookify.
19. Saved article remains readable.

50. Explicit Non-Goals for V1

Do not implement:

  • cloud accounts,
  • server database,
  • subscription/billing,
  • AI summarization,
  • social features,
  • automatic web crawling,
  • paywall bypass,
  • Safari native extension,
  • App Store application,
  • Android share target,
  • multi-user collaboration.

Keep v1 focused.


51. Design Direction

Bookify should feel like:

ebook reader
+
read-it-later application
+
browser reader mode

not like a conventional website.

Design characteristics:

  • restrained,
  • typography-first,
  • large reading area,
  • minimal chrome,
  • excellent dark mode,
  • no distracting animations,
  • no card-heavy dashboard aesthetic,
  • no unnecessary gradients,
  • no excessive icons.

The article content should dominate the experience.


52. Engineering Guidelines

Use small modules and explicit interfaces.

Avoid a single massive reader script.

Separate:

article extraction
article sanitization
storage
pagination
position tracking
UI
bookmarklet transport

Maintain strict TypeScript types.

Do not silently swallow failures.

Provide useful development logging behind a debug flag.

Production UI should show meaningful errors such as:

Bookify couldn't identify the main article on this page.

or:

The article was copied. Open Bookify and choose Import from Clipboard.

53. Implementation Philosophy

Prefer simple browser primitives over recreating browser functionality.

Examples:

Use:

CSS columns

rather than writing a custom line-layout engine.

Use:

IndexedDB

rather than inventing storage.

Use:

service worker

rather than requiring a server.

Use:

semantic text anchors

rather than treating page numbers as permanent identifiers.

The browser is already an excellent HTML typesetter. Bookify should provide the missing:

pagination
navigation
persistence
library
offline layer

around it.


54. Initial Coding-Agent Instruction

Implement this specification incrementally.

Work milestone-by-milestone in the order given.

For each milestone:

  1. inspect the existing repository before modifying anything;
  2. make the smallest coherent implementation satisfying that milestone;
  3. run applicable tests;
  4. fix failures before proceeding;
  5. update README.md when behavior or setup changes;
  6. commit the milestone using a descriptive commit message;
  7. do not move to the next milestone until the current milestone builds successfully.

Do not collapse the project into one large implementation pass.

Maintain working software at every milestone.

If an architectural decision differs from this specification because of a demonstrated browser limitation, document:

the limitation,
the alternatives considered,
the implemented workaround

in:

docs/architecture-decisions.md

The highest-priority behavioral requirements are:

- Bookify must work as a static GitHub Pages PWA.
- Saved articles must work offline.
- Reading position must survive repagination.
- Page turns must occur only from explicit page-turn buttons.
- Horizontal table scrolling must never change the ebook page.
- The bookmarklet must remain ASCII-safe.
- Imported pages must not execute source JavaScript.
- The storage/import format must remain independent of the capture mechanism.

Build a functional product, not merely a visual mockup.