DEV Community

Joshua Kaplan
Joshua Kaplan

Posted on

From Browser to Serverless: How We Protected Our AI Font Generation IP (And You Should Too)

From Browser to Serverless: How We Protected Our AI Font Generation IP (And You Should Too)

When we built GLIPH—an AI-powered tool that converts sketches into production fonts—we faced every web app founder's nightmare: our most valuable code was completely exposed in the browser.

Anyone could open DevTools, dig through our JavaScript, and reverse-engineer 6 months of custom AI algorithms. 😱

Here's how we moved our core IP to serverless functions and why you should consider the same approach for your proprietary logic.

🔍 The Problem: Client-Side = Exposed Code

Our original architecture looked like this:

// All of this was visible in the browser 🤦‍♂️
class SmartFontGenerator {
  async processGlyphSheet(glyphs) {
    // Custom AI glyph detection algorithms
    const enhancedGlyphs = await this.analyzeGlyphs(glyphs);

    // Proprietary vectorization logic
    const vectorizedGlyphs = this.vectorizeWithAI(enhancedGlyphs);

    // Advanced font generation with smart kerning
    return this.generateFont(vectorizedGlyphs);
  }
}
Enter fullscreen mode Exit fullscreen mode

Even with obfuscation, a determined developer could:

  • Extract our AI models
  • Reverse-engineer our vectorization algorithms
  • Copy our font generation logic
  • Build a competing product in weeks

🛡️ The Solution: Serverless IP Protection

We moved our crown jewels to Netlify Functions:

// netlify/functions/font-generator.js
exports.handler = async (event, context) => {
  // API key protection
  if (event.headers['x-api-key'] !== process.env.GLIPH_FONT_SECRET) {
    return { statusCode: 401, body: 'Unauthorized' };
  }

  try {
    const { glyphs, metrics } = JSON.parse(event.body);

    // 🔒 All proprietary logic now runs server-side
    const fontBuffer = await generateSmartFont(glyphs, metrics);

    return {
      statusCode: 200,
      body: JSON.stringify({ 
        fontData: Buffer.from(fontBuffer).toString('base64')
      })
    };
  } catch (error) {
    return { statusCode: 500, body: 'Font generation failed' };
  }
};

// 🔒 Secret sauce hidden on server
async function generateSmartFont(glyphs, metrics) {
  // Custom AI algorithms safely tucked away
  // Complex vectorization logic protected
  // Advanced font generation secured
}
Enter fullscreen mode Exit fullscreen mode

🔄 The Migration Challenges

1. Browser APIs Don't Exist in Node.js

Our client-side code used Image, Canvas, and document:

// ❌ This breaks in serverless functions
const canvas = document.createElement('canvas');
const img = new Image();
img.onload = () => {
  ctx.drawImage(img, 0, 0);
  const imageData = ctx.getImageData(0, 0, width, height);
};
Enter fullscreen mode Exit fullscreen mode

Solution: Pre-process image data on client, send pixel arrays:

// ✅ Client-side preprocessing
const pixels = await dataUrlToPixels(glyph.dataUrl);
const glyphData = {
  ...glyph,
  pixels: Array.from(pixels) // Send raw pixel data
};

// Send to serverless function
fetch('/.netlify/functions/font-generator', {
  method: 'POST',
  headers: { 'x-api-key': process.env.REACT_APP_GLIPH_FONT_SECRET },
  body: JSON.stringify({ glyphs: [glyphData] })
});
Enter fullscreen mode Exit fullscreen mode

2. TypeScript → JavaScript Conversion

Our codebase was TypeScript. Serverless functions needed vanilla JS:

// Before: TypeScript with full type safety
interface GlyphImage {
  id: string;
  dataUrl: string;
  vectorized: boolean;
  svgPathData?: string;
}

class SmartFontGenerator {
  private fontMetrics: FontMetrics;

  async processGlyphSheet(glyphs: GlyphImage[]): Promise<EnhancedGlyph[]> {
    // Complex typed logic
  }
}
Enter fullscreen mode Exit fullscreen mode
// After: Plain JavaScript for serverless
class SmartFontGenerator {
  constructor() {
    this.fontMetrics = {};
  }

  async processGlyphSheet(glyphs) {
    // Same logic, no types
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Dependencies Management

Created netlify/functions/package.json:

{
  "dependencies": {
    "opentype.js": "^1.3.3",
    "buffer": "^6.0.3"
  }
}
Enter fullscreen mode Exit fullscreen mode

📊 The Results

Before (Client-Side):

  • ❌ IP completely exposed
  • ❌ Large bundle sizes (AI models + logic)
  • ❌ Performance varies by device

After (Serverless):

  • ✅ IP protected behind API keys
  • ✅ Lighter client bundles
  • ✅ Consistent server performance
  • ✅ Easier to update algorithms
  • ✅ Built-in scaling

💰 The Business Impact

GLIPH processes font generation requests at $5/month per user. Our core IP is now:

  • Protected from reverse engineering
  • Centrally maintained and updatable
  • Scalable without client-side limitations

🛠️ When Should You Consider This?

Move logic to serverless when:

  • Your algorithms are your competitive advantage
  • You have complex AI/ML models
  • Processing is computationally intensive
  • You need consistent performance across devices
  • IP protection is business-critical

🔗 Want to See It In Action?

Check out GLIPH at [Gliph.us] - transform sketches into fonts using our protected AI pipeline.

Questions about serverless IP protection? Drop them below! 👇


Tags: #serverless #netlify #typescript #javascript #ip #startup #ai

Top comments (0)