Over the holidays, I decided to try and see how quickly I can build a project using AI (end-to-end), mostly as a learning exercise. I've been writing a bit more about AI and side projects and wanted to put my own advice to the test.

So this post goes into how milao.to went from idea to reality in under 10 hours of active working time. I'll go into my thought process and tech stack here; and share some insights I took away.

Ideation

The idea here was simple: I had a LinkedIn post about helping people find jobs which got more responses than I expected, and I needed a quick and dirty way to manage the data for myself. So I thought: why not make this into a website, and share the data where people were comfortable?

I decided to use ChatGPT to give me feedback on this idea. Here's some of the prompts I used (ignoring responses for brevity). Indented bullets indicate follow ups, top level bullets indicate different session

  • I wrote the below post on LinkedIn and got a lot of responses and it's hard to manage them. Is there value in building an app or website for this use case? Would it be something others would use?
    • What features would you think are a must have for an MVP?
    • How can I build this in a way that later generalizes to multiple curators?
    • How do we maintain privacy if a company or job seeker doesn't want to share their full details initially? Or should the matching be purely curator driven?
    • I'd like to slowly start implementing this. What SQL table schema(s) would I need for this?
    • Please give me a 2 paragraph summary of this as a request I can give to a freelancer to build a low code version of this app for me
  • I wrote the below post on LinkedIn and got a lot of responses and it's hard to manage them. I would like to build a webapp for myself to scale this out and help me keep track of which job seekers there are and which hiring managers I know. It should let me keep track of private data and notes about each thing and also let me show some redacted public information with people's consent. I eventually want to make this multi user. Please write a feature specification document so I can know exactly what to build and which pages to add to my website.
    • Please create a roadmap and focus on how I can incrementally build an MVP
    • Please write me a database schema I can use for this in SQLite
  • I have received this rough job matching website proposal from a big tech engineer who wants to give back to the community by connecting job seekers and hiring managers with personalized matches and introductions. He wants to make it easier to manage the process. Please take this draft and turn it into a better specification to give to a junior engineer to implement. Keep it super focused on the MVP - even if it's just hardcoded HTML pages or low code for now it's fine. [ redacted long prompt with a few bullet points I wrote myself ]
    • This is a little too detailed, please make it much more concise so I can provide it to an AI chatbot as a prompt

As you can see, I was bouncing off ideas I already had, sounding them off of it, fact checking them, and just noodling by myself. I would say its advice there was 30% useful (a lot of superfluous detail, but some of the ideas it highlighted were things I'd not thought of for potential scaling issues and they influenced my design), but it got my brain thinking in the background.

Total time taken: 20 minutes of wall clock time, spent over a few days as I thought about this in the background.

Building

To get started, I took the above prompts with some minor edits and just shoved it into Claude:

Please design an initial prototype following the below specifications Milao MVP Specification A job-matching tool for a single curator to track and manage job seekers and hiring managers.

Pages:

  1. Open Jobs: • List of job opportunities with fields for company name, role, hiring manager info, posting link (optional), and tags. • Actions: Add, edit, or delete jobs.
  2. Candidates: • List of job seekers with fields for name, TL;DR description, intro blurb, contact info, skills/tags, and familiarity level. • Actions: Add, edit, or delete candidates.
  3. Todo List: • Track next steps for candidates, including fields for candidate name, task description, target contact, due date, and status. • Actions: Add, mark as complete, or delete tasks.

Implementation Notes: • Single admin user (no accounts). • Basic password protection for access. • Use lightweight tools or frameworks (plain HTML, or minimal backend like some REST API). • Prioritize basic CRUD functionality. Focus on simplicity and speed of development. Keep it minimal and functional for now.

This did a surprisingly good job of making something functional (pages looked clean, and complete). I only needed two follow up prompts:

  • This uses React. I don't know Javascript. Please design it in pure HTML and CSS so that I can use it as a set of static pages I can update the content myself manually.
  • Add an additional about page explaining why I'm doing this, use some standard filler text so I can update that myself

Total time taken: 30 minutes wall clock, spent over a few days of noodling on it in the background (I got sick).

I then finally had time to sit down and code. So I spun up a new cargo project, took some of the scaffolding from my last project, and got something up to serve static HTML. Then I went from there and started writing database schemas, templates, models for Job and Candidates, and some queries so that there was 'real' data in there, and it was all plumbed through instead of fake data. I didn't use any AI prompting here, but I did use the autocomplete in Cursor heavily, after copying in templates from past projects.

Total time taken: 3 hours.

Then it came time to do actually add the C and U part of CRUD. This is where it started to shine. I started using Cursor's composer to fill out things:

  • Add a new form for creating a job
    • Assume we may have a prior job passed in (so that this can also do edits) -- fill in those fields, using the pattern in job.html.tera
  • A lot of the styles in job_form do not exist in the css file so the form looks ugly. please add the relevant styles

The only "hard" thing here was adding the relevant files to the chat. It one-shotted the forms and code pretty much, and made it look passable, something I still cannot do myself.

I took that, then wrote the backend routes and database queries for this, using Cursor to write macros for some repetitive code (which annoyed me otherwise):

  • Turn this into a macro so I can do the same thing for other enums

Then it was time to effectively do the exact same code I just did for Jobs but for Candidates. I let Cursor do the whole thing for me in 5 minutes flat:

  • Add a form for creating/editing a candidate, similar to the job form
  • Write admin routes/forms to create/edit candidates similar to what exists for jobs

Time taken: 3 hours (majority of it was in setting up custom auth/copying the "right" template code I had for backends)

Then it was "just" time to deploy it, so I went and searched for a domain name, wrote an about page, created a Dockerfile, copied my usual deployment setup, and had this up and running on my VPS in about 2 hours. A chunk of time here was actually just DNS propagation latency (I got the first deployment wrong so had to wait for caches to expire overnight), and fixing 3 typos in dockerfile builds after multi-minute compiles (sigh). And, that was it!

Your choices are weird!

Well, yes they are. A few things I had to justify to myself:

  • Why not a no-code tool?
    • This could definitely have been done using a no-code tool. BUT it would take me longer to research the right one, instead of building this and I wanted to write code.
  • Why not Replit agent?
    • This is an excellent question. In this case, I prioritized deployment/maintenance convenience: I wanted a stack I'm familiar with. I like paying $0 additional cost, this takes under 20MB memory on my shared VPS and no CPU cost. This is fine.
  • 10 hours is still a lot for this!
    • It is! But now that I've done it, I suspect I can do the next in 5, now that I've figured out some of the quirks (a lot of this was first time startup cost). And I'm happy with that.
  • Why rust and no javascript?
    • Because I'm a luddite, I'm too scared to learn the trend of the day, and I enjoy rust. Plus for things like this, if I can get my responses in under 5ms from my backend (uncached), then it's just network latency. This is Good Enough (TM) for a lot of things.

Tech stack

NB: this is mostly for self reference. This is the stack I used:

Cherry on top: adding new features quickly

After launch I shared it with a friend for feedback. He suggested adding links to LinkedIn profiles where available.

I tried using cursor to do this and my mind was blown - this was one of the moments where I was seriously like "I'll be out of a job soon".

I wrote my database migration by hand to add three new fields. Then I just ran this prompt on 4 different files:

  • I just added the notes, todos, and linkedin_profile columns to the candidates table. Please update this file accordingly so I can create/update/view candidates

And it was done. The code worked. No changes needed. All in under 5 minutes.

Lessons learned

I learnt a lot and had fun doing this! With reflection, a few key takeaways showed up for me:

  • AI really helps get over the startup cost. My time's quite fragmented these days so it's super helpful to be able to toss an idea out, think about it in the background, ask another question, and page things out of my memory.
  • Autocomplete in the IDE is good and something I can't live without now.
  • It really helps to decide the tech stack/components you want to use upfront, and know which things you need to use before starting. AI can help you rubber duck design this, but you need to know what you're doing
  • Once you have that though, AI can really quickly help you go from that design to a real working product.
  • Phrasing your problems in small, tractable pieces makes it much easier for an AI to help
  • If you know you're doing somewhat repetitive work (e.g. adding type A, then type B, then type C) -- do one first, get it working e2e, then just ask the AI to repeat what you did. Way faster.
  • Just saying "fix this" or "this doesn't work" goes surprisingly far.
  • If optimizing for speed, focus on familiar tech rather than spending your mental energy learning new things (if you can avoid it)