HandWrite turns a clear photo of handwritten letters into a downloadable TrueType font. The app guides someone through uploading an alphabet sample, analyzes the photo with Gemini, traces the detected glyphs in the browser, and exports a .ttf file for review and download.
- Accepts phone photos, including common formats such as JPEG, PNG, WEBP, HEIC, and HEIF.
- Normalizes uploads to JPEG before analysis.
- Uses a stateless Next.js API route to ask Gemini for alphabet glyph locations.
- Generates the font in a Web Worker so tracing and OpenType serialization do not block the upload UI.
- Supports uppercase and lowercase glyph extraction when both are present.
- Shows a font preview only after a real
.ttfhas been generated.
- Next.js 16 App Router
- React 19
- TypeScript
- Tailwind CSS 4
- Bun
- Gemini API through
@google/genai opentype.jsfor font creationimagetracerjsfor raster-to-vector tracing
Install dependencies:
bun installCreate .env.local and add a Gemini API key:
GEMINI_API_KEY=your_api_key_hereFor production, configure Redis-backed upload limiting with either Upstash Redis or Vercel KV-compatible REST variables:
UPSTASH_REDIS_REST_URL=your_redis_rest_url
UPSTASH_REDIS_REST_TOKEN=your_redis_rest_tokenRun the development server:
bun run devOpen http://localhost:3000.
bun run dev # Start the local development server
bun run build # Create a production build
bun run start # Start the production server
bun run lint # Run ESLint
bun run test # Run Bun tests with the project test setupsrc/app/
page.tsx Home page
upload/ Upload, analysis, generation, and review UI
api/extract/analyze/ Stateless Gemini analysis route
src/lib/extraction/ Gemini response schemas and extraction constants
src/lib/font/ Glyph tracing, font generation, and worker code
src/lib/images/ Upload normalization helpers
src/lib/server/ Server-only environment helpers
src/test/ Test setup
- The user uploads a photo of handwritten alphabet samples.
- The browser checks the file type and size, then normalizes the image to JPEG.
- The
/api/extract/analyzeroute sends the image bytes to Gemini. - Gemini returns structured glyph detections validated by local schemas.
- The browser starts a Web Worker to clean glyph masks, trace paths, and build a
.ttf. - The UI displays the generated font preview and download action.
- The app does not persist uploads or generated fonts.
GEMINI_API_KEYstays on the server and is never exposed to browser code.- Production analysis uploads are capped at three valid photos per client IP.
- Font fidelity depends on the photo: clear lighting, dark ink, and separated letters produce better glyphs.
