Picture this: It’s 2 AM, I’m scrolling through my bank statement, and I see three charges I completely forgot about. Spotify Premium (again?), some AI tool I tried once, and a $29/month “productivity” app I haven’t opened in months.
Sound familiar?
As a senior Angular developer, I had the tools to fix this problem. So I gave myself exactly 14 days to build a complete micro SaaS solution from scratch.
The result? SubTrack — a subscription tracking app that not only solved my problem but taught me more about modern Angular development than months of tutorial-watching ever could.
This article kicks off my new series, “Zero to SaaS in 14 Days”, where I build lean SaaS MVPs end-to-end in tight timeframes and share the raw, real lessons learned along the way.
Here’s the brutally honest story of what worked, what didn’t, and why my “failed” revenue attempt might actually be the biggest win.
🎯 The Problem Everyone Has (But Nobody Talks About)
The $273/Month Subscription Creep
We’re living in the subscription economy, and it’s slowly bleeding us dry:
- That $9.99 Netflix subscription? It’s now $17.99
- “Just trying” a new SaaS tool for $19/month… 6 months ago
- App Store subscriptions you forgot existed
- Annual renewals that hit like financial surprise parties
The existing solutions? Either clunky mobile apps that feel like enterprise software, or heavyweight financial trackers that want to connect to your entire banking history just to track a few subscriptions.
My “Aha!” Moment
I needed something lightweight, fast, and browser-based. Something that could:
- Track subscriptions without connecting to my bank
- Scream at me when renewals are coming up
- Show me exactly where my money’s going with beautiful charts
- Work offline and sync later (local-first philosophy)
Most importantly: I wanted to build it with Angular 20’s latest features and see if modern web development could solve this ancient problem elegantly.
🚀 The 14-Day Sprint: Building SubTrack
Day 1–2: The Foundation That Changes Everything
Goal: Set up the bones without getting lost in architecture rabbit holes.
I started with Angular 20’s standalone components and the game-changing signals API. No more modules, no more complex state management — just pure, reactive bliss:
// This is what modern Angular looks like
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(), // 🔥 Future-proofing
provideRouter(routes)
]
};
The secret sauce? A local-first architecture that starts working immediately:
@Injectable({ providedIn: 'root' })
export class SubscriptionsData {
// Pure reactive state with signals
private subscriptions = signal<Subscription[]>([]);
// Computed properties that update automatically
totalCost = computed(() =>
this.subscriptions().reduce((total, sub) => total + sub.cost, 0)
);
dueSubscriptions = computed(() =>
this.subscriptions().filter(sub => this.isNearDue(sub))
);
}
Why this matters: No loading states, no API failures, no “network required” nonsense. The app just works, instantly.
🚀 Ready to level up your frontend game? Grab the FREE 10-Step Code Review Checklist and catch bugs early 🐞, boost app speed ⚡, and make teamwork easy 🤝. Click to get started - your best code is just one download away! 📋✨
Day 3–7: The CRUD Revolution
Remember the pain of building CRUD operations? Those days are officially over.
I built a complete subscription management system with:
- Smart form validation that actually helps users
- Accessible dialogs that don’t make you want to throw your keyboard
- Date handling that doesn’t break when timezones get involved
The breakthrough moment came with this date normalization trick:
private isNearDue(subscription: Subscription): boolean {
// The secret: normalize EVERYTHING to start of day
const today = new Date();
today.setHours(0, 0, 0, 0);
const dueDate = new Date(subscription.nextPaymentDate);
dueDate.setHours(0, 0, 0, 0);
const daysUntilDue = Math.ceil(
(dueDate.getTime() - today.getTime()) / (1000 * 3600 * 24)
);
return daysUntilDue >= 0 && daysUntilDue <= 7;
}
The result? No more “why is my notification badge disappearing?” bugs. Pure, predictable date logic that actually works.
Day 8–12: Filters That Don’t Suck
Here’s where most CRUD apps die: terrible search and filtering.
I built something different — a filter system that feels like magic:
interface FilterState {
searchTerm: string | null;
category: string | null;
billingCycle: BillingCycle | null;
dateRange: { start: Date | null; end: Date | null };
}
// Filter logic that's actually readable
private matchesAllFilters(subscription: Subscription, filters: FilterState): boolean {
return this.matchesSearchTerm(subscription, filters.searchTerm) &&
this.matchesCategory(subscription, filters.category) &&
this.matchesBillingCycle(subscription, filters.billingCycle) &&
this.matchesDateRange(subscription, filters.dateRange);
}
The magic ingredient? Every filter updates in real-time using Angular signals. Type a letter, see results instantly. Change a date range, boom — filtered results without any loading spinners.
Day 13–14: Charts That Tell Stories
Here’s where SubTrack transformed from “just another CRUD app” to “holy crap, I’m spending HOW much on Adobe?!”
Four chart types that expose the truth about your spending:
// Chart configuration that actually makes sense
const CHART_CONFIG = {
PIE_WIDTH: 380,
PIE_WIDTH_MOBILE: 200,
BAR_HEIGHT: 350,
MOBILE_BREAKPOINT: 480,
TOP_SUBSCRIPTIONS_LIMIT: 5
} as const;
private createPieChartOptions(): PieChartOptions {
const { labels, series } = this.categoryData();
return {
series,
chart: { width: CHART_CONFIG.PIE_WIDTH, type: 'pie' },
labels,
responsive: [{ /* Mobile-first approach */ }],
tooltip: { y: { formatter: CURRENCY_FORMATTER.format } }
};
}
The moment everything clicked: When I saw that Adobe Creative Cloud was eating $52.99/month of my budget. That single chart paid for the entire development time by helping me realize what subscriptions I could actually cancel.
💡 Plot Twists: What Nobody Tells You
The Bug That Almost Broke Everything
Day 11, 11:47 PM: The notification badge kept disappearing when subscriptions were due “today.”
Hours of debugging later, I discovered the culprit: time-of-day calculations were fighting with day-boundary logic. The fix was embarrassingly simple — normalize everything to midnight:
private normalizeToStartOfDay(date: Date): Date {
const normalized = new Date(date);
normalized.setHours(0, 0, 0, 0);
return normalized;
}
Lesson learned: Sometimes the most frustrating bugs have the most elegant solutions.
The Feature That Became The App
Originally, the notification badge was just a nice-to-have. But when I implemented the 7-day “near due” window, suddenly the entire app made sense.
Users don’t want to manage subscriptions — they want to forget about them until it matters.
That badge became the single most important feature, turning SubTrack from a database into a personal financial assistant.
🔍 The Technical Deep-Dive That Changed My Mind
Why Angular 20 + Signals = Developer Happiness
After building this app, I’m convinced that Angular’s signals are the future of reactive programming:
// Old way: Complex RxJS chains, memory leaks, subscription hell
this.filteredData$ = this.searchTerm$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(term => this.filterData(term)),
shareReplay(1)
);
// New way: Pure reactive bliss
readonly filteredData = computed(() => {
const term = this.searchTerm();
const filters = this.filters();
return this.filterData(term, filters);
});
No subscriptions to manage. No memory leaks. No async pipe headaches. Just pure, predictable reactivity.
The Local-First Architecture That Actually Works
Most apps start with “let’s build an API first.” I did the opposite — local storage with a migration path:
@Injectable({ providedIn: 'root' })
export class LocalStorageApi {
// Defensive programming that prevents data loss
getItems<T>(key: string): T[] {
try {
const items = localStorage.getItem(key);
if (!items) return [];
const parsed = JSON.parse(items);
return Array.isArray(parsed) ? parsed : [];
} catch (error) {
console.error(`Error parsing localStorage data for key ${key}`, error);
this.clearItem(key); // Fail gracefully
return [];
}
}
}
Result: Zero infrastructure costs, instant app startup, and users can try it without signing up for anything.
📈 The Results That Surprised Me
What Worked Better Than Expected
- Angular 20’s standalone components eliminated so much boilerplate
- Local-first architecture made the app feel incredibly fast
- Material 3 theming gave professional UI with minimal effort
- Signals + computed properties made complex state trivial
What I’d Do Differently
- Start with a domain layer from day one (too much logic ended up in components)
- Prepare for internationalization/multi-currency support: Early architecture choices to support different locales make expanding beyond initial markets easier.
- Invest in automated testing early: Setting up unit and integration tests before feature creep means faster iterations and less bug hunting closer to launch.
- Prototype key interactions before full implementation: Rapid clickable prototypes might have highlighted UX challenges earlier and saved development time.
The $0 Revenue Reality Check
Here’s the uncomfortable truth: I made exactly $0 from SubTrack.
But here’s why that doesn’t matter:
- Validated the local-first approach for future projects
- Mastered Angular 20’s signals before they become mainstream
- Built a portfolio piece that showcases modern development practices
- Learned what users actually want in subscription management
Sometimes the biggest wins don’t show up in your bank account immediately.
🎪 The “Holy Crap” Moment That Made It All Worth It
Day 14, 3:22 PM: I deployed the final version and opened the spending overview.
The top 5 chart showed:
- Adobe Creative Cloud: $52.99/month
- Coursera Plus: $39.99/month
- Prime + Music: $16.98/month
- ChatGPT Plus: $20.00/month
- Some random productivity app: $29.99/month
Total: $159.95/month I wasn’t fully conscious of.
At that moment, SubTrack stopped being a coding exercise and became a financial wake-up call. I immediately canceled two subscriptions and saved $69.98/month.
The app paid for itself before I even tried to monetize it.
🚀 Help Me Build SubTrack That Works For You!
SubTrack is just getting started. To shape the future of subscription management, your feedback is everything. Please take a moment to answer these few key questions:
- What’s your biggest frustration with subscription tracking today?
- Which SubTrack feature do you find most useful or exciting?
- What one feature is missing that would make you use SubTrack daily?
- Would you pay around $5/month for extra perks like multi-device sync, export, or alerts?
- How important is data privacy and local-first storage to you?
- Would you trust SubTrack to handle your subscription data securely?
- How do you want to be notified about upcoming payments? (Email, SMS, in-app)
- If you’re using another tool, what would make you switch to SubTrack?
Your answers guide my roadmap — let’s build the subscription manager you actually want.
Drop your thoughts below or reach out anytime!
💬 Your Turn: Let’s Build Something Amazing Together
This 14-day sprint showed me the best products solve real problems. SubTrack was born from my own subscription shock moments.
What’s your biggest problem you’d solve if you had two weeks and modern tools?
Try SubTrack now:
Your feedback will shape what comes next. Drop a comment or DM me anytime.
Sometimes, the best way to fix a problem is to build the solution yourself.
Want more behind-the-scenes? Follow me for updates on my next 14-day challenge . 🔥
Thanks for Reading 🙌
I hope these tips help you ship better, faster, and more maintainable frontend projects.
🛠 Explore My Developer Resources
Save time and level up your code reviews, architecture, and performance optimization with my premium Angular & frontend tools.
👉 Browse on Gumroad
💬 Let's Connect on LinkedIn
I share actionable insights on Angular & modern frontend development - plus behind‑the‑scenes tips from real‑world projects.
👉 Connect with me here
📣 Follow Me on X
Stay updated with quick frontend tips, Angular insights, and real-time updates - plus join conversations with other developers.
👉 Follow me on X
Your support fuels more guides, checklists, and tools for the frontend community.
Let's keep building together 🚀
Top comments (1)