memorydial

I’d just finished MyFatnessPal when I came across an old idea from The Hacker’s Diet: the “Eat Watch.” A traffic light for your appetite. Green means eat, red means stop. A few hours later, it wasn’t just an idea anymore — it was running on my Garmin fēnix 7X Pro.

Source concept: The Hacker’s Diet – “The Eat Watch” https://hackersdiet.org/hackdiet/e4/eatwatch.html

Original illustration (credit: John Walker / Fourmilab): Original “Eat Watch” illustration


From Idea to Wrist

It started as a passing thought: Wouldn’t it be cool if someone built that? I had no experience with Garmin’s Connect IQ SDK or MonkeyC, their proprietary language. But I wanted to see if I could go from concept to working prototype in a single session — with help from AI.

The concept was simple: a wrist-based calorie traffic light that shows EAT (green) or STOP (red) depending on your daily calorie budget.

Instead of telling AI to “build a calorie tracker,” I started with something broader:

Create a roadmap for a Garmin app that shows EAT/STOP status based on calories, with phases for MVP, UX improvements, and integration.

That single prompt gave me everything I needed:

  • Development phases
  • Clear success criteria
  • Feature priorities

It turned a loose idea into a concrete plan.

My version (prototype on Garmin fēnix 7X Pro): Garmin Eat Watch prototype


Phase 1: Laying the Groundwork

The hardest part wasn’t the logic — it was the structure. Garmin apps need specific manifests, signing keys, and resource folders. MonkeyC feels a bit like Java but has its own quirks.

Prompt that saved hours:

Set up a Garmin Connect IQ project for the fēnix 7X Pro with correct folders, manifest, and build process.

The AI generated:

  • Complete manifest.xml
  • Resource folder structure
  • Build script with key generation

Then I hit a signing key error. One more prompt fixed it instantly:

Monkeyc compiler gives “invalid key format.” What’s the correct format?

Answer:

openssl genrsa -out temp_key.pem 4096
openssl pkcs8 -topk8 -inform PEM -outform DER -in temp_key.pem -out dev_key.der -nocrypt

What would’ve taken an afternoon of documentation digging was done in minutes.


Phase 2: The UX Shift

My first version was overloaded with labels, boxes, and numbers — fine for testing, but useless at a glance. I needed simplicity.

Prompt:

Redesign with a large EAT/STOP indicator and minimal calorie display. Prioritize instant visual feedback.

The AI suggested:

  • A massive header taking 45% of the screen
  • Bold text for EAT/STOP
  • Simple “consumed – remaining” display
  • Color logic: green for EAT, red for STOP

That redesign was the moment it felt like a product, not a prototype.


Phase 3: Persistence and Polish

Then came the first real bug: settings wouldn’t save between restarts. Calorie targets vanished. Reset times didn’t work.

Debugging prompt:

Daily target isn’t saving. Refactor to use Application.Storage and add reset time editing like TargetInputView.

Fixes included:

  • Rebuilt storage using Application.Storage.setValue()
  • Added full TimeInputView
  • Validated input ranges (500–5000 calories)
  • Added persistence tests that passed first try

It now remembered everything, even after a reboot.


What AI Got Right (and What I Learned)

1. Start Broad, Then Narrow

Begin with the roadmap, not the feature. It defines your scope.

2. Be Clear With Constraints

Specific numbers and formats save hours of rework.

3. Reference Patterns

Pointing to existing code or patterns keeps consistency.

4. Ask for Tests

Every major function came with automated tests, just by asking.

5. UX First, Always

A single “simplify this” prompt made the app usable.


Using AI Like a Teammate

In a few hours, I went from zero Garmin experience to a working, wrist-ready app.

Core Features:

  • Real-time EAT/STOP indicator
  • Button-based calorie entry (50-calorie steps)
  • Custom daily target with persistent storage
  • Midnight reset and timezone awareness

Technical Quality:

  • Clean structure
  • Passing tests
  • Battery-efficient

AI handled setup, syntax, and scaffolding. I handled decisions, debugging, and polish. Together, we built something functional — and fun — in record time.

Conclusion

I went from a passing thought – wouldn’t it be cool if someone built this? – to actually building it myself in just a few hours. What started as curiosity became a working Garmin app on my wrist.

MyFatnessPal demo

Thesis: Food logging fails because it fights human behaviour. An AI that understands plain English makes tracking fast enough to stick.

The Problem We All Ignore

I’ve tried MyFitnessPal, Cronometer, and a dozen others. Same pattern every time: great intentions, abandoned in weeks.

The reason? Food logging sucks.

Not the idea, tracking what you eat is valuable. The process is the problem: hunting through databases, guessing portions, adding oils and sauces as separate entries. Five minutes later, you’ve logged one “simple” salad.

Plenty of user research points to high early abandonment for nutrition apps. The friction is too high. The payoff feels too far away.

So I built something different.

The Vision: Talk to Your Food Log

What if logging food was as easy as texting?

“Chicken caesar salad with light dressing.”

That’s it. No measuring cups. No barcode scanning. Just describe what you ate. Let AI do the boring parts.

MyFatnessPal (yes, the name is a joke) understands natural language and returns structured nutrition data from plain-English descriptions.

Result: food logging that’s dramatically faster and surprisingly accurate for complex meals.

How It Works (AI-First, Not Database-First)

Under the hood, MyFatnessPal uses a lightweight GPT model to parse your description and:

  1. Identify ingredients (e.g., romaine, grilled chicken, parmesan, croutons, dressing)
  2. Estimate reasonable portions from context
  3. Calculate calories and macros (protein, carbs, fat)
  4. Return structured data to populate your log

It shines on: – Restaurant meals: “Chipotle bowl with chicken, no rice.” – Home cooking: “Mom’s beef stew, about two cups.” – Snacks: “Handful of almonds and an apple.”

It isn’t perfect, but it’s often more useful than manual database hunting and fast enough to use daily.

Tech Stack (Deliberately Boring)

  • Backend: Django 5.1 (Python 3.12)
  • DB: SQLite (Postgres later if needed)
  • Frontend: Tailwind CSS
  • AI: OpenAI API with caching and resilient error handling
  • Testing: pytest with ~85% coverage (external APIs mocked)

No microservices. No GraphQL. No frontend build maze. Just clean Django and modern tooling.

Why it matters: quick boots, millisecond-fast tests, single-container deploy, ~170 well-tested files.

Features That Reduce Friction

1) Quick-Add Recent Foods

Re-log repeating meals with one click.

2) Recipe Management

Save ingredients → auto per-serving nutrition → log a serving instantly.

3) Visual Daily Summary

Progress bars for calories, quick charts for macros, color-coded guidance.

4) Edit Anything

Fix mistakes, add dessert after dinner—no wrestling with the UI.

Development Philosophy: TDD or Nothing

Every feature started as a test:

  • Red → Green → Refactor loop for each behavior
  • 170+ tests, ~85% coverage on core apps
  • Confidence to refactor aggressively without regressions

What Makes This Different

Versus MyFitnessPal/Cronometer
Them: database search, manual portions, 5–10 min/meal
Me: natural language + AI estimation, ~30 sec/meal

Versus Social Fitness Apps
Them: feeds and gamification
Me: private by default—honest tracking without judgment

Versus Feature-Heavy Suites
Them: everything plus the kitchen sink
Me: one thing done extremely well—effortless logging

The Numbers (Post-MVP)

  • 15+ core features
  • ~85% test coverage on core apps
  • 170+ passing tests
  • Sub-second analysis on typical entries
  • 2-minute first-run: sign up → log food → see insights

What I Learned

  1. AI isn’t magic, but it’s great at fuzzy tasks.
    “Good enough, fast” beats “maybe precise, slow.”

  2. TDD feels slow—until it saves your week.
    Fewer bugs, safer refactors, cleaner design.

  3. Simplicity scales.
    Every feature I didn’t build is maintenance I don’t owe.

  4. Developer tools matter.
    Agent OS turned planning into executable specs.

What’s Next

  • Weekly Insights: trend callouts (“more carbs on weekends”)
  • Pantry Tracker: reduce waste by tracking what you have
  • Exports: CSV/JSON for your data
  • Mobile Polish: responsive now; aiming for native-feeling gestures

Truth is, the app is already useful. I use it daily. Friends keep using it. That’s the metric that matters.

Try It (Eventually)

It’s a personal project for now. I may open-source it or offer a hosted version. If you’re into:

  • AI-powered nutrition tracking that doesn’t suck
  • Production-grade Django with TDD
  • Real-world OpenAI integrations

Reach out. I’m happy to share details and war stories.


Next Steps (High-Level): Add MCP Integration

Goal: expose MyFatnessPal to AI assistants via Model Context Protocol (MCP) so they can log meals, fetch summaries, and manage recipes on your behalf.

Plan (no code, just the map): 1. Agree on Capabilities
– Tools: log_food, getdailysummary, recent_entries, logrecipeserving.
– Optional: find_recipe, create_recipe (later).

  1. Stabilize a Minimal API

    • One endpoint to accept a free-text meal and return structured nutrition.
    • One endpoint to fetch daily summaries by date.
    • Endpoints for recent items and recipe logging.
  2. Choose MCP Transport & Runtime

    • Start with stdio for local use; graduate to HTTP if you need remote calls.
    • Pick TypeScript or Python—whatever your team can maintain comfortably.
  3. Define Contracts

    • Tight, human-readable JSON schemas for inputs/outputs.
    • Clear error shapes (including “AI could not infer portions”).
  4. Auth & Safety

    • Scoped tokens (read vs write).
    • Per-token rate limits and audit logs.
    • Idempotency keys for create/log operations.
  5. Privacy by Default

    • No sharing without explicit user intent.
    • Redact PII from logs; short retention for raw prompts if you store them at all.
  6. Observability

    • Request IDs, structured logs, minimal metrics: success rate, latency, error classes.
    • Trace from assistant prompt → MCP tool → app result.
  7. Resilience

    • Retries with backoff on transient failures.
    • Circuit breaker if the AI service is degraded.
    • Graceful fallbacks (e.g., save raw text entry unparsed).
  8. Testing

    • Contract tests against the API.
    • Golden-file tests for typical meals (restaurant, home-cooked, snack).
    • Load test a “busy evening” scenario.
  9. Launch Steps

    • Ship v0 privately to power users.
    • Collect feedback on tool names and result shapes.
    • Iterate, then publish a lightweight “how to connect” guide.

Appendix

Tech Stack: Django 5.1, Python 3.12, OpenAI, Tailwind, pytest
Time: Two phases, ~3 weeks
Coverage: ~85% with 170+ tests
Status: Fully functional MVP with recipe management

Last Sunday, I resurrected my dead startup in four hours. MemoryDial was a web monitoring service I built in 2014, and abandoned in 2016. It tracked changes on any website, any element, and sent you notifications when something updated. Think of it as a universal notification system for the web, back before push notifications existed. Claude Code got it running again before lunch. What took me six months of nights and weekends in 2011 took a single morning in 2025.

I wasn't planning to resurrect it. I have been using Distill.io every day for web monitoring for the past few years, circa 2018, their browser extension is really good. It has a CSS picker, and it watches websites for changes on a cadence you select and it alerts you when something updates. It's exactly what I built in 2011. But now I need something I could hook into my AI systems with no API limits and no constraints on what I monitor or how. That was when I realised that MemoryDial was sitting there dead in a Git repo.

I fired up Claude Code, ran /init and four hours later, it was running locally again. The Django version was 1.3! Claude updated it to modern Python. It didn't rewrite anything, it just updated deprecated dependencies, swapped out old libraries. The core logic still worked. The idea still worked.

But this isn't really about resurrecting old code. It's about a pattern I kept missing for fifteen years.

The Milkman at 3am

Let me tell you about my actual first attempt at building something. Before MemoryDial.

I was coding late one night when I heard the milkman arrive. Our house was on his route. Ma would always scramble for cash when he knocked, digging through drawers for exact change. I'd just built an online ordering system for a college assessment. I was exploring payment processors in that pre-Stripe world of AIB Merchant Services and Realex Payments. I thought I could help him out.

When he came to collect money one evening, I asked about his route. “Want to come along?” he said.

At 3am, delivering milk in south Dublin, I learned what the job actually involved. Spider webs stretched between every fence and bush, exactly at face height. “Ah fecking spiders are everywhere tonight,” he said, wiping web remnants from his face for the twentieth time that hour. But the spider webs weren't the real problem.

He'd been robbed three times collecting money. Once, he caught the guy. His son helped him find another. The third got away clean. His whole sleep pattern was destroyed. Not by the early deliveries but by the afternoon money collection. Sleep a few hours after morning deliveries. Do commercial runs. Then try to sleep again after chasing payments. Biphasic sleep ruined by people saying “get me next week.”

This was 2009. I saw the opportunity immediately. Online payments would solve everything. No more cash collection, no more robbery risk, better sleep. He would have easily paid more than twenty euro a month just for that.

So I built MilkDirect. Customer portal with order management. Milkman dashboard for route planning. Admin panel for the dairy. Holiday pauses. Calendar views. Special items. The works.

He needed only required payment processing. I built an entire dairy management platform, kitchen sink included.

I kept thinking it wasn't complete enough. It wasn't perfect enough. I wanted to go back to him with the full system, not just the payments part he actually needed. By the time I got it finished in early 2013 I were too late. MyMilkman.ie launched in the summer of 2013 by Glanbia. I had our version with payments working in 2010, but faffed about trying to deliver the perfect product for another 4 years. Four years. I had a them four years before.

Chrome's Dead Tiles

By 2014, I'd moved on to MemoryDial. The idea came from staring at Chrome's “Most Visited” tiles every day. Eight static squares showing dead screenshots of websites. They should be alive. They should pulse with changes like Facebook's red notification bubble. That addictive dopamine hit, but for any website.

This was my pitch from 2014:

“Memorydial is a service that allows users to get dynamic notifications from websites. Say for instance you want to know when a particular website you frequent gets updated. How do you currently do this? Do you get bombarded with RSS updates? Do you wait for a friend to share it with you?”

I thought I were solving how people discovered content. “Users can define websites or portions of web pages that they wish to be notified about.” The technical implementation was solid. WebSockets for real time updates. Diff algorithms to detect changes. Django handling the backend. You could track any element on any page. I even had grand visions. Group notifications because “we believe this to be a compelling service to users based on the feedback we have received.”

What feedback? We'd talked to maybe three people. Friends who said “yeah, that sounds cool bro.”

I built the whole thing first. Then tried to figure out who needed it. I pitched to NDRC accelerator in Dublin, down at St James's Gate. Met with advisors. I did get some solid advice, “Focus on ideas where you already figured out where the customers are...” I'd built it assuming they would come. Field of Dreams thinking. Kevin Costner in a cornfield, except it was Django and no jazz in Dublin.

The Pattern I Couldn't See

Both times I could spot the opportunity. The milkman's spider webs were a real problem with a real solution. Chrome's static web tiles were begging to be dynamic.

Both times I could build the technical solution. MilkDirect worked. MemoryDial worked. Both times I failed for the exact same reason.

When building takes six months of nights and weekends, you have to commit before validating. You invest so much time that pivoting feels like failure. You perfect instead of ship. You build in isolation. Then you try to shoehorn software onto a customer.

By the time you have something to show, you're too invested to hear that nobody wants it, too exhausted to promote it properly, too deep to pivot. This pattern repeated for fifteen years. Always building outside work hours. Never able to go full time. Spotting opportunities. Building solutions. Failing to ship.

What's Different Now

Last Sunday changed something for me. Getting MemoryDial running in four hours made me realise the game has completely changed. I can spin up a prototype by Wednesday. Test an assumption before lunch. The prototype is the customer interview now. Building is talking.

When you can build in hours instead of months, “build it and they will come” becomes “build it and see who shows up.” The cost of being wrong dropped to almost zero. But more importantly, I finally understand what shipping means now.

The Blog Is the Shipping

MemoryDial is becoming two things.

First, the tool itself. I'll extend it however I want. Hook it into my AI systems. Make it do things Distill.io can't or won't. My own infrastructure. My own rules. I'll use it myself, and if others want to use it, great.

Second, MemoryDial.com is becoming this blog. A place to ship ideas at 80 percent instead of products at 100 percent. To write and think in public. To build momentum through publishing.

Writing is shipping now. Publishing is launching. Getting ideas out there. Seeing what resonates. Keeping things moving.

The technical details are genuinely fun. How Django's old URL routing needed updating. How WebSocket implementations have evolved. How what took six months of learning and building in 2011 takes four hours of prompting and debugging in 2025.

But the technical details aren't the point anymore. The point is momentum. Getting ideas into the world while they still have energy.

Building Within Reason

The milkman didn't need our perfect system. He needed to not get robbed collecting cash at 3am. Twenty euro a month for payment processing would have changed his life. He wouldn't have been in a position to get robbed if he was in bed asleep while his money was collecting automatically. That lesson was right there in my face of spider webs, if I'd been listening instead of building.

Fifteen years of this pattern. Spotting opportunities but not shipping them. Building in isolation then wondering why no one came. Working nights and weekends. Never able to make the jump to full time because nothing quite took off.

The spider webs are still there. Problems still exist at 3am like cobwebs. But now I can build something as quick as I can write the spec. See if anyone else gets their face full of spider webs. Move on if they don't.

Building within reason finally makes sense when reason means hours, not months.

I'm more mature now. More focused and excited about sharing ideas and things I'm working on. Not trying to build the perfect system in isolation anymore.

The blog is the shipping now. Ideas out there. Building in public. Thinking through writing.

Welcome to MemoryDial. Again.

The Challenge: Canadian Business Invoicing Done Right

As a consultant working with Canadian businesses, I needed a professional invoice and timesheet system that respected GST and HST, tracked SOW and PO references, and produced sharp PDFs ready for clients. I did not want another subscription or a brittle spreadsheet. I chose Django, and I let AI coding assistants accelerate the work.

This post shows exactly what we built, how AI helped, what still required human judgment, and the prompts that saved hours.

Note: this post shares an engineering approach, not tax advice. Keep your accountant close.


What We Built

A production Django application that delivers:

  • Professional invoice generation with automatic sequential numbering
  • Canadian tax compliance with GST and HST, 5 percent default and configurable
  • Timesheet management with stat holiday support
  • Customer and company management with simple CRM features
  • PDF generation that looks clean in print and on screen
  • Email integration for direct invoice delivery with CC support
  • Banking details on invoices, including institution, transit, and account numbers
  • SOW and PO tracking on customers and invoices
  • Docker deployment for a reliable production setup
  • Comprehensive testing with 32 plus unit tests that catch edge cases

The system runs in production today and sends real invoices to real clients.


The AI Assisted Development Journey

Phase 1: Foundation and Core Models

I began with clear, constrained prompts that described the data model and tax behavior.

Prompt

Create a Django project for invoice generation with these models:
Company, Customer, Product, Invoice, OrderLine.
Companies include addresses and contacts.
Invoices have line items with quantities and unit prices.

Prompt

Add GST/HST tax calculation to invoices. The tax rate is configurable
in GlobalSettings and defaults to 5 percent. Use Python's Decimal
for all financial calculations to avoid floating point errors.

This produced a working base. Real needs pushed me to add Canadian specifics.

Prompt

Add fields to Company for Canadian banking:
bank_institution_number (3 digits), bank_transit_number (5 digits),
bank_account_number, and gst_number for GST/HST registration.

Prompt

Add SOW and PO fields to Company and Invoice as optional
CharFields with max length 100.

Key learning: precise requirements reduce refactoring. Asking for Decimal up front prevented subtle rounding bugs.


Phase 2: PDF Generation and Styling

I chose WeasyPrint for HTML to PDF.

Prompt

Set up WeasyPrint. Create a view that renders
invoices/templates/invoices/invoice_pdf.html to PDF and saves it
to Invoice.pdf_document.

Prompt

Design a professional invoice template with:
logo at top, billing and customer details, invoice number and dates,
line items with product, quantity, price, and totals,
subtotal, discount, GST/HST, and grand total, banking information at bottom.
Use a clean, Canadian business style.

The first draft lacked contrast. I iterated.

Prompt

Make the table easier to read.
Add zebra striping, bold headers with a dark background,
clear spacing between sections, and a bordered totals box.

Pro tip: for anything visual, iterate in short loops. Establish layout first, then refine spacing, then refine type, then contrast.


Phase 3: Timesheet Functionality

I needed monthly timesheets, calendar view, stat holidays, and totals.

Prompt

Create Timesheet and TimesheetEntry.
Timesheet: customer, month, year, hourly_rate.
TimesheetEntry: timesheet, date, hours (decimal), is_stat_holiday.
Validate that entries fall inside the timesheet month.

Prompt

Create a timesheet PDF template similar to the invoice template.
Show a calendar grid with dates, hours, and stat holiday markers.
Calculate total hours and total amount due at the bottom.

A pleasant surprise came from the assistant.

Unexpected win: it suggested Django calendar utilities for a clean calendar grid. That simplified the implementation and reduced custom date math.


Phase 4: Comprehensive Testing

Tests are tedious to write, yet they save your future self. This is where AI shined.

Prompt

Write unit tests for Invoice:
creation with automatic numbering, GST/HST accuracy,
discounts, zero value invoices, fractional cent rounding.
Use Django's test framework and separate modules.

Prompt

Write tax calculation edge case tests:
half cent cases such as 10.005, pennies, large amounts,
0 percent tax, 100 percent discount.
Use Decimal and quantize to 2 decimal places.

Prompt

Write tests for timesheets:
hours math, stat holiday marking, month validation,
rate calculations, and partial hours 0.5 and 0.25.

Result: 1,348 lines of tests across 32 plus cases. The suite caught several corner cases before production.


Phase 5: Email Integration and Deployment

Email needed to send PDFs with a clear message and CC support.

Prompt

Create an email utility that takes an Invoice,
renders a concise email body, attaches the PDF,
sends to the customer's contact, CCs a secondary email if set,
and updates a MailInfo status. Use Django's email framework.

For production I containerized the service.

Prompt

Create a Dockerfile that uses Python 3.13, installs dependencies with Poetry,
includes the SQLite database for dev, runs migrations on startup,
uses Gunicorn for production, and serves static files with WhiteNoise.
Add docker-compose.yml.

Critical issue discovered: dates displayed as 2,025 instead of 2025. Django thousand separators applied to year numbers.

Fix

Set USE_THOUSAND_SEPARATOR = False in settings.py.
Explain that internationalization number formatting applies separators
to all numbers, including years in certain contexts.

Key Technical Decisions

Use Decimal for Money

Floating point math creates penny level errors. Decimal avoids this.

from decimal import Decimal, ROUND_HALF_UP

TWO_PLACES = Decimal("0.01")

def money(x: Decimal) -> Decimal:
    return x.quantize(TWO_PLACES, rounding=ROUND_HALF_UP)

subtotal = money(sum(line.total for line in invoice.lines()))
gst_rate = Decimal("0.05")  # configurable default
tax = money(subtotal * gst_rate)
total = subtotal + tax

Prompt that helped

Explain why to use Decimal for currency.
Show a calculation that fails with float and succeeds with Decimal.

Automatic Unit Price from Product

Avoid retyping prices. Let OrderLine inherit the price, but allow overrides.

def save(self, *args, **kwargs):
    if not self.unit_price and self.product:
        self.unit_price = self.product.price
    super().save(*args, **kwargs)

Test Safe Invoice Numbering

Sequential numbers should not cause flaky tests. I moved tests into a separate range.

def increase_last_number(self):
    import sys
    if 'test' in sys.argv or 'pytest' in sys.modules:
        if self.last_number < 9000:
            self.last_number = 9000
    self.last_number += 1
    self.save()
    return self.last_number

Django Formsets for Line Items

Users add several items fast with formsets.

from django.forms import inlineformset_factory

OrderLineFormSet = inlineformset_factory(
    Invoice, OrderLine,
    form=OrderLineForm,
    extra=10,
    can_delete=True
)

Prompts That Saved Hours

The Audit Prompt

Prompt

Review Invoice.calculate_totals for bugs.
Check order of operations, Decimal usage, edge cases,
and any division by zero. Suggest improvements and write tests.

This caught a 100 percent discount case that still charged tax. The fix set the subtotal after discount to zero, then short circuited tax.

The Production Ready Prompt

Prompt

Review the Django app for production readiness.
Check security settings and secrets, common indexes,
static file configuration, email error handling,
and migration safety. Produce a deployment checklist.

I added indexes, fixed ALLOWED_HOSTS, hardened settings with environment variables, and confirmed WhiteNoise and Gunicorn behavior.

The Test Organization Prompt

Prompt

Split invoices/tests.py into:
test_models.py, test_forms.py,
test_invoice_calculations.py, test_timesheets.py.
Keep the same coverage, improve maintainability.

The suite became easier to read and run.


Lessons Learned

What Worked Well

  1. Specific prompts created better code and fewer revisions.
  2. Iterative refinement raised quality without churn.
  3. Asking for explanations taught me new patterns while shipping.
  4. Test generation fit AI perfectly, especially for edge cases.
  5. Code review prompts surfaced bugs I would have missed.

What Required Human Judgment

  1. Canadian business rules and SOW and PO behavior.
  2. UX decisions such as layout, wording, and approvals.
  3. Architecture choices such as Django, WeasyPrint, and containerization.
  4. Security and privacy tradeoffs.
  5. Deployment decisions and backup plans.

Pitfalls to Avoid

  1. Accepting the first answer without inspection.
  2. Skipping edge cases in tests.
  3. Pasting code you do not fully understand.
  4. Ignoring warnings in explanations.
  5. Over reliance on AI at the expense of domain understanding.

Results

Metric Value
Time about six weeks of evenings and weekends
Solo estimate without AI three to four months for an experienced Django developer
Lines of code about 2,000 application, 1,350 tests, 800 templates
Production running today with Docker
Test coverage 32 plus comprehensive tests
Cost savings replaced a 20 dollar per month subscription

Conclusion

AI did not write the entire system, or this blog post, it just sped up the tedious parts, helped me think, and caught bugs through test generation and code review prompts. I set the business rules and architecture, and I made the tradeoffs. Together we shipped a reliable, Canada aware invoicing stack in a reasonable timeline.

MemoryDial began as a small project over a decade ago. It watched websites for changes, letting you track any part of any page and get notified when something shifted. The original version was built in 2011 and went through a few iterations before being shelved in 2016.

Instead of leaving the name idle, I have decided to relaunch MemoryDial as a personal blog. This will be a place for me to publish ideas, share what I’m working on, and make projects public as they develop.

Each post will be a release, whether it is a small experiment, a technical note, a reflection on process, an idea, or an attempt to spec something in public before actually building.