Skip to content

wylie/dogeared

Repository files navigation

Dogeared

Dogeared exists to create a better place for readers.

It is built for people who love books, who want to track what they read, discover what’s next, and share those experiences with others.

Dogeared is not driven by ads, algorithms, or profit. It is free to use, supported by optional donations, and designed with a focus on simplicity, usefulness, and respect for its users.

We believe books are for everyone. No book should be hidden, restricted, or left behind because of trends, systems, or gatekeeping.

This is a space for readers, built and maintained with care, where the goal is not growth at all costs, but something better, a tool that stays useful, thoughtful, and true to the people who use it.

Vercel + Neon Data Structure

Dogeared now includes a Neon-ready schema for app-driven genre lists. The catalog layer is designed to persist normalized book metadata and source identifiers only. Avoid storing or re-serving full third-party payloads unless the provider terms explicitly allow it.

Files

  • db/neon-schema.sql: core tables + get_top_books_by_genre(...) ranking function.
  • src/lib/catalog.ts: catalog-source helpers for source mapping persistence.
  • src/lib/neon.ts: Vercel server runtime Neon client.
  • src/pages/api/activity/recent.ts: API route for recent user activity from Neon.
  • src/pages/api/profile/info.ts: API route for persisted profile metadata in Neon.
  • src/pages/api/lists/top.ts: API route for Top books by genre.

Environment Variables

Set this in local .env and in Vercel Project Settings:

  • DATABASE_URL: Neon pooled connection string.
  • GOOGLE_BOOKS_API_KEY: existing key for search/suggest routes.
  • BREVO_API_KEY: API key for Dogeared magic-link email delivery.
  • BREVO_FROM_EMAIL: verified sender email used for magic-link emails.
  • BREVO_FROM_NAME: optional sender name for magic-link emails.
  • APP_BASE_URL: production base URL used by scheduled monitoring workflow (store as GitHub secret).
  • ADMIN_USERNAMES: comma-separated usernames allowed to access /admin/data-health (default: wylie).

Quick Setup

  1. Create a Neon project and copy its pooled DATABASE_URL.
  2. Run db/neon-schema.sql in Neon SQL Editor.
  3. Add DATABASE_URL to Vercel.
  4. Deploy to Vercel.
  5. Query top list route:
    • /api/lists/top?genre=fantasy
    • Optional: limit (1-50), windowDays (1-3650)

Top List Strategy

get_top_books_by_genre(...) ranks titles from real user shelves:

  • reading weighted highest
  • finished weighted medium
  • want_to_read weighted baseline
  • plus unique reader count

Metadata Backfills

Recurring metadata maintenance is now centralized:

  • npm run backfill:report: outputs JSON coverage for book/author metadata and duplicate work-key groups.
  • npm run backfill:metadata: runs quality report, author bio/avatar backfills, synopsis backfill, genre backfill, then a final report.

Optional env controls:

  • BACKFILL_DRY_RUN=1: run without writes for author scripts.
  • BACKFILL_LIMIT=500: cap records processed per script (0 or unset = no cap).
  • BACKFILL_CONCURRENCY=4: worker concurrency for supported scripts.
  • METRICS_FACT_LIMIT=3000: max analytics fact rows included in live metrics payload.

GitHub Actions:

  • .github/workflows/metadata-backfills.yml runs weekly on Monday and supports manual dispatch.
  • Scheduled runs default to dry-run mode with a bounded limit.

QA + Monitoring

  • CI now includes smoke-level endpoint checks in tests/production-smoke.test.ts.
  • /api/health provides a lightweight health signal with DB status/latency.
  • .github/workflows/production-monitor.yml runs every 30 minutes and checks:
    • /api/health
    • /api/books/search
    • /api/lists/top
  • On failure, the monitor workflow creates or updates a Production monitor failure issue with a link to the failed run.

Auth State Preview (Local)

Client auth state is now centralized in src/lib/clientAuth.ts and used across navigation and shelf actions.

For local UI checks, you can force view mode per URL:

  • ?authView=logged-in
  • ?authView=logged-out
  • ?authView=live (or remove the param)

The override is stored in local storage (dogeared:auth-preview) so you can quickly refresh and compare authenticated vs unauthenticated views while building profile/privacy/follow flows.

Support Dogeared

If you find Dogeared useful and want to help it grow, this is a simple way to do that.

Buy Me a Coffee

About

Dogeared is a reader-focused app for tracking, discovering, and sharing books, built with no ads, no paywalls, and no agenda, just a better experience for people who love to read.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors