Say It Now - Sessions 16 & 17

Fonts, Print Commerce, Limits & Admin

March 27, 2026

At a Glance

10
Commits
10
Font Options
4
New DB Tables/Migrations
12
Files Created
1

PDF Font Embedding

New

Registered 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.

Crimson Pro Serif
Lora Serif
EB Garamond Serif
Playfair Display Display
Inter Sans-Serif
Lato Sans-Serif
Open Sans Sans-Serif
Montserrat Sans-Serif

All fonts are Blurb/Lulu print-safe. Plus the two built-in options (Classic Serif, Clean Sans) for a total of 10.

2

Curated Font Picker

New

The 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.

Cover creator with font picker on Text tab
3

Print Cost Estimator

New

Book 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.

Full sizes page with estimator and order card
4

Print Order Flow

New

Next 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_orders table 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.

5

Admin Print Settings

Admin

Sheri 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.

Admin Print Settings and Print Orders sections
6

Share Link & Dashboard Polish

Fix

The 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.

Full dashboard with limits, share link, and navigation

Session 17 Additions

7

Contributor & Photo Limits

New

Book 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
8

Premium Hardcover + Spine Color

New

Premium 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.

9

Order Notifications

New

Two 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.

10

Admin Print Orders

Admin

New "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

FileChange
src/lib/pdf-fonts.tsNew -- Font registration for @react-pdf
src/lib/cover-design.tsFont metadata, bodyFont field, preview helpers
src/components/TributeBookPDF.tsxImport font registration, use bodyFont
src/components/CoverCreator.tsxFontPicker component, Google Fonts loading, tab URL param
src/components/CostEstimator.tsxNew -- Planning estimator with layout-aware page model
src/components/PrintOrderCard.tsxNew -- Order card with Stripe payment
src/pages/api/order-print.tsNew -- API route for print orders
src/pages/dashboard/[bookId].astroShare link fix, Change Fonts link
src/pages/dashboard/[bookId]/sizes.astroEstimator + order card rendering
src/pages/admin/index.astroPrint Settings section
supabase/migrations/...site_settings.sqlNew -- site_settings table
supabase/migrations/...print_orders.sqlNew -- print_orders table
Session 17
src/pages/api/check-limits.tsNew -- server-side limit enforcement
src/pages/b/[code].astroLimit check, dynamic photo cap, "book full" page
src/components/PrintOrderCard.tsxPremium hardcover, spine color picker, bookTier prop
src/lib/email.tsBook-full + print order notification functions
src/pages/api/stripe-webhook.tsPrint order payment completion handler
supabase/migrations/...spine_color.sqlNew -- spine_color on print_orders
supabase/migrations/...book_limits.sqlNew -- max_contributors + max_photos on books