From Perl Scripts at Yahoo! to AI-Powered Flutter Apps

I was thinking the other day about how much has changed since I started at Yahoo! back in ’99. Back then, we were building the internet’s infrastructure with Perl scripts, find and grep commands, and a whole lot of grit. We were the ones in the machine, making it work, scaling it to millions of users. It was a once-in-a-lifetime opportunity, and I loved every minute of it.

Fast forward to today. The landscape is completely different. I’ve been a software engineer for almost 30 years, and the tools are evolving faster than ever. Lately, I’ve been diving deep into AI-powered coding, specifically with a command-line tool called Claude Code. It’s a long way from the copy-paste I started with in ChatGPT last year.

To put it to the test, I decided to take on a new challenge: building a full-fledged Flutter app that runs on iOS, Android, and the web. Maybe a simple app to log my runs, or a food journal for Kate. Something personal. But instead of grinding it out solo, I decided to treat the AI as my coding partner. A friend was asking for tips on getting started, so I cleaned up my notes from the experience. It feels a lot like sharing a new running route or a discovery at the farmer’s market.

A good engineer is a lazy engineer. That means you find the best tools to get the job done efficiently. And let me tell you, this AI coding assistant is a fascinating new tool. But it’s not magic. You can’t just give it a vague idea and expect a perfect app. You have to treat it like a junior engineer on your team: you need to be a good manager, provide clear direction, and have a solid plan.

Here’s a look at how I approached it, broken down into the phases of the project.

Phase 1: The Plan is Everything

I’ve always believed that you shouldn’t write a line of code without a plan. It’s the difference between building a skyscraper and a sandcastle. With an AI, this is even more critical.

  • Planning Mode is Non-Negotiable: Before the AI wrote any Flutter code, I put it in “planning mode.” This is like a mandatory design review. We went back and forth, discussing options. I had it outline the pros and cons of different state management libraries for Flutter, since I was new to the ecosystem. You wouldn’t want an engineer on your team to just start coding without a vetted plan, and you shouldn’t let your AI partner do it either.
  • Detailed Specs in Markdown: I’ve found myself writing longer and longer specs. For this Flutter app, I spent a good hour writing a two-page document in Markdown. It’s a simple format—`#` for headings, `-` for lists—but it brings clarity and reduces ambiguity. It forces you to think through the problem, which is half the battle.
  • Mockups First: A friend gave me a great tip: have the AI generate a quick UI mockup. I had it spit out an interactive mockup of the app’s interface. It’s much faster than a full build and lets you get a feel for the user experience. We tweaked the layout and flow before I gave the green light for the real build.
  • The To-Do List: Once I approved the plan, I had the AI write the final plan and a detailed to-do list into a `PLAN.md` file. This becomes our source of truth. If the AI gets sidetracked or forgets a step during a long build, I can just point it back to this document. It’s our contract.

Phase 2: Setting Up the Workspace

Just like you’d set up your dev environment, you need to configure your AI partner. It needs to know the rules of the road for your project.

  • The `CLAUDE.md` File: This is a handy file where you put standing instructions. I filled it with the overall project objective, the exact command-line instructions to build and launch the Flutter app, and where to find the log files. Over time, I added my own rules, like “Always use this color scheme” or “Never commit directly to the main branch.”
  • Custom Commands for Automation: I’m a huge believer in automating repetitive tasks. I created a few custom commands in the `.claude/commands/` directory. For example, I made a `/commit` command that adds all my changes, drafts a detailed commit message (which is usually better than what I’d write), and commits the code. I also made a `/bl` (build and launch) command to run a clean build and check the logs. It’s like having little shell scripts for your AI.

Phase 3: The Coding Dance (and the Feedback Loop)

This is where the real work happens. It’s an iterative process, a back-and-forth between you and the AI.

  • Be Explicit: You can’t be vague. I use the `@` symbol to reference specific files (e.g., `@lib/main.dart`). It has auto-completion and makes the request crystal clear. For complex logic, I tell it to “think hard” or even “ultrathink.” It’s like telling an engineer to step away from the keyboard and hit the whiteboard.
  • The Feedback Loop is Magic: This is the dream setup. I worked with the AI to create a script that would build the Flutter app, launch it, and then check the output logs for errors. I told it to run this in a loop until the problem was solved. I could literally watch it try a fix, see it fail, analyze the log, and try something else. I’d go for a run or make dinner, and come back to find it had solved a tricky bug on its own.
  • Managing Context: The AI has a limited memory (context window). When it gets full, it has to summarize the conversation, which can sometimes lead to it forgetting things. My approach is simple: after a major task is done, tested, and committed, I use the `/clear` command to wipe the slate clean. It’s like finishing a marathon; you don’t start your next training day by re-running the last 26 miles. You start fresh.

Phase 4: Staying in Control

At the end of the day, you are the senior engineer in this partnership. You are in control.

  • Git is Your Safety Net: I commit my working, tested changes before every new major prompt. If the AI starts going down a rabbit hole and follow-up prompts aren’t helping, I don’t hesitate to hit the reset button. I run `git restore` to go back to the last good state and try again with a more refined prompt. It can be tough to give up on the current path, but it’s better than getting tangled in messy, incorrect code. It’s like a failed rep in a workout—better to reset and do it right than to finish with bad form.
  • Know When to Hit the Brakes: The `Esc` key is your friend. If you see the AI doing something you don’t like, you can pause it instantly. You can even type in new instructions while it’s working, and it will incorporate your feedback on the fly.

It’s a different way of working, for sure. It’s less about the low-level syntax and more about high-level architecture, planning, and guidance. Back at Yahoo!, we were the ones deep in the machine, writing every line. Now, I feel more like a conductor, orchestrating an incredibly fast and capable, if sometimes naive, musician. The core principles of good engineering—discipline, planning, automation—are more important than ever.

It’s not about being replaced. It’s about leverage. It’s a new tool that, if you learn to use it with discipline, lets you build bigger, better, and faster than ever before.