DEV Community

Cover image for Building an AI Side Project That Actually Ships — Lessons from Shipping 3 MVPs
Shaw Sha
Shaw Sha

Posted on

Building an AI Side Project That Actually Ships — Lessons from Shipping 3 MVPs

Most AI side projects die before seeing a single user. I know because I've killed more than I've shipped. But somewhere between the hype cycle and the burnout, I figured out a rhythm that actually works. Over the last two months, I shipped three AI-powered MVPs — not demos, not tutorials, but real projects that people can use. Here's what I learned, what I'd do differently, and why the biggest bottleneck was never the AI itself.

The three projects, briefly

Before I get into the lessons, here's what I actually built:

  1. MeetingNotes.ai — a bot that joins my Google Meet calls (via a separate audio feed), transcribes them, and generates action items. ~800 lines of TypeScript.
  2. CommitSense — a CLI tool that reads your staged git diff, generates a conventional commit message, and optionally opens a PR description. ~350 lines of Python.
  3. TagBot — a Slack app that automatically categorizes incoming messages in busy channels. ~200 lines of Node.js.

None of these are revolutionary. That's the point. Each one solved a specific problem I had, and each one reached "usable by other people" status in under two weeks.

Lesson 1: The idea is 10% of the work. The plumbing is 90%.

When I started, I thought the hard part would be prompt engineering or fine-tuning. It wasn't. The hard part was everything around the AI call: authentication, rate limiting, error handling, retry logic, and deploying the thing so it doesn't crash at 2 AM.

Here's a realistic example. For CommitSense, the core feature is dead simple — call an LLM with a diff and get a commit message back:

import subprocess
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

def generate_commit_message():
    diff = subprocess.run(
        ["git", "diff", "--cached"],
        capture_output=True,
        text=True
    ).stdout

    if not diff.strip():
        return "Nothing staged. Run `git add` first."

    prompt = f"""You are an expert software engineer. Write a concise conventional commit message for the following diff.

Rules:
- Use format: type(scope): description
- Max 72 characters for the subject line
- Focus on WHY, not just WHAT

Diff:
{diff[:8000]}  # truncate to stay within token limits
"""

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3,
        max_tokens=100
    )

    return response.choices[0].message.content.strip()
Enter fullscreen mode Exit fullscreen mode

That's the "AI magic" — about 20 lines. The other 330 lines are: handling the case where git diff returns nothing, truncating large diffs, token counting, retry logic when the API rate-limits me, a config file for custom prompts, and a --dry-run flag so people can test without committing.

The lesson: if your side project is just "call an API and print the result," you're not building a product. You're writing a script. The product is everything you wrap around that call.

Lesson 2: Ship ugly. Ship fast. Ship to one person.

My first side project, MeetingNotes.ai, took three weeks because I kept polishing the UI. I wanted a pretty dashboard, a landing page, and a nice onboarding flow. By the time I had all that, I'd lost interest and almost abandoned it.

For CommitSense, I forced myself to ship the CLI version first. No UI. Just a command you run in a terminal. The first version was genuinely rough — the output formatting was janky, and it didn't handle multi-line commit bodies well. But I gave it to two developer friends, and their feedback was worth more than any amount of self-criticism.

One of them said: "The commit message is great, but I want it to also suggest a branch name." That led to a feature I never would've thought of. Another said: "I use cz for conventional commits — can you integrate with that?" I hadn't heard of it. Within a day, I added an --cz flag.

If I'd kept polishing the UI instead of shipping, I'd have built features nobody wanted.

Lesson 3: Pick boring infrastructure

Here's where I made my biggest mistake and then corrected it.

For MeetingNotes.ai, I initially decided to self-host a small open-source model. I read blog posts about running Llama 3 on a single GPU, and it sounded cool. In practice, it was a nightmare:

  • The model needed 16GB of VRAM for reasonable speed
  • My cloud GPU bill was $0.80/hour, and I was testing constantly
  • Every model update required re-downloading weights
  • The output quality was noticeably worse than the hosted APIs
  • I spent 4 days on infrastructure instead of features

I gave up and switched to a simple pay-as-you-go API approach. The difference was night and day. The whole integration took about an hour, the output quality jumped, and my cost went from a flat $0.80/hour (running even when idle) to about $0.003 per call — which for my usage meant a total of about $4 for the entire month.

That experience changed how I think about side projects. The goal is to ship something that works, not to prove you can run a model. When you're building an MVP, the model is a commodity. The value is in the product around it.

Lesson 4: Costs are different than you expect

Let me share real numbers from the last two months:

Project AI API cost/month Infrastructure cost/month Users
MeetingNotes.ai ~$12 $0 (hosted on a free tier) 4
CommitSense ~$3 $0 (CLI, runs locally) 9
TagBot ~$2 $0 (Slack cloud) 6 (one workspace)

Total: about $17/month for three running projects. That's less than I spend on coffee.

The surprise was how much cheaper this is than I expected. I'd read horror stories about runaway API costs. The reality: if you're careful about token usage (truncate inputs, use smaller models where possible, cache responses), the cost is trivial at MVP scale.

For MeetingNotes.ai, the biggest cost driver was the transcription model, not the LLM. Whisper API charges by the minute, and a 1-hour meeting costs about $0.36 to transcribe. The summarization call costs a fraction of that. You don't know this until you actually run it, which is another reason to ship fast and measure.

Lesson 5: The 80/20 rule applies to AI features too

I kept wanting to add "smart" features to TagBot — sentiment analysis, auto-response suggestions, thread summarization. It would've been cool. But the core use case — "is this message about a bug, a feature request, or noise?" — was already working with a simple prompt and a gpt-4o-mini call.

I've learned to ask: will this feature get 50% more usage, or 5% more usage? If it's the latter, it goes on the backlog. The 20% of features that matter get shipped first, and the rest can wait.

The reality check: what actually helped me ship

If I'm honest, the factor that helped most wasn't discipline or motivation. It was removing friction. Here's what I mean:

  • I stopped self-hosting models entirely. The maintenance burden was killing my momentum.
  • I standardized on one API provider across all three projects, so I only had to learn one SDK, one auth flow, one billing system.
  • I set a hard deadline of 14 days per project. If it wasn't usable by then, it wasn't worth building.

For the API provider, I ended up using a pay-as-you-go gateway that aggregates multiple models — by the way, I use tai.shadie-oneapi.com for this. It lets me switch between models without changing code, which turned out to be huge. When I wanted to test whether gpt-4o-mini was good enough for a task instead of the full gpt-4o, I just changed a string in a config file. No new SDK, no new credentials, no new billing setup. It's not the flashiest tool, but it's the kind of boring, practical choice that keeps side projects alive.

What I'd tell someone starting today

If you're starting an AI side project tomorrow, here's my honest advice:

  1. Pick a problem you have right now. Not a market opportunity. Not a "cool AI thing." Something that annoys you daily.
  2. Use hosted APIs from day one. Your first MVP doesn't need you to be a machine learning engineer. It needs you to be a product person.
  3. Set a 2-week deadline. If you can't get something usable in 14 days, you're either over-scoping or over-engineering.
  4. Show it to one person before you finish it. Embarrassing early feedback is worth more than polished assumptions.
  5. Measure your API costs from week one. You'll learn more from $4 of real usage than from $40 of theoretical optimization.

The side project trend is real, but the reality is that most people never ship because they optimize the wrong things. They optimize for impressive tech instead of usable products. The AI is the easy part. Shipping is hard. But it's also the only part that matters.

I'm already planning MVP number four — a browser extension that summarizes long articles into five bullet points while preserving the author's key arguments. This time, I'm expecting it to take about a week. Not because I've gotten smarter, but because I've finally stopped doing things that don't matter.

Top comments (0)