Building a Terminal Header Generator with Cloudflare Workers
How I built a customizable terminal-style banner generator using Cloudflare Workers, SVG animations, and modern web technologies. Perfect for README files and project headers.
Introduction
As developers, we spend a lot of time creating README files for our projects. A visually appealing header can make your project stand out and create a memorable first impression. That's why I built Capsule Generator - a terminal-style header generator that creates beautiful, customizable SVG banners with animations.
Try it live: capsule-generator.akszt.dev
The Problem
Most GitHub README headers are either:
- Static images that require design tools and manual updates
- Generic badges that lack personality
- Complex setups requiring build tools and dependencies
I wanted something that was:
- ✅ Dynamic - Generate headers on-the-fly via URL parameters
- ✅ Beautiful - Modern terminal aesthetics with smooth animations
- ✅ Fast - Instant generation with global edge delivery
- ✅ Simple - Just paste a URL, no downloads or installations
Tech Stack
Cloudflare Workers
The entire application runs on Cloudflare's edge network, providing:
- Global distribution - Under 50ms response time worldwide
- Serverless architecture - No servers to manage
- Zero cold starts - Always ready to serve
- Free tier - 100,000 requests/day included
SVG + CSS Animations
I chose SVG for several reasons:
- Scalable - Looks perfect at any size
- Lightweight - Minimal file size (under 10KB)
- Animated - Native CSS animation support
- Embeddable - Works in Markdown, HTML, and web pages
Vanilla JavaScript
No frameworks needed! The UI uses:
- Native Web APIs - Fetch, FormData, URLSearchParams
- CSS Grid & Flexbox - Modern responsive layouts
- Custom Properties - Easy theming
- Real-time preview - Debounced updates
Key Features
1. Multiple Color Themes
I designed 5 distinct terminal-inspired themes:
const colorSchemes = {
'modern-gradient': {
primary: '#0d1421', // Deep terminal black
accent: '#00ff88', // Classic green terminal
wave: '#334155' // Subtle wave overlay
},
'neon-blue': {
primary: '#0a0e27',
accent: '#00d9ff', // Cyber blue glow
wave: '#1e40af'
},
'cyberpunk': {
primary: '#0c0c0c',
accent: '#ff0080', // Pink neon
text: '#00ff41' // Matrix green
},
// ... more themes
}2. Smooth Wave Animations
The transparent wave effect creates depth without overwhelming the text:
const waveStartY = svgHeight * 0.7; // Waves start at 70% height
// Three layers of waves with different speeds
@keyframes wave1 {
0%, 100% { /* Wave peak */ }
50% { /* Wave trough */ }
}
.wave1 { animation: wave1 6s ease-in-out infinite; }
.wave2 { animation: wave2 4.5s ease-in-out infinite; }
.wave3 { animation: wave3 3s ease-in-out infinite; }Each wave layer has:
- Different frequencies - Creates natural motion
- Gradient opacity - Fades from 15% to 0% transparency
- Synchronized timing - Smooth continuous animation
3. Dynamic Text Effects
Multiple animation styles to match your project's vibe:
Wave Effect - Animated background waves
animation: 'wave'Terminal Glow - Pulsing neon glow around text
@keyframes textGlow {
0%, 100% { filter: drop-shadow(0 0 15px #00ff88); }
50% { filter: drop-shadow(0 0 35px #00ff88); }
}Typing Cursor - Simulates live terminal input
<rect class="cursor" /> // Blinking cursorFloat Effect - Text gently floats up and down
@keyframes float {
0%, 100% { transform: translateY(0px); }
50% { transform: translateY(-8px); }
}4. Customizable Positioning
Full control over text placement with percentage-based positioning:
const titleX = url.searchParams.get('titleX') || '50'; // Center by default
const titleY = url.searchParams.get('titleY') || '35';
<g transform="translate(${titleX * 1200 / 100}, ${titleY * svgHeight / 100})">
<text class="main-text">${name}</text>
</g>5. Real-time Preview
The form updates the preview as you type using debounced API calls:
// Auto-update preview on input
const inputs = document.querySelectorAll('input, select');
inputs.forEach(input => {
input.addEventListener('input', debounce(updatePreview, 300));
});
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
}How It Works
Request Flow
- User visits
capsule-generator.akszt.dev - Worker serves HTML form (no name parameter)
- User customizes settings and clicks generate
- Form builds URL with all parameters:
?name=Akshat+Mehta &desc=Full+Stack+Developer &color=neon-blue &animation=wave &height=300 &fontSize=80 - Worker generates SVG dynamically
- Preview updates in real-time
- Copy embed code to use anywhere
URL Parameters
All customization happens via query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
name | string | required | Main title text |
desc | string | optional | Subtitle/description |
color | string | modern-gradient | Theme name |
animation | string | wave | Animation type |
height | number | 300 | SVG height in pixels |
fontSize | number | 80 | Title font size |
descFontSize | number | 32 | Description font size |
titleX | number | 50 | Title X position (%) |
titleY | number | 35 | Title Y position (%) |
descX | number | 50 | Description X position (%) |
descY | number | 55 | Description Y position (%) |
Example Usage
Basic Header:
Customized:
Result:
Performance Optimizations
1. Edge Caching
SVGs are cached globally with smart cache control:
return new Response(svg, {
headers: {
'Content-Type': 'image/svg+xml',
'Cache-Control': 'public, max-age=3600' // 1 hour cache
}
})2. Minimal Dependencies
Zero external dependencies:
- No npm packages
- No build step
- Pure JavaScript + SVG
- ~15KB total size
3. Efficient SVG Generation
Template strings for fast concatenation:
function generateTerminalSVG(params) {
return `<svg>...</svg>`; // Direct string return
}Design Decisions
Why Cloudflare Workers?
Pros:
- ✅ Global edge network (faster than traditional servers)
- ✅ No cold starts (unlike AWS Lambda)
- ✅ Simple deployment (
wrangler deploy) - ✅ Generous free tier
- ✅ Built-in CDN
Cons:
- ❌ 10ms CPU time limit (not an issue for SVG generation)
- ❌ No file system (not needed)
Why SVG Over Canvas?
SVG Advantages:
- Scalable at any resolution
- Native browser support
- CSS animatable
- Markdown compatible
- Small file size
- Accessible text
Canvas Limitations:
- Raster output (pixelated when scaled)
- Requires server-side rendering
- Larger file sizes
- No native animation
Why Vanilla JavaScript?
For this use case:
- No state management needed
- Simple DOM manipulation
- Smaller bundle size
- Faster load times
- No framework lock-in
Challenges & Solutions
Challenge 1: Transparent Wave Overlay
Problem: Waves covering the text made it unreadable
Solution:
- Used gradient opacity (15% → 0%)
- Positioned waves at 70% height
- Applied blur filters for smooth blending
<linearGradient id="waveGrad1">
<stop offset="0%" stop-opacity="0.15"/>
<stop offset="100%" stop-opacity="0"/>
</linearGradient>Challenge 2: Font Rendering
Problem: Custom fonts don't load in SVG
Solution:
- Used system monospace fonts with fallbacks
- Specified font stack in SVG styles
- Added font-weight for better rendering
font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Consolas', monospace;Challenge 3: Mobile Responsiveness
Problem: Fixed SVG dimensions didn't scale on mobile
Solution:
- Made preview container responsive
- Used
viewBoxfor SVG scaling - Added max-width CSS
.preview-svg {
max-width: 100%;
height: auto;
}Future Enhancements
Ideas for v2.0:
- Custom Fonts - Upload your own font files
- Image Backgrounds - Add logos or patterns
- Export to PNG - For platforms without SVG support
- Saved Presets - Save favorite configurations
- Batch Generation - Generate multiple headers
- API Endpoint - Programmatic access
- Analytics - Track popular themes and configs
Lessons Learned
1. Edge Computing is Powerful
Cloudflare Workers made deployment and scaling trivial. No servers, no DevOps, just deploy and forget.
2. SVG is Underrated
SVGs are perfect for dynamic graphics. The combination of XML structure and CSS styling is incredibly flexible.
3. URL Parameters > Config Files
For simple tools, URL parameters provide instant sharing and no database needed.
4. Real-time Preview Matters
Users expect immediate feedback. Debounced updates create a smooth experience without overwhelming the server.
5. Simplicity Wins
Vanilla JavaScript was the right choice. Sometimes the best framework is no framework.
Code Snippet: SVG Generation
Here's the core SVG generation logic:
function generateTerminalSVG(name, desc, colorScheme, fontSize, animation) {
const scheme = colorSchemes[colorScheme] || colorSchemes['modern-gradient'];
return `
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="300">
<defs>
<linearGradient id="bgGrad">
<stop offset="0%" stop-color="${scheme.primary}"/>
<stop offset="100%" stop-color="${scheme.secondary}"/>
</linearGradient>
<style>
.main-text {
font-family: 'JetBrains Mono', monospace;
fill: url(#textGrad);
${animation === 'glow' ? 'animation: textGlow 3s infinite;' : ''}
}
</style>
</defs>
<rect width="1200" height="300" fill="url(#bgGrad)"/>
<!-- Animated waves -->
<path class="wave1" fill="url(#waveGrad1)"/>
<!-- Text -->
<text x="50%" y="35%" class="main-text" font-size="${fontSize}">
${name}
</text>
${desc ? `<text x="50%" y="55%" class="desc-text">${desc}</text>` : ''}
</svg>`;
}Try It Yourself
- Visit capsule-generator.akszt.dev
- Enter your name and description
- Choose a theme and animation
- Adjust positioning and sizing
- Copy the generated URL
- Paste in your README.md!
Open Source
The project is deployed on Cloudflare Workers and serves thousands of requests daily. Feel free to use it in your projects!
Live Demo: capsule-generator.akszt.dev
Conclusion
Building the Terminal Header Generator was a fun exercise in edge computing and SVG manipulation. It showcases how modern web technologies enable powerful tools with minimal complexity.
Key takeaways:
- Edge computing reduces latency and simplifies deployment
- SVG animations create engaging visuals with tiny file sizes
- URL parameters enable instant sharing and configuration
- Vanilla JavaScript is often all you need
Whether you're building a personal project or a production tool, sometimes the best solution is the simplest one.
Have you tried creating your own terminal header? What features would you add? Let me know in the comments!
Built with ☕ and deployed on Cloudflare Workers