From idea to paying customers: building an AI changelog tool with Angular 21 A developer built Releasely, an AI changelog generator for indie SaaS founders, using Angular 21, Supabase, and the Claude API. The tool generates three audience-specific versions of a changelog from a single input, and the developer shared architecture decisions including backend-only API keys, two-layer rate limiting, and XML-wrapped user input for prompt injection defense. The project is deployed with a Node.js backend on Railway, Angular frontend on Vercel, and uses Lemon Squeezy for payments. How I built Releasely with Angular 21, Supabase, and Claude API I just launched Releasely https://releasely.io — an AI changelog generator for indie SaaS founders. From first commit to deployed product while working part-time around my day job. Here's the full stack and what I learned. The Idea Every time I shipped a release, I wrote the same changelog three times — once for my team in technical language, once for users in plain English, once for X in punchy marketing tone. It killed my release-day momentum. Generic AI tools give you one output. I wanted three audience-specific versions from one input. The Stack Frontend — Angular 21 - Standalone components only no NgModules - Zoneless change detection no zone.js - Signal inputs/outputs throughout - @if / @for new control flow - inject , toSignal , computed patterns - Deployed on Vercel Backend — Node.js + Express - Deployed on Railway always-on, no cold starts - Express middleware for auth, rate limiting, sanitization - All Claude API calls server-side only Database + Auth — Supabase - RLS enabled on every table - Magic link auth with branded emails via Resend SMTP - Auto-profile trigger on user signup - 6 tables: profiles, changelogs, usage logs, subscribers, github connections, github repos AI — Claude Sonnet 4.6 - Three different system prompts one per tone - User input wrapped in XML tags for prompt injection defence - Prompt caching for repeated context Payments — Lemon Squeezy - Stripe is invite-only in India, Lemon Squeezy was the cleanest alternative - Merchant of record handles global tax automatically - Webhook-based plan upgrades to Supabase profiles GitHub App Integration - @octokit/app for installation tokens - AES-256-GCM encryption for stored tokens - CSRF state parameter on OAuth flow - Webhook signature verification Architecture Decisions That Mattered 1. Backend-only API keys The Claude API key never touches the Angular bundle. Angular calls /api/generate on my Node backend, which checks auth, enforces quota, then calls Claude. This is non-negotiable for any AI SaaS. 2. Two-layer rate limiting - IP-level: express-rate-limit, 20 req/min - Per-user: daily quota checked against Supabase usage logs 5/100/300 for free/solo/team 3. XML-wrapped user input Every user input is wrapped in