At a Glance
PDF Font Embedding
NewRegistered 8 Google Fonts with @react-pdf/renderer so they actually embed in downloaded PDFs. Previously, only built-in Times-Roman and Helvetica were available -- the browser preview showed nice fonts but the PDF didn't match.
Fonts load from Google's CDN (TTF format) on demand when a PDF is generated. No local font files to maintain.
All fonts are Blurb/Lulu print-safe. Plus the two built-in options (Classic Serif, Clean Sans) for a total of 10.
Curated Font Picker
NewThe cover creator's Text tab now has a full font picker with grouped Serif / Sans-Serif options. Each font previews in its own typeface. Three independent font controls:
- Title font -- for the cover title
- Subtitle font -- for the cover subtitle
- Interior pages font -- for contributor tributes and table of contents
Google Fonts are loaded dynamically in the browser for live preview. The "Change Fonts" link on the main dashboard goes directly to this tab.
Print Cost Estimator
NewBook owners can now plan their book's print cost before collecting tributes. The estimator models the actual PDF layout:
- Contributors -- how many people will submit
- Photos per person -- 3 fit per row at 150px
- Message length -- Short (~50 words), Medium (~150), Long (~300+)
- Cover type -- Softcover or Hardcover
- Interior -- Black & White or Full Color
The estimator shows estimated pages, print cost, plan credit applied, and the amount the owner would pay. This helps owners decide contributor and photo limits before sharing their book link.
Print Order Flow
NewNext to the planning estimator, the order card shows the real cost based on actual book data (real contributor count, real photo count). The business model:
- Each plan includes a print credit (default $20, admin-configurable)
- If the book costs less than the credit: order for $0
- If it exceeds the credit: pay the difference via Stripe
- Orders are recorded in a
print_orderstable for Sheri to fulfill manually
The estimator (left) and order card (right) live side by side on the book sizes page. The estimator is for planning; the order card uses real data.
Admin Print Settings
AdminSheri controls two settings from the admin dashboard that affect customer-facing pricing:
- Print Markup % -- margin applied on top of Lulu wholesale cost (default 40%)
- Print Credit $ -- amount included in each plan toward a printed copy (default $20)
Stored in a new site_settings table with RLS -- anyone can read, only admins can write.
Share Link & Dashboard Polish
FixThe share link on the book dashboard was getting truncated because the QR code and link were crammed side-by-side. Fixed by stacking vertically -- QR code + description above, full-width link below with a visible teal "Copy" button (was a barely-visible clipboard emoji).
Also renamed "Compare Sizes" to "Plan Your Book" (links to estimator + order page) and added "Change Fonts" next to "Design Cover." Change Fonts opens directly to the Text tab.
Session 17 Additions
Contributor & Photo Limits
NewBook owners can now set maximum contributors and maximum photos per contributor from the dashboard. Defaults: 25 contributors, 5 photos each.
- Server-side enforcement -- the contributor form checks limits via API before allowing submission
- "Book is full" page -- contributors who arrive after the limit see a clear message
- Owner notification -- when someone is turned away, the book owner gets an email so they can increase the limit if they want
Premium Hardcover + Spine Color
NewPremium tier books now get hardcover included. The order card pre-selects hardcover with an "included" badge. Non-premium tiers can still choose hardcover but pay full price.
Hardcover orders get a spine color picker: 6 preset colors (Midnight, Teal, Navy, Burgundy, Forest, Gold) plus a custom color input. Spine color is stored on the order for fulfillment.
Order Notifications
NewTwo new email notifications via Azure Communication Services:
- Print order notification -- Sheri gets an email with full order details (book, size, cover, interior, spine color, pages, pricing) when a print order is placed
- Book full notification -- book owner gets emailed when a contributor is turned away due to limits
Stripe webhook updated to handle print order payment completion and trigger the notification.
Admin Print Orders
AdminNew "Print Orders" section in the admin dashboard. Sheri can see all orders with book, cover type, interior, spine color swatch, pages, amount, and date. Status dropdown lets her update orders inline: pending, paid, processing, shipped, cancelled.
Book owners also see their order status on the dashboard with color-coded badges.
Files Changed
| File | Change |
|---|---|
src/lib/pdf-fonts.ts | New -- Font registration for @react-pdf |
src/lib/cover-design.ts | Font metadata, bodyFont field, preview helpers |
src/components/TributeBookPDF.tsx | Import font registration, use bodyFont |
src/components/CoverCreator.tsx | FontPicker component, Google Fonts loading, tab URL param |
src/components/CostEstimator.tsx | New -- Planning estimator with layout-aware page model |
src/components/PrintOrderCard.tsx | New -- Order card with Stripe payment |
src/pages/api/order-print.ts | New -- API route for print orders |
src/pages/dashboard/[bookId].astro | Share link fix, Change Fonts link |
src/pages/dashboard/[bookId]/sizes.astro | Estimator + order card rendering |
src/pages/admin/index.astro | Print Settings section |
supabase/migrations/...site_settings.sql | New -- site_settings table |
supabase/migrations/...print_orders.sql | New -- print_orders table |
| Session 17 | |
src/pages/api/check-limits.ts | New -- server-side limit enforcement |
src/pages/b/[code].astro | Limit check, dynamic photo cap, "book full" page |
src/components/PrintOrderCard.tsx | Premium hardcover, spine color picker, bookTier prop |
src/lib/email.ts | Book-full + print order notification functions |
src/pages/api/stripe-webhook.ts | Print order payment completion handler |
supabase/migrations/...spine_color.sql | New -- spine_color on print_orders |
supabase/migrations/...book_limits.sql | New -- max_contributors + max_photos on books |