Building Cronkiter: A Vintage Audio Transformer in Under 2 Hours
From Reddit inspiration to production: How AI coding tools are changing what "shipping fast" means
About Me: I'm a business and product executive with zero coding experience. I've spent my career building products by working with engineering teams at Amazon, Wondery, Fox, Rovi, and TV Guide, but never wrote production code myself. Until recently.
Frustrated with the pace of traditional development and inspired by the AI coding revolution, I decided to build my own projects using AI assistants (primarily Claude Code, Codex, and Cursor). This blog post is part of that journey—documenting what I've learned building real production systems as a complete beginner.
TL;DR
The Story: Saw a Reddit post asking ElevenLabs to add vintage radio effects to their TTS. Built Cronkiter, a free browser-based vintage audio transformer, in about 90 minutes using Claude Code.
Key Learnings:
- Web Audio API is surprisingly powerful—no FFmpeg needed for this
- Browser-based tools = zero backend, instant deployment
- First time using GoatCounter for privacy-friendly analytics
- Learned proper SEO meta tags, Open Graph, and social media validation
- Mobile UX matters: built responsive "desktop required" message
- Branding iteration: "Edward R. Mur-Wren" → "Cronkiter" (less birdy, more broadcast)
Tech Stack: Vanilla JavaScript + Web Audio API + GitHub Pages. That's it.
Try it: sparrowfm.github.io/cronkiter
The Inspiration: A Reddit Comment
I was browsing the ElevenLabs subreddit when I saw someone asking for a feature to make TTS output sound like it was coming through an old 1940s radio or vintage TV. The use case was perfect: they wanted to add atmospheric authenticity to historical content.
My immediate thought: "Wait, couldn't I just build this as a standalone tool?"
A few things clicked:
- No backend needed - The Web Audio API can process audio entirely in the browser
- Universal utility - Not just for TTS, but any audio file
- Simple enough to ship in hours - Audio filters, echo, bandpass filters... these are built into browsers!
I opened Claude Code and started building.
Why NOT FFmpeg This Time?
Regular readers know I've been deep in FFmpeg-land with AWS Lambda recently. Why not use FFmpeg here?
The Web Audio API Alternative
For client-side audio effects like this, the Web Audio API is actually better than FFmpeg because:
- Zero infrastructure - Runs entirely in the user's browser. No Lambda, no S3, no upload/download.
- Real-time preview - Users can hear the effect instantly before rendering.
- Privacy-first - Audio never leaves the user's device. No file uploads to servers.
- Free at scale - Processing happens on the client. My hosting cost: $0.
When to use FFmpeg vs Web Audio API:
| Use Case | Use FFmpeg | Use Web Audio API |
|---|---|---|
| Server-side batch processing | ✅ Yes | ❌ No |
| Video processing | ✅ Yes | ❌ No |
| Complex multi-track mixing | ✅ Yes | ⚠️ Maybe |
| Real-time audio effects | ❌ No | ✅ Yes |
| Privacy-sensitive audio | ⚠️ Requires uploads | ✅ Client-side only |
| Simple format conversion | ✅ Yes | ✅ Yes |
For Cronkiter, the Web Audio API was perfect. No need to overcomplicate.
Building the Audio Processing Chain
The Vintage Broadcast Sound
What makes audio sound "old-timey" or like it's coming through a vintage radio? I researched and identified these key elements:
- Narrowband filtering - Old AM radios had limited frequency response (roughly 300-3000 Hz)
- Slapback echo - Vintage broadcast studios had characteristic short delays (60-120ms)
- Mono fold-down - Old equipment was mono, so collapsing stereo gives that "centered" feel
- Compression - Broadcast limiters created that "squashed" dynamic range
- Tape hiss - Optional atmospheric noise for extra authenticity
Translating to Web Audio API
Here's how each effect maps to Web Audio API nodes:
// Audio processing chain
Source → [Mono Fold] → High-Pass → Low-Pass → Compressor
↓
Dry Path → Output
↓
Wet Path → Delay → Feedback → Output
↓
[Optional White Noise] → Output
Key Web Audio API Components Used:
BiquadFilterNode- High-pass and low-pass filters to create narrowband soundDelayNode- For slapback echo effectGainNode- For wet/dry mix and feedback controlDynamicsCompressorNode- Broadcast-style limitingChannelSplitterNode/ChannelMergerNode- Mono fold-downAudioBufferSourceNode- For white noise generationOfflineAudioContext- For rendering final WAV files
The beauty? All of this runs in real-time with preview playback, then can render to a WAV file for download.
Four Presets Emerged
During testing, I created four distinct sound profiles:
- Raw - Baseline, no processing
- Newsroom - Subtle slapback (80ms), gentle filtering (100Hz-5kHz). Think Walter Cronkite era.
- Old TV / AM Radio - Aggressive narrowband (300Hz-3kHz), pronounced echo (110ms). Full vintage vibe.
- Old TV + Hiss - Same as #3 but with light white noise for maximum authenticity
Users can also tweak every parameter manually: delay time, wet/dry mix, feedback, filter frequencies, and hiss level.
Design Evolution: From Birds to Broadcast Journalism
Original Name: "Edward R. Mur-Wren"
I started with a pun on Edward R. Murrow (legendary CBS broadcaster) + wren (bird). The tagline was "Good night, and good chirp." Cute, right?
After showing it to friends: "It's too birdy. I don't immediately get what it does."
Fair point. The bird puns distracted from the core value proposition.
Rebranding: "Cronkiter"
Renamed to Cronkiter - a play on Walter Cronkite, the most trusted voice in American broadcast news. New tagline: "And that's the way it sounds."
Why this works better:
- Immediately evokes broadcast journalism
- Sounds like a legit audio tool, not a toy
- Tagline references Cronkite's famous sign-off ("And that's the way it is")
- Less quirky, more professional
The badge also evolved from "Broadcast Audio Tool" to "Vintage Audio Transformer" - more descriptive and SEO-friendly.
New Tech: Privacy-Friendly Analytics with GoatCounter
I wanted to track usage but didn't want Google Analytics' bloat or privacy concerns. This was my first time using GoatCounter.
Why GoatCounter?
- Privacy-first - No cookies, no tracking pixels, GDPR compliant by default
- Lightweight - ~3KB script vs Google Analytics' ~45KB
- Free tier - Perfect for side projects
- Simple integration - One script tag, done
The entire integration:
<script data-goatcounter="https://sparrowfm.goatcounter.com/count"
async src="//gc.zgo.at/count.js"></script>
That's it. Now I can see:
- Page views and unique visitors
- Referrer sources (Reddit, Twitter, etc.)
- Browser and device breakdown
- Geographic regions (anonymized)
Lesson learned: For simple sites, GoatCounter is fantastic. No need to overcomplicate with GA4's event tracking complexity.
Deep Dive: Comprehensive SEO for the First Time
I've built production tools before, but never properly tackled SEO and social media meta tags. With Cronkiter, I decided to do it right.
What I Implemented
1. Basic SEO Meta Tags
<title>Cronkiter - Free Vintage Audio Transformer | Make Audio Sound Old-Timey</title>
<meta name="description" content="Transform your audio into nostalgic, old-timey broadcasts for free! Make any recording sound like it's crackling through a 1940s radio or vintage TV. No uploads, runs in your browser.">
<meta name="keywords" content="vintage audio, old radio sound, audio transformer, retro audio effect, broadcast audio, 1940s radio">
Key learnings:
- Title should be under 60 characters for Google's display limit
- Description should be 150-160 characters (I aimed for the sweet spot)
- Keywords help, but are less important than they used to be
- Include your main value prop in the title ("Free", "No uploads")
2. Open Graph Tags (Facebook, LinkedIn, WhatsApp)
<meta property="og:type" content="website">
<meta property="og:title" content="Cronkiter - Free Vintage Audio Transformer">
<meta property="og:description" content="Transform your audio into nostalgic, old-timey broadcasts! Make recordings sound like 1940s radio or vintage TV.">
<meta property="og:image" content="https://sparrowfm.github.io/cronkiter/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Cronkiter interface showing vintage audio presets">
Critical details I learned:
- Image dimensions matter - 1200x630px is the golden standard for all platforms
- Always specify width/height - Helps platforms cache and display correctly
- Alt text is required - Both for accessibility and fallback
- Use og:image:secure_url - Explicitly declare HTTPS image URL
3. Twitter Card Tags
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Cronkiter - Free Vintage Audio Transformer">
<meta name="twitter:description" content="Transform audio into nostalgic broadcasts!">
<meta name="twitter:image" content="https://sparrowfm.github.io/cronkiter/og-image.png">
<meta name="twitter:image:alt" content="Cronkiter interface">
Twitter-specific learnings:
- Use
summary_large_imagecard type for best engagement - Twitter descriptions are limited to 200 characters
- Image should be at least 300x157px, but 1200x630px is recommended
- Add
twitter:siteandtwitter:creatorif you have a Twitter handle
4. Structured Data (JSON-LD Schema)
This was entirely new to me. I added Schema.org structured data so search engines understand what the tool is:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "Cronkiter",
"description": "Free vintage audio transformer that makes recordings sound like old-timey broadcasts",
"url": "https://sparrowfm.github.io/cronkiter/",
"applicationCategory": "MultimediaApplication",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"featureList": [
"Vintage audio presets",
"Real-time audio preview",
"WAV file export",
"Browser-based processing"
]
}
</script>
Why this matters:
- Google can show rich snippets in search results
- Clearly declares it's free (price: 0)
- Lists features that search engines can index
- Categorizes it as a multimedia web application
5. Semantic HTML5
I also learned to use proper HTML5 semantic tags instead of generic <div> elements:
<main class="container">
<article class="main-content">
<header class="branding">
<h1>Cronkiter - Free Vintage Audio Transformer</h1>
</header>
<!-- content -->
<footer>
<!-- footer content -->
</footer>
</article>
</main>
Benefits:
- Better accessibility for screen readers
- Improved SEO - search engines understand page structure
- Cleaner, more maintainable code
Validating Social Media Tags Across Platforms
I created a comprehensive validation checklist for all major platforms:
| Platform | Protocol | Status | Validation Tool |
|---|---|---|---|
| Open Graph | ✅ Fully optimized | Sharing Debugger | |
| Open Graph | ✅ Fully optimized | Post Inspector | |
| Twitter/X | Twitter Cards | ✅ Fully optimized | Card Validator |
| Open Graph | ✅ Works perfectly | Test by sending link | |
| Discord | Open Graph | ✅ Rich embeds | Send link in channel |
| Slack | Open Graph | ✅ Auto-unfurl | Share link in workspace |
| Open Graph | ✅ Thumbnail support | Post and preview | |
| Open Graph | ⚠️ Stories only | Link sticker in Stories |
Instagram caveat: Regular Instagram posts don't show link previews (this is an Instagram limitation, not a meta tag issue). However, link stickers in Instagram Stories do use Open Graph tags!
Generated the Social Media Preview Image
I used Puppeteer to automatically generate a 1200x630px screenshot for social sharing:
// create-og-image.js
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 630, deviceScaleFactor: 2 });
await page.goto('http://localhost:8000');
await page.screenshot({ path: 'og-image.png' });
Now when someone shares Cronkiter on social media, they see a professional preview card with the app interface.
Key SEO Takeaways
- Start with the basics - Title, description, keywords
- Social = SEO - Open Graph tags help with sharing AND search rankings
- Images matter - 1200x630px is universal for all platforms
- Validate everything - Use platform-specific debuggers before launch
- Semantic HTML helps - Use
<main>,<article>,<header>instead of<div> - Structured data = rich results - JSON-LD helps Google understand your content
Mobile UX: The "Desktop Required" Message
During testing, I discovered that mobile browsers have severely limited Web Audio API support. Audio processing works, but:
- Mobile Safari requires user interaction to start AudioContext
- Performance is inconsistent across devices
- Small screens make the UI cramped
- Mobile browsers often have restricted audio playback
The Solution: Responsive Messaging
Instead of a broken mobile experience, I added a media query that shows a clear message on small screens:
@media (max-width: 768px) {
.mobile-message {
display: block;
}
.main-content {
display: none;
}
}
Mobile users see:
Desktop Required
This vintage audio transformer works best on desktop browsers with full audio processing capabilities.
Please visit this page on your computer to give your recordings that classic old-timey radio sound!
Lesson learned: It's better to be honest about device limitations than to deliver a broken experience. Users appreciate clarity.
Comprehensive Testing with Puppeteer
To ensure everything worked, I wrote a full test suite using Puppeteer:
Three Test Suites Created
- Full Suite (51 tests) - Desktop/mobile layouts, UI controls, presets, visual design
- Upload Test (14 tests) - File upload workflow, audio processing, WAV rendering
- E2E Test (17 tests) - Sample loading via HTTP server, complete workflow
Test coverage:
- ✅ All 4 audio presets apply correct parameters
- ✅ Preview playback works
- ✅ WAV rendering produces downloadable files
- ✅ Mobile responsive design shows proper messages
- ✅ All UI controls function correctly
- ✅ Branding and footer display properly
Results: 100% pass rate on upload and E2E tests. The only failures in the full suite were CORS issues when loading sample.mp3 via file:// URLs (expected, not a real issue).
Running tests:
npm run test:upload # 14/14 passed ✅
npm run test:e2e # 17/17 passed ✅
Why this matters: As a non-technical founder, having automated tests gives me confidence that future changes won't break core functionality.
Deployment: GitHub Pages = Zero Infrastructure
One of the best parts of this project? Zero backend infrastructure.
- No Lambda functions to maintain
- No S3 buckets to configure
- No database to provision
- No API keys to manage
Just:
- Push
index.htmlto GitHub - Enable GitHub Pages
- Done
Total monthly cost: $0
Maintenance burden: Zero
Scalability: Infinite (processing happens on client devices)
This is the beauty of browser-based tools. GitHub Pages serves static files at CDN speeds globally, and all the "work" happens on the user's device.
What I'd Do Differently
1. Start with Branding
I wasted time with "Edward R. Mur-Wren" before realizing the bird puns were distracting. Should have tested the name with a few people before building the full UI.
2. Mobile Strategy Upfront
I built the entire desktop experience before considering mobile. Should have checked Web Audio API mobile support first and planned the "desktop required" message from the start.
3. SEO from Day One
Added comprehensive SEO meta tags after the tool was built. Would have been easier to include them in the initial HTML template.
4. Consider a Visual Waveform
Users can preview audio, but there's no visual feedback. Adding a simple waveform visualization with AnalyserNode would improve UX.
5. Preset Descriptions
The preset dropdown is bare-bones. Adding tooltip descriptions of each preset would help users understand what they do before trying them.
Key Learnings from Building with AI
What Claude Code Did Well
- Web Audio API expertise - Generated clean, working audio processing chains
- CSS styling - Beautiful gradient backgrounds and card-based UI
- Responsive design - Media queries and mobile detection
- SEO meta tags - Comprehensive Open Graph and Twitter Card setup
- Test generation - Full Puppeteer test suite with good coverage
What Required Human Guidance
- Product direction - "Make it less birdy" → rebrand to Cronkiter
- UX decisions - Mobile blocking vs broken mobile experience
- Naming presets - "Newsroom" vs "Old TV" vs "Old TV + Hiss"
- SEO keyword selection - "vintage audio transformer" vs "broadcast audio tool"
- Platform validation - Testing social media previews across all platforms
The AI Coding Reality
Building with AI isn't about "the AI builds it all for you." It's about:
- You provide clear direction - What to build, why, and for whom
- AI handles implementation - Code, styling, testing, documentation
- You make decisions - UX, branding, feature scope
- AI accelerates iteration - Quick changes, refactoring, testing
In 90 minutes, I went from idea → working prototype → deployed production tool. That would have taken me weeks (or months) trying to learn Web Audio API, CSS, SEO best practices, and social media meta tags from scratch.
But I still had to:
- Understand what makes audio sound "vintage"
- Decide on the user experience
- Choose the branding and messaging
- Validate it worked across platforms
- Write this blog post explaining the journey
The Numbers (So Far)
Development Time: ~90 minutes
Lines of Code: ~670 (single HTML file)
Dependencies: 0 (vanilla JavaScript)
Test Coverage: 51 tests, 90%+ pass rate
Hosting Cost: $0/month
GitHub Stars: TBD (just launched!)
GoatCounter Analytics (first week):
- Will update this post with traffic data once it's live!
Try Cronkiter Yourself
Live Demo: sparrowfm.github.io/cronkiter
Source Code: github.com/sparrowfm/cronkiter
License: MIT (use it for anything!)
Use Cases
- Content creators - Add vintage radio vibes to podcasts or videos
- Game developers - Process voiceovers for historical/retro games
- Audiobook producers - Create atmospheric effects for period pieces
- TTS enthusiasts - Make ElevenLabs output sound old-timey
- Musicians - Vintage-ify vocals or instruments
What's Next?
Cronkiter is feature-complete for v1.0, but here are some ideas for future iterations:
- Visual waveform - Real-time audio visualization
- More presets - Telephone, megaphone, underwater, vinyl record
- Custom preset saving - Let users save their favorite settings
- Batch processing - Process multiple files at once
- Share presets - URL parameters to share exact settings
But for now, I'm shipping it as-is. Done is better than perfect.
Final Thoughts
This project reinforced something I've learned over and over: AI coding tools are incredible accelerators, but you still need to know what to build and why.
I didn't need to know:
- How to code biquad filters in Web Audio API
- The exact syntax for Open Graph meta tags
- How to write Puppeteer tests
- CSS grid vs flexbox for responsive layouts
But I did need to know:
- What makes audio sound "vintage"
- That users value privacy (client-side processing)
- Mobile limitations should be communicated clearly
- Good branding matters
- SEO and social sharing drive discovery
The combination of product intuition + AI coding is incredibly powerful. You can ship real, production-ready tools in hours instead of weeks.
If you're on the fence about trying AI coding assistants, my advice: just start building. Pick a small project, open Claude Code (or Cursor, or GitHub Copilot), and see how far you can get in an afternoon.
You might be surprised how much you can ship.
Questions? Feedback? Find me on GitHub or try Cronkiter and let me know what you think!
"And that's the way it sounds." 🎙️