Typography
We use system fonts to feel native on each platform, with a special exception for book titles which use a serif font to create a distinctly "bookish" feel.
Font Families
- iOS: SF Pro / system default
- Android: Roboto / system default
- Web: System stack (e.g.,
-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif) - Book Titles: Merriweather (serif via Google Fonts)
Sizes (mobile)
- H1 – Screen Title: 24–26 pt, semi-bold
- H2 – Section Header: 20 pt, semi-bold
- Body: 16 pt, regular
- Caption / Meta: 13–14 pt, regular
Line Height
- Body and captions: 1.4–1.6 line height for comfortable reading.
General Guidelines
- Screen titles should be clear but not huge; no giant hero text.
- Use H2 sparingly to mark sections; avoid over-nesting headings.
- Prefer normal sentence case over ALL CAPS.
AppTypography System (Flutter)
The AppTypography class in lib/config/theme.dart defines a complete typography hierarchy for the BookWish app. This system creates visual distinction between content (text displayed within cards/tiles) and container (navigation, empty states, and other UI chrome).
Content vs. Container Typography Philosophy
BookWish uses a dual-font approach that creates a warm, bookish atmosphere:
- Content (displayed in cards, tiles, and containers with white backgrounds): Uses serif fonts (Merriweather) to feel literary and cozy
- Container (navigation bars, empty states, buttons, page titles): Uses sans-serif fonts (system default) to feel native and functional
This distinction reinforces that cards contain the "story" (book content, social posts, reviews) while the surrounding UI is the functional "frame" that holds everything together.
Card/Tile Content Styles (Serif - Merriweather)
-
AppTypography.bookTitleLarge- 22pt, w700, for large book displays- Use in: Book info overlay headers, featured book cards
-
AppTypography.bookTitle- 17pt, w600, for standard book listings- Use in: Wishlist items, search results, general book tiles
-
AppTypography.bookTitleSmall- 15pt, w600, for compact book displays- Use in: Small book cards, inline book references
-
AppTypography.author- 14pt, w400, subtle (70% opacity)- Use in: Author names beneath book titles (all contexts)
-
AppTypography.cardHeading- 18pt, w600- Use in: Card titles (club names, challenge names, notification titles)
-
AppTypography.cardBody- 15pt, w400, line height 1.5- Use in: Card descriptions, review content, line content, notification body
-
AppTypography.cardBodySmall- 14pt, w400, line height 1.4- Use in: Secondary card text, member counts, participant counts
-
AppTypography.cardLabel- 14pt, w500- Use in: Card labels, badge text, price tags within cards
-
AppTypography.cardCaption- 12pt, w400, subtle (60% opacity)- Use in: Timestamps, metadata within cards
Container/UI Element Styles (Sans-serif - System Default)
-
AppTypography.headingLarge- 24pt, w600 -
AppTypography.heading- 20pt, w600- Use in: Page titles, section headers outside cards, dialog titles
-
AppTypography.label- 16pt, w500 -
AppTypography.labelSmall- 14pt, w500- Use in: Buttons, form labels, action text, navigation labels
-
AppTypography.body- 16pt, w400, line height 1.5 -
AppTypography.bodySmall- 14pt, w400, line height 1.4- Use in: Empty state messages, error messages, helper text, snackbars
-
AppTypography.caption- 12pt, w400, subtle (60% opacity)- Use in: Metadata outside cards, helper text
Usage Guidelines
-
Identify the context - Is the text inside a card/tile (white background, rounded corners, shadow)? Use serif (
card*styles). Is it outside? Use sans-serif. -
Cards and tiles always use serif - All text content within cards, tiles, list items with card styling should use the
card*typography variants. -
Container UI always uses sans-serif - App bars, navigation, empty states, buttons, snackbars, dialogs should use sans-serif styles.
-
Book titles are always serif - Regardless of context, book titles and authors always use
bookTitlevariants andauthorstyle. -
Don't mix within the same surface - A single card should use all serif text; navigation bar should use all sans-serif text.
Example Usage
// Inside a ClubCard (white background, rounded corners)
Text(
club.name,
style: AppTypography.cardHeading, // Serif
)
Text(
club.description,
style: AppTypography.cardBody, // Serif
)
Text(
'${club.memberCount} members',
style: AppTypography.cardBodySmall, // Serif
)
// Inside a BookListTile (white background)
Text(
book.title,
style: AppTypography.bookTitle, // Serif
)
Text(
book.authors.join(', '),
style: AppTypography.author, // Serif
)
// Empty state (not in a card)
Text(
'No clubs yet',
style: AppTypography.heading, // Sans-serif
)
Text(
'Join a book club to read with others.',
style: AppTypography.body, // Sans-serif
)
// Button label (container UI)
Text(
'Add to Wishlist',
style: AppTypography.label, // Sans-serif
)