Skip to content

Bismay-exe/nobadfonts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

140 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Banner

"Because Comic Sans deserves to stay in 2003."


TypeScript React Vite Tailwind CSS Supabase Capacitor GSAP License: MIT Live


πŸ”€ NoBadFonts is a next-generation, curated font discovery platform built for designers who demand quality, context, and performance β€” across web, Android, and iOS.


🌐 Visit the Site Β· πŸ“¦ Try the CLI Β· πŸ› Report a Bug


πŸ“– Table of Contents


🎯 What Is NoBadFonts?

The internet has a font problem. Too many fonts. Too little curation. Zero context.

You open Google Fonts, see 1,400+ options, type "Hello World" in a tiny box, and somehow have to make a decision that'll define your entire brand. That's broken.

NoBadFonts fixes this. It's a curated typography platform at nobadfonts.in where:

  • 🎨 Fonts are previewed the way they'll actually be used β€” in dashboards, editorial layouts, and code editors
  • πŸ€– Every font has a real, generated description β€” not "beautiful, modern, versatile" filler copy
  • ⚑ Uploads are optimized in your browser via WebAssembly WOFF2 conversion before hitting the server
  • πŸ“± The full experience works natively on Android and iOS via Capacitor
  • πŸ–₯️ Developers can install fonts directly from the terminal with the companion CLI

This isn't a font gallery. It's a complete typography toolchain for people who take type seriously.


✨ Features

πŸ”¬ Context-Aware Type Tester

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Preview Mode:  [ UI / Dashboard ]  [ Editorial ]  [ Code ]  β”‚
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Typography in context,                    β”‚
β”‚  β”‚  Dashboard  β”‚   not in a vacuum.                          β”‚
β”‚  β”‚  Widget     β”‚                                             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   No more guessing if Inter looks           β”‚
β”‚                    good in a tooltip. Just... see it.        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The FontTester.tsx component lets you preview fonts in three real-world contexts:

Mode Description
πŸ–₯️ UI / Dashboard Buttons, tooltips, tables β€” the full product-design context
πŸ“° Editorial Dense, multi-column text for readability testing
πŸ’» Code Monospace fonts in a syntax-highlighted block

⚑ Browser-Side WOFF2 Conversion

The upload pipeline (src/pages/Upload.tsx) is where things get serious. Before a font even leaves your browser:

User uploads .ttf / .otf
         β”‚
         β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Validation  β”‚  ← Checks metadata, file type, required fields
  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Fingerprint  β”‚  ← Generates unique slug (e.g. "helvetica-now-display")
  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  WASM WOFF2 Encoder  β”‚  ← Runs wawoff2 (Google's woff2 port) IN THE BROWSER
  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Upload Compressed WOFF2 to Supabase β”‚  ← Smaller. Faster. Better.
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βœ… Users upload raw fonts. Servers receive optimized WOFF2. The network and your end-users thank you.


🧠 Algorithmic Description Engine

No more "A beautiful, modern, versatile typeface" placeholder copy. The engine at src/utils/fontDescriptionGenerator.ts analyzes a font's actual tag set and synthesizes something real:

// Input
tags: ['sans', 'geometric', 'modern', 'bold']

// Output
"A geometric sans-serif with a modern character.
 Its bold weight makes it ideal for headlines and branding."

Each description is unique to the font's personality. Curated at scale.


🎭 Font Pairing Engine

Stop guessing which fonts go together. The pairing interface (src/pages/FontPairing.tsx) lets you:

  • Browse curated pairing recommendations
  • Customize heading + body combinations in a live preview
  • Filter by mood, category, and contrast style

πŸ—ΊοΈ Glyph Map

See every character a font supports β€” before you commit. The GlyphMap.tsx component renders the full Unicode coverage of any typeface, so you know if it handles your language, symbols, or edge cases.


πŸ“Š Designer Analytics Dashboard

Uploaders get a private AnalyticsDashboard.tsx showing:

  • Total views and downloads per font
  • Geographic breakdown of interest
  • Trending performance over time

πŸ“‹ Feature Status at a Glance

Feature Description Status
πŸ”¬ Context-Aware Type Tester Preview fonts in UI, Editorial & Code contexts βœ… Live
⚑ Browser WOFF2 Conversion WASM-powered TTF β†’ WOFF2 before upload βœ… Live
🧠 Algorithmic Description Engine Auto-generates font copy from metadata tags βœ… Live
🎭 Font Pairing Engine Smart heading + body pairing suggestions βœ… Live
πŸ—ΊοΈ Glyph Map Viewer Full Unicode coverage display βœ… Live
πŸ“Š Analytics Dashboard Views, downloads & geo stats per font βœ… Live
πŸ“± iOS & Android (Capacitor) Native mobile with shared codebase βœ… Live
πŸ–₯️ CLI Tool npx nobadfonts-cli add <font> βœ… Live
🌐 Edge-generated fonts.css Remote embedding via Supabase Edge Functions 🚧 Planned
πŸ€– AI Font Recommendations Personalized discovery via ML 🚧 Planned
πŸŽ›οΈ Variable Font Axis Controls Live weight/width sliders in the type tester 🚧 Planned
πŸŒ™ Dark Mode System-aware theme toggle 🚧 Planned

πŸ” Role-Based Access Control

Role Powers
πŸ‘€ member Upload fonts, manage their own library
πŸ›‘οΈ admin Global curation rights, publish/unpublish any font, run FixWoff2Scanner

Enforced at the database level via Supabase Row Level Security (RLS) β€” not just in the UI.



πŸ“Έ Screenshots

🌐 Live at nobadfonts.in β€” visit to see it in action.

🏠 Landing Page

Landing Page

πŸ”€ Font Catalog

Font Catalog

πŸ”€ Font Details

Font Details

πŸ”¬ Font Pairing

Font Pairing

πŸ”¬ NoBadFonts-cli

NoBadFonts-cli

πŸ“± Mobile View (Capacitor)

πŸ”€ Font Catalog
|

πŸ”€ Font Details

πŸ”¬ Font Pairing

πŸ”¬ NoBadFonts-cli

---

πŸ—ΊοΈ App Structure Diagram

A high-level map of every page and how they connect:

graph TD
  Home["🏠 Home (Landing)"] --> Catalog["πŸ“š Fonts Catalog"]
  Home --> Auth["πŸ” Auth (Login/Signup)"]
  Home --> Members["πŸ‘₯ Members Directory"]
  Home --> CLI["πŸ–₯️ CLI Docs Page"]

  Catalog --> FontDetails["πŸ”€ Font Details"]
  FontDetails --> TypeTester["πŸ”¬ Type Tester"]
  FontDetails --> GlyphMap["πŸ—ΊοΈ Glyph Map"]
  FontDetails --> Pairing["🎭 Font Pairing"]

  Auth --> Profile["πŸ‘€ Profile"]
  Auth --> Upload["⬆️ Upload Pipeline"]
  Auth --> AdminDash["πŸ›‘οΈ Admin Dashboard"]

  Profile --> Analytics["πŸ“Š Analytics Dashboard"]
  Profile --> FontGrid["πŸ–ΌοΈ Font Grid (My Uploads)"]

  Members --> MemberDetails["πŸ§‘ Member Detail Page"]
  MemberDetails --> DesignerFonts["🎨 Designer's Fonts"]

  Upload --> WASM["⚑ WASM WOFF2 Encoder"]
  WASM --> Supabase["☁️ Supabase Storage"]
Loading

πŸ—οΈ Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         NoBadFonts Platform                         β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚   Web App   β”‚    β”‚ Android App  β”‚    β”‚      iOS App         β”‚   β”‚
β”‚   β”‚  (Vite +    β”‚    β”‚ (Capacitor)  β”‚    β”‚   (Capacitor)        β”‚   β”‚
β”‚   β”‚   React 19) β”‚    β”‚              β”‚    β”‚                      β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚          β”‚                  β”‚                        β”‚              β”‚
β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                             β”‚ Shared React Codebase (99%)           β”‚
β”‚                             β–Ό                                       β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚   β”‚                   React 19 + TypeScript                   β”‚     β”‚
β”‚   β”‚                                                           β”‚     β”‚
β”‚   β”‚   AuthContext ──► Supabase Auth                           β”‚     β”‚
β”‚   β”‚   UploadContext ──► WASM WOFF2 Queue                      β”‚     β”‚
β”‚   β”‚   Lenis + GSAP ──► Scroll Animations                      β”‚     β”‚
β”‚   β”‚   Framer Motion ──► Micro-interactions                    β”‚     β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                           β”‚                                         β”‚
β”‚                           β–Ό                                         β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚   β”‚                  Supabase Backend                         β”‚     β”‚
β”‚   β”‚                                                           β”‚     β”‚
β”‚   β”‚   PostgreSQL ──► fonts, profiles, font_variants           β”‚     β”‚
β”‚   β”‚   Storage ──► Font files (.woff2, .ttf, .otf)             β”‚     β”‚
β”‚   β”‚   RLS Policies ──► Row-level auth enforcement             β”‚     β”‚
β”‚   β”‚   Edge Functions ──► (Future) fonts.css generation        β”‚     β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βš™οΈ Tech Stack

Frontend

Technology Version Role
React 19 RC Core UI framework
TypeScript 5.x Type safety across the entire codebase
Vite Latest Build tool β€” instant HMR, optimized bundles
Tailwind CSS v4 (Alpha) Styling β€” new engine, sub-ms compile times
Framer Motion Latest Layout animations, modal transitions
GSAP + Lenis Latest Smooth scroll parallax effects

Backend & Infrastructure

Technology Role
Supabase PostgreSQL + Auth + Storage + RLS
Vercel Web deployment + edge CDN
Capacitor iOS & Android native bridge

Unique Capabilities

Technology What It Does
wawoff2 (WASM) Converts TTF β†’ WOFF2 in the browser before upload
Algorithmic Desc. Engine Synthesizes font descriptions from metadata tags
Supabase RLS Database-level auth, not just UI-level

🎨 Color Palette

The NoBadFonts design system is built around a high-contrast, type-forward aesthetic:

Role Color Hex Used For
Background #0f0f0f #0f0f0f Page backgrounds
Surface #1a1a1a #1a1a1a Cards, modals
Primary Text #f5f5f5 #f5f5f5 Headlines, body copy
Accent #ffffff #ffffff CTAs, highlights
Muted #6b7280 #6b7280 Secondary text, tags
Success #3ecf8e #3ecf8e Published status, Supabase integration

πŸ’Ύ Database Schema

profiles

CREATE TABLE profiles (
  id         UUID PRIMARY KEY REFERENCES auth.users,
  username   TEXT UNIQUE NOT NULL,
  role       TEXT DEFAULT 'member' CHECK (role IN ('member', 'admin')),
  avatar_url TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

fonts

CREATE TABLE fonts (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  slug         TEXT UNIQUE NOT NULL,
  name         TEXT NOT NULL,
  user_id      UUID REFERENCES profiles(id),
  tags         TEXT[],
  category     TEXT,
  designer     TEXT,
  is_published BOOLEAN DEFAULT FALSE,
  created_at   TIMESTAMPTZ DEFAULT NOW()
);

font_variants

CREATE TABLE font_variants (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  font_id         UUID REFERENCES fonts(id) ON DELETE CASCADE,
  variant_name    TEXT NOT NULL,        -- e.g. "Bold Italic"
  woff2_url       TEXT,                 -- CDN link to compressed file
  ttf_url         TEXT,
  file_size_woff2 BIGINT,               -- For analytics
  created_at      TIMESTAMPTZ DEFAULT NOW()
);

RLS at a Glance

fonts table:
  βœ… Anyone can SELECT published fonts
  βœ… Authenticated users can INSERT their own fonts
  βœ… Users can UPDATE/DELETE only their own rows
  βœ… Admins have unrestricted access

πŸ“‚ Project Structure

nobadfonts/
β”‚
β”œβ”€β”€ πŸ“ .github/workflows/        # CI/CD pipelines
β”œβ”€β”€ πŸ“ android/                  # Capacitor Android project
β”œβ”€β”€ πŸ“ logo/                     # Brand assets
β”‚
β”œβ”€β”€ πŸ“ nobadfonts-cli/           # ← Standalone CLI package
β”‚   └── README.md
β”‚
β”œβ”€β”€ πŸ“ public/                   # Static assets
β”œβ”€β”€ πŸ“ scripts/                  # Utility scripts
β”œβ”€β”€ πŸ“ supabase/                 # DB migrations & edge functions
β”‚
└── πŸ“ src/
    β”‚
    β”œβ”€β”€ πŸ“ components/
    β”‚   β”œβ”€β”€ πŸ“ admin/
    β”‚   β”‚   └── FixWoff2Scanner.tsx    # Admin tool: scan & fix broken woff2 refs
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ font-pairing/
    β”‚   β”‚   β”œβ”€β”€ CustomizeSidebar.tsx   # Live font pair customizer
    β”‚   β”‚   └── FontPickerSidebar.tsx  # Browse & pick fonts for pairing
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ fonts/
    β”‚   β”‚   β”œβ”€β”€ ContextPreview.tsx     # UI / Editorial / Code preview modes
    β”‚   β”‚   β”œβ”€β”€ Filters.tsx            # Tag + category filtering
    β”‚   β”‚   β”œβ”€β”€ FontCard.tsx           # Card component in catalog grid
    β”‚   β”‚   β”œβ”€β”€ FontTester.tsx         # Interactive type tester
    β”‚   β”‚   β”œβ”€β”€ GlyphMap.tsx           # Full Unicode glyph coverage viewer
    β”‚   β”‚   β”œβ”€β”€ LicenseInfo.tsx        # License display
    β”‚   β”‚   β”œβ”€β”€ PreviewAccordion.tsx   # Expandable preview panel
    β”‚   β”‚   β”œβ”€β”€ ShareModal.tsx         # Share font link modal
    β”‚   β”‚   └── SocialShareCard.tsx    # OG card generator
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ home/
    β”‚   β”‚   β”œβ”€β”€ πŸ“ Hero/               # Hero section variants (1, 2, 4)
    β”‚   β”‚   β”œβ”€β”€ Land2.tsx ... Land8.tsx # Landing page sections
    β”‚   β”‚   └── Landing.tsx
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ layout/
    β”‚   β”‚   β”œβ”€β”€ Footer.tsx
    β”‚   β”‚   β”œβ”€β”€ Layout.tsx
    β”‚   β”‚   β”œβ”€β”€ Navbar.tsx
    β”‚   β”‚   └── ScrollRestoration.tsx
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ profile/
    β”‚   β”‚   β”œβ”€β”€ AnalyticsDashboard.tsx # Font performance stats
    β”‚   β”‚   β”œβ”€β”€ FontGrid.tsx           # Profile's uploaded fonts
    β”‚   β”‚   β”œβ”€β”€ ProfileHeader.tsx
    β”‚   β”‚   └── SettingsForm.tsx
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ shared/
    β”‚   β”‚   β”œβ”€β”€ EmptyState.tsx
    β”‚   β”‚   β”œβ”€β”€ ErrorBoundary.tsx
    β”‚   β”‚   └── SEO.tsx
    β”‚   β”‚
    β”‚   └── UploadProgressPopup.tsx    # Background upload progress indicator
    β”‚
    β”œβ”€β”€ πŸ“ contexts/
    β”‚   β”œβ”€β”€ AuthContext.tsx            # Supabase auth state: user, session, profile
    β”‚   └── UploadContext.tsx          # WOFF2 conversion queue management
    β”‚
    β”œβ”€β”€ πŸ“ hooks/
    β”‚   β”œβ”€β”€ useFont.ts                 # Single font data fetching
    β”‚   β”œβ”€β”€ useFonts.ts                # Catalog data fetching with filters
    β”‚   β”œβ”€β”€ useLenis.ts                # Smooth scroll β†’ GSAP ScrollTrigger bridge
    β”‚   β”œβ”€β”€ useMediaQuery.ts           # Responsive breakpoint detection
    β”‚   └── useViewMode.ts             # Grid vs list view toggle
    β”‚
    β”œβ”€β”€ πŸ“ pages/
    β”‚   β”œβ”€β”€ AdminDashboard.tsx         # Admin-only moderation panel
    β”‚   β”œβ”€β”€ Auth.tsx                   # Login / signup
    β”‚   β”œβ”€β”€ Cli.tsx                    # CLI documentation page
    β”‚   β”œβ”€β”€ DesignerFonts.tsx          # Fonts filtered by designer
    β”‚   β”œβ”€β”€ FontDetails.tsx            # Full font detail page
    β”‚   β”œβ”€β”€ FontPairing.tsx            # Pair fonts interactively
    β”‚   β”œβ”€β”€ FontsCatalog.tsx           # Main browsable catalog
    β”‚   β”œβ”€β”€ Home.tsx                   # Landing page
    β”‚   β”œβ”€β”€ MemberDetails.tsx          # Public profile view
    β”‚   β”œβ”€β”€ Members.tsx                # Community directory
    β”‚   β”œβ”€β”€ Profile.tsx                # Private user profile
    β”‚   └── Upload.tsx                 # Multi-stage upload pipeline
    β”‚
    β”œβ”€β”€ πŸ“ types/
    β”‚   β”œβ”€β”€ database.types.ts          # Supabase-generated DB types
    β”‚   └── font.ts                    # FontVariant, FontData interfaces
    β”‚
    β”œβ”€β”€ πŸ“ utils/
    β”‚   β”œβ”€β”€ fontDescriptionGenerator.ts # Algorithmic description synthesis
    β”‚   └── woff2.ts                    # WASM WOFF2 encoder wrapper
    β”‚
    β”œβ”€β”€ App.tsx
    β”œβ”€β”€ fonts.css                       # @font-face declarations
    β”œβ”€β”€ index.css
    └── main.tsx

πŸš€ Using NoBadFonts

NoBadFonts is a live product at nobadfonts.in. No setup needed β€” just open it in your browser.

What you want to do Where to go
πŸ”€ Browse & preview fonts nobadfonts.in/fonts
🎭 Pair fonts together nobadfonts.in/pairing
⬆️ Upload your typeface Create a free account, then hit Upload
πŸ–₯️ Use fonts in your project via CLI See CLI Companion below
πŸ“± Use on mobile Download the Android / iOS app

πŸ–₯️ Self-Hosting

The source code is open β€” if you want to run your own instance, here's how.

Prerequisites

Node.js  β‰₯ 20.x
npm      β‰₯ 10.x   (or pnpm)

Setup

# Install dependencies
npm install

# Configure environment
cp .env.example .env

Add your Supabase credentials to .env:

VITE_SUPABASE_URL=https://your-project-ref.supabase.co
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key

πŸ’‘ Get these from your Supabase Dashboard β†’ Project Settings β†’ API

# Start dev server
npm run dev
# β†’ http://localhost:5173

# Build for production
npm run build

πŸ“± Mobile (Capacitor)

NoBadFonts runs natively on Android and iOS using Capacitor. 99% of the codebase is shared.

Android

# Sync the web build into the native project
npx cap sync

# Open in Android Studio
npx cap open android

iOS

npx cap sync
npx cap open ios   # Requires macOS + Xcode

Native Plugins Used

Plugin Purpose
@capacitor/filesystem Read/write font files locally
@capacitor/haptics Tactile feedback on interactions

πŸ”Œ CLI Companion

For developers who prefer living in the terminal, NoBadFonts ships with a companion CLI.

# Install globally
npm install -g nobadfonts-cli

# Add a font to your project
npx nobadfonts-cli add inter

# List all available curated fonts
npx nobadfonts-cli list

# Search by category
npx nobadfonts-cli search --category="geometric-sans"

The CLI automatically downloads the WOFF2 file, injects the @font-face declaration into your fonts.css, and keeps everything organized.

πŸ“– Full docs: nobadfonts-cli/README.md


❓ FAQ

Q: Is NoBadFonts free to use?

Yes β€” browsing, previewing, and discovering fonts is completely free. Creating an account to upload your own typefaces is also free.

Q: What font formats can I upload?

.ttf, .otf, .woff, and .woff2 are all accepted. If you upload a .ttf or .otf, NoBadFonts automatically converts it to .woff2 in your browser before uploading β€” so your fonts load faster for everyone.

Q: Can I use the fonts I find here in commercial projects?

License information is shown on every font's detail page. Always check the specific font's license before using it in commercial work.

Q: How does the CLI work?

Install it with npm install -g nobadfonts-cli, then run npx nobadfonts-cli add <fontname>. It fetches the WOFF2, writes the @font-face rule into your CSS, and you're done in one command.

Q: Is there a mobile app?

Yes β€” NoBadFonts is available as a native Android and iOS app with the same full feature set as the website.

Q: I found a bug or have a feature idea. Where do I go?

Open an issue on GitHub Issues β€” all feedback is read and considered.


πŸ›£οΈ Roadmap

  • Context-aware type tester (UI / Editorial / Code modes)
  • Browser-side WOFF2 conversion with WASM
  • Algorithmic font description generator
  • Font pairing engine
  • Glyph map viewer
  • Capacitor mobile (Android + iOS)
  • CLI companion tool
  • Admin dashboard with curation tools
  • Supabase Edge Function β€” generate fonts.css for remote embedding
  • AI-powered font recommendation engine
  • Variable font axis controls in the type tester
  • Dark mode
  • Font collections / bookmarks

πŸ§‘β€πŸ€β€πŸ§‘ Contributors

Thanks to everyone who has contributed to NoBadFonts!

Want to see your avatar here? Check out the Contributing section and open a PR!


πŸ“„ License

Distributed under the MIT License. See LICENSE for full text.


Built with πŸ–€ by Bismay

nobadfonts.in β€” Stop using bad fonts.


Visit the site Star on GitHub

β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•
β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β•šβ•β•β•β•β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘     β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘
β•šβ•β•  β•šβ•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•      β•šβ•β•β•β•β•β• β•šβ•β•  β•šβ•β•β•β•   β•šβ•β•   β•šβ•β•β•β•β•β•β•