I promised a friend I'd build a tool to monitor changes on a website and convert the updated articles to an RSS feed.
At first I tried using Django, which boasts “batteries included”. There is a Django library that handles scheduled tasks. I forgot the name—it was such a long time ago after all. What I remember is that it caused circular library dependencies and required setting up migrations, since it managed tasks and their run records in the database.
Months passed before I attempted the project again.
This time I used Go. I had built small projects in Go prior to this. I could unapologetically say “I know Go,” because who doesn’t, with its syntax being so transparent?
Yet it still took me a long time to finish the project.
There were conflicting incentives. On top of building the project, I wanted to learn new things. And it’s fair (even good) to learn new things along the way. I read about HTMX then opted for Alpine.js after comparing their respective syntaxes. At this point I didn’t want to build too much of a UI. Both promised interactivity with minimal scripting in HTML pages. Yet after some struggling with templating in Go, I missed JSX. I also found it difficult to wrap my head around embedding data into an HTML element using a custom attribute.
Then there was mission creep. When I set out to work on this project, the initial goal was to monitor one section on one website. Then I asked myself, wouldn’t it be more useful if I allowed people to add websites to track?
In the end product, you can add websites and sections. The app monitors website changes, scrapes pages whose URLs match a pattern, and extracts the title, author, publication date, and content using CSS selectors. All the updates are displayed in the RSS feed view.
Then I thought, who has time to read all this word soup? So I decided to add an API call to ask OpenAI to summarize the full text for me. Now, with these added features, I moved the UI from Go templates and Alpine.js to a full-blown React project.
GitHub Copilot helped a lot during development. One shift in my mindset especially helped me accelerate the development process.
At the beginning, the questions I asked LLMs were “how do I do this?” Upon getting a response, I'd read it carefully, trying to understand the suggested approach and the reasoning behind it.
While good for learning, this significantly slowed me down. As coding agents became more capable, I soon slipped into asking “Do that for me.” Then the whole process became much faster and more pleasant.
I have a habit of taking notes and creating Anki cards. I thought conversations with LLMs were a good source of knowledge. In the end I realized most of these conversations are transient, scenario-specific, and not worth memorizing.
I’m sure there is a lot of background knowledge behind how each function is called and how each code block is structured, and such knowledge is useful for someone like me who’s relatively new to Go.
But there's a cadence to learning and building. To use a painting analogy, laying out the perspective and applying colors are both important. “How do I do it?” questions are the latter. When you let coding agents solve these problems, you can focus on the perspective part, which is more relevant to the structure of the whole picture.
In a real problem I faced, “How do I handle a nil value when I parse a row of SQL query results?” is about a detail. The fact that you need to handle the nil value is more about the whole. As long as you know you need to handle that, I figure it's fine to delegate the details to coding agents.