Overview
Track and display page views for storylines and individual plots. Display with eye icon across the app.
Database
New table: page_views
CREATE TABLE page_views (
id SERIAL PRIMARY KEY,
storyline_id INTEGER NOT NULL REFERENCES storylines(storyline_id),
plot_index INTEGER, -- NULL = storyline main page, 0 = genesis, 1+ = chapter
viewer_address TEXT, -- NULL for anonymous views
viewed_at TIMESTAMPTZ DEFAULT NOW(),
session_id TEXT -- fingerprint to dedupe within session
);
CREATE INDEX idx_page_views_storyline ON page_views(storyline_id);
CREATE INDEX idx_page_views_plot ON page_views(storyline_id, plot_index);
Add to storylines table (denormalized counter for fast reads):
ALTER TABLE storylines ADD COLUMN view_count INTEGER DEFAULT 0;
API routes
POST /api/views
- Body:
{ storylineId, plotIndex?, sessionId }
- Dedupe: max 1 view per session per page per hour
- Increment denormalized counter on storylines table
- No auth required (anonymous views allowed)
GET /api/views?storylineId=X
- Returns total view count for storyline
- Optionally per-plot breakdown
Display locations (with eye icon 👁)
- Home page story cards —
👁 1,234 (storyline total views)
- Story detail page header — next to plot count and rating
- Individual plot pages (Phase 9) — per-plot view count
- Writer dashboard — total views across all storylines
Client-side tracking
- Fire POST /api/views on page load (useEffect)
- Generate sessionId via fingerprint (e.g. hash of user-agent + screen size) or random UUID stored in sessionStorage
- Don't block rendering on view count API
Display format
- Eye icon + number:
👁 1,234
- Use SVG eye icon matching design system (not emoji)
- Compact format for large numbers: 1.2K, 12.3K, 1.2M
Dependency
Acceptance Criteria
Overview
Track and display page views for storylines and individual plots. Display with eye icon across the app.
Database
New table: page_views
Add to storylines table (denormalized counter for fast reads):
API routes
POST /api/views
{ storylineId, plotIndex?, sessionId }GET /api/views?storylineId=X
Display locations (with eye icon 👁)
👁 1,234(storyline total views)Client-side tracking
Display format
👁 1,234Dependency
Acceptance Criteria