Skip to main content
website logo savvydev
Week 1: Voice Logging and Building Something I'd Actually Use

Week 1: Voice Logging and Building Something I'd Actually Use

Five days into building Paveway, and I'm learning that the best product decisions come from solving your own problems in real-time.

Frontend Development Software Development Web Development Best Practices Code Quality Performance

The Problem I Discovered While Building

I started this week with a plan: build a basic logging system where I could track my daily work. Simple form, save to database, show it in a list. Standard CRUD stuff.

But as I was building it, I kept thinking: “Would I actually use this every day?” And honestly? Probably not. Typing out detailed logs at the end of a long day sounds exhausting. I’d skip it half the time.

That’s when I realized I was building the wrong thing. Not wrong architecturally—wrong for actual daily use. If I wouldn’t use it consistently, the whole premise of tracking growth over time falls apart.

So I pivoted. Instead of building what was on my roadmap, I built what would actually get me to log daily.

Solving the Real Problem

Voice logging wasn’t on my original week 1 plan. I was supposed to build basic logging first, then add voice later as a nice-to-have feature.

But on day 2, after implementing the text-based form, I went for a walk. Had this whole mental model of what I’d just built, the tradeoffs I’d made, why certain architectural decisions mattered. And I thought: “I should log this when I get back.”

By the time I got to my desk 15 minutes later, I’d forgotten half of it.

That’s when it clicked. My best thinking doesn’t happen at my keyboard. It happens when I’m walking, right after solving a problem, in that post-coding clarity moment. If logging only works at my desk, I’m going to miss the most valuable insights.

So I changed the plan. Voice logging moved to day 3.

The Implementation

The actual transcription code ended up being surprisingly simple:

const transcription = await openai.audio.transcriptions.create({
  file: audioBlob,
  model: "whisper-1"
});

That’s it. The API just works. Cost is about $0.006 per minute—less than a penny for a 2-minute log.

The hard part? Browser audio permissions. MediaRecorder quirks across different browsers. Handling interrupted recordings. All the unglamorous stuff that users will never see but has to work perfectly or the whole feature falls apart.

There’s something humbling about spending hours debugging browser APIs so that a 4-line OpenAI call can work reliably.

What I Shipped This Week

Here’s what actually got built in the first 5 days:

Voice Logging - Hit the mic button, talk for up to 2 minutes, and it transcribes using OpenAI’s Whisper API. The transcription shows up in the log form ready to save or edit. Cost is about $0.006 per minute.

Timeline View - Visual timeline showing logs as dots on a horizontal axis. Hover for a preview, click for details. Watching the streak build up is more satisfying than I expected.

Feed View - Feels like a private social feed. Quick post card at the top for fast entries without the full form flow.

Multi-Step Forms - Split the logging form into one question at a time with a progress bar. Answering 8 questions in a row feels overwhelming. Answering 1 question 8 times? Much easier.

Dynamic Input Types - Star ratings for satisfaction, sliders for energy levels, dropdowns for choices. More natural than typing numbers.

Charts - Basic visualizations of activity trends, energy patterns, productivity by day of week using Recharts.

Some Technical Decisions Worth Mentioning

Next.js Server Actions - I’m using server actions for all data mutations. No API routes to maintain, automatic cache revalidation, excellent TypeScript support. It’s the right level of abstraction for this project.

Supabase RLS - All permissions live at the database level through Row Level Security. Users see only their logs, admins see everything. Zero trust enforced before data even leaves the database. This feels right for a career development tool where privacy actually matters.

Dynamic Prompts - Questions are stored in the database with their configuration in a JSONB column. Adding a new prompt is just an INSERT statement—no code deploy needed. This will matter later when I want to let users customize their own prompts.

These aren’t flashy decisions, but they’re the kind of architectural choices that either make future work easy or turn into regrets six weeks from now.

What I’m Learning

Five days in and the most important lesson: build for actual usage first, AI features second.

I haven’t touched Claude integration yet. No pattern recognition, no career advice, no intelligent analysis. Right now I’m just building a logging tool that I’ll actually use every day.

Because here’s the thing: if I don’t log consistently, there’s no data for AI to analyze. The foundation has to be solid first. The foundation has to be something I’d use even without the AI features.

This is forcing me to think differently about the project. Instead of “how do I build AI career coaching,” I’m asking “how do I build a logging habit that generates useful data for AI to work with?”

The AI part will come. But first, the basics have to work.

A note on velocity: Shipping all this in 5 days wouldn’t have been possible without Cursor and AI coding agents. They’ve been a game changer for moving fast. I’m spending less time writing boilerplate and more time thinking about what actually matters—the UX decisions, the architecture, the problems I’m trying to solve. That’s the real productivity unlock.

Week 1 Complete

✅ Voice logging working
✅ Timeline and feed views
✅ Multi-step forms
✅ Dynamic input types
✅ Charts and analytics
✅ Using the app daily
⬜ GitHub integration
⬜ Claude API integration

Week 2 Preview

Now that logging feels good, it’s time to add the AI. Next week I’m integrating Claude to analyze log entries and start identifying patterns.

The questions I’m thinking about:

  • How do you structure prompts for consistent, helpful analysis?
  • How do you handle cases where there’s not enough context yet?
  • When should the AI say “I don’t know” instead of guessing?

This is where the real experiment begins.


Progress: Week 1 complete (Day 5 of 90)

Tech Stack: Next.js 15, TypeScript, Supabase, Tailwind CSS, OpenAI Whisper API, Recharts

This is part of a 90-day series on building Paveway. Read the full plan here.