DEV Community

Cover image for I Built a Free Unicode Font Generator with Zero Server Costs — Here is How
biwu he
biwu he

Posted on • Originally published at fontgeneratorfree.online

I Built a Free Unicode Font Generator with Zero Server Costs — Here is How

Have you ever wanted to generate fancy text for your Instagram bio, Twitter handle, or TikTok username? There are tons of font generator websites out there, but most of them either:

  • 📵 Require signup
  • 💰 Charge for basic features
  • 🐢 Run slow on free hosting
  • 📱 Don't work well on mobile

So I built Font Generator Free — a completely free, no-signup-required Unicode font generator that works seamlessly on all devices.

In this post, I'll walk you through the tech stack, key challenges, and how you can build something similar.

The Problem

I wanted to create stylish text for my social media profiles. Most tools I found had one of these issues:

  • Limited font styles (maybe 5-10)
  • Required account creation
  • Watermarks on exports
  • Slow or buggy
  • No batch conversion

I figured: how hard can it be? Let me build one myself.

The Solution

![Font Generator Interface]

Key Features

  • 30+ Font Styles — Bold, Italic, Bubble, Gothic, Cursive, Zalgo, and more
  • Two Modes — Single text or batch conversion
  • Multiple Export Formats — TXT, HTML, ZIP, PNG, PDF
  • Pro Features — Unlimited saved combos, cloud sync, history
  • Zero Cost — Totally free to run

Tech Stack

Here's what makes this all possible without paying for servers:

Frontend

  • Pure HTML + JavaScript (no framework overhead)
  • Tailwind CSS via CDN (fast prototyping)
  • JSZip for client-side ZIP generation
  • html-to-image for PNG exports

Backend

  • Cloudflare Workers — Serverless edge functions
  • Cloudflare D1 — SQLite database (100MB free)
  • Cloudflare Pages — Static site hosting (free)

Total monthly cost: $0 ☁️

How It Works

1. Unicode Font Mapping

The core of a font generator is Unicode character mapping. Each "font" is actually a different Unicode block:

Regular:    ABCDEFGHIJKLMNOPQRSTUVWXYZ
Bold:      𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙
Bubble:    ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏ
Gothic:    𝔄𝔅𝔇𝔈𝔉𝔊𝔋𝔌𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔕𝔖𝔗𝔘𝔙𝔚𝔛𝔜𝔷
Enter fullscreen mode Exit fullscreen mode

Here's a simplified version of how I map characters:

const boldMap = {
  'A': '𝐀', 'B': '𝐁', 'C': '𝐂', // ... all A-Z, a-z, 0-9
};

function convertToBold(text) {
  return text.split('').map(char => boldMap[char] || char).join('');
}
Enter fullscreen mode Exit fullscreen mode

2. Batch Mode with Client-Side Processing

For batch conversion, I process everything in the browser:

function batchConvert(texts, fonts) {
  const results = [];

  for (const text of texts) {
    for (const font of fonts) {
      results.push({
        source: text,
        font: font.name,
        output: font.convert(text)
      });
    }
  }

  return results;
}
Enter fullscreen mode Exit fullscreen mode

This keeps the backend simple — it only needs to handle user authentication and saving combos.

3. Cloudflare Workers API

The backend is a simple Worker handling user authentication and data storage:

export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (url.pathname === '/api/combo/save') {
      // Save user's font combo to D1
      const { google_sub, name, fonts } = await request.json();
      await env.DB.prepare(
        `INSERT INTO font_combos (google_sub, name, fonts) VALUES (?, ?, ?)`
      ).bind(google_sub, name, JSON.stringify(fonts)).run();

      return new Response(JSON.stringify({ success: true }));
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

4. PayPal Integration

For Pro subscriptions, I integrated PayPal. The key part is webhook signature verification to prevent fake payments:

async function verifyWebhookSignature(request, env) {
  // Extract PayPal headers
  const transmissionId = request.headers.get('PAYPAL-TRANSMISSION-ID');
  const certUrl = request.headers.get('PAYPAL-CERT-URL');
  const signature = request.headers.get('PAYPAL-TRANSMISSION-SIG');

  // Verify certificate comes from PayPal
  if (!certUrl.endsWith('.paypal.com')) {
    return { valid: false };
  }

  // Download cert and verify RSA signature
  // ... signature verification logic

  return { valid: true };
}
Enter fullscreen mode Exit fullscreen mode

Challenges & Solutions

Challenge 1: Unicode Ranges

Some Unicode blocks aren't continuous! For example, Mathematical Bold Italic:

// Wrong: Assumes continuous range
const start = 0x1D400;
const boldItalic = {};
for (let i = 0; i < 26; i++) {
  boldItalic[base[i]] = String.fromCodePoint(start + i); // ❌ Wrong codes!
}
Enter fullscreen mode Exit fullscreen mode

Solution: Manually verify each character's code point. I had to fix several fonts that were using incorrect ranges.

Challenge 2: Composite Characters

Fonts like "Dot" use combining characters (like i + combining dot):

// Wrong: Array.from splits the composite character
Array.from('ȧḃċḋ'); // ['a', '̇', 'b', '̇', ...] ❌

// Correct: Build manually
const dotMap = {};
for (const char of 'abcdefghijklmnopqrstuvwxyz') {
  dotMap[char] = char + '\u0307'; // Add combining dot
}
Enter fullscreen mode Exit fullscreen mode

Challenge 3: Monthly Renewal Logic

When a user renews their monthly subscription, I needed to extend from their current expiry date (not reset to 30 days):

async function calculateExpiry(env, googleId, planType, now) {
  if (planType === 'lifetime') return null; // Never expires

  const user = await env.DB.prepare(
    'SELECT subscription_expires_at FROM users WHERE google_id = ?'
  ).bind(googleId).first();

  if (user?.subscription_expires_at > now) {
    // Extend from current expiry (don't lose remaining days)
    return user.subscription_expires_at + 30 * 24 * 3600;
  }

  // Start fresh
  return now + 30 * 24 * 3600;
}
Enter fullscreen mode Exit fullscreen mode

Deployment

The deployment is surprisingly simple:

  1. Cloudflare Pages — Connects to GitHub, auto-deploys on push
  2. Cloudflare Workerswrangler deploy pushes the API
  3. Cloudflare D1 — Creates database with one command
# Deploy worker
CLOUDFLARE_API_TOKEN=xxx npx wrangler deploy

# Create database
npx wrangler d1 create font-generator-db
Enter fullscreen mode Exit fullscreen mode

Results

After launching:

  • 📈 ~500 daily visitors in first week
  • 🔒 0 security incidents
  • 💰 $0 hosting costs
  • 😊 Users love the simplicity

What's Next

Potential improvements:

  • Add more Unicode blocks (Emoji, symbols)
  • Multi-language support
  • User-generated font presets
  • Social sharing features

Conclusion

You don't need expensive servers to build useful web tools. Modern edge platforms like Cloudflare Workers can handle quite a bit of traffic for free. The key is:

  1. Keep the frontend static and client-side
  2. Use edge functions for API logic
  3. Choose the right database for your use case

If you're building something similar, I'd love to hear about it. Feel free to ask questions in the comments!


Links:

Top comments (0)