journal // Jan 16, 2025

Indie Hacker Diaries #33: Don't Use AI as a Crutch

Indie Hacker Diaries #33: Don't Use AI as a Crutch

About a year and a half ago, I decided to build my own documentation system.

While it works, the experience of creating, editing, and adjusting the navigation for the docs has been a nightmare.

When I shipped Parrot last fall, I used Mintlify as a shortcut. The only problem with the service is that it blocks updates if the Git user making the commits doesn’t match the Git user connected to Mintlify. To get around it, I just created a fresh SSH key to match the user, but I realized if I wanted to use Mintlfiy for other projects, I’d have to keep generating keys (or perform some uncomfy slight of hand).

Instead, I decided to pull a Picasso and “steal” Mintlify’s concept of using a config file combined with static markdown files in my project (as opposed to rendering from a database like the current version of my docs system). The advantage was that I wouldn’t have to play SSH key roulette with Mintlify, or, end up paying them for access (which at $150/mo for the lowest plan, it’s a steep ask on an indie hacker budget).

After a bit of noodling with a prototype, I decided to dig in and see what was possible. The one thing that has been a constant snag for me has been finding a documentation tool that lets you do custom components in plain HTML. Mintlify uses MDX (a variant of Markdown that lets you include React components directly in Markdown), but being the stubborn old man that I am, I just wanted something simple and HTML based.

I stumbled across Stripe’s Markdoc library, but after an hour of trying to figure out how to use their plain HTML components feature (which is secondary to the default usage of React components), I gave up and said “I bet I can just build a custom parser.” Sure enough, with a little help from Claude, in about 10 minutes I had a working solution. The API? A simple embed tag (based on Markdoc’s syntax) that maps to a function that returns a string (or template literal) of HTML.

For the curious, here’s what the embed tag looks like in Markdown:

{% code theme="light" title="Terminal" %}
npm i -g @joystick.js/cli
{% /code %}

And the associated function to render the corresponding HTML:

code: (attributes = {}, children = '') => {
  return `<div class="mod-code">
  ${attributes?.title ? `<header>
    <p>${attributes.title}</p>
    <i class="mod-icon-clipboard-copy"></i>
  </header>` : ''}
  <pre data-theme="${attributes?.theme || 'light'}" class="language-javascript"><code>${children}</code></pre>    
</div>`;
},

The function receives the variables and “children” (any Markdown between the open and close tag statement in the main Markdown file) and then using the same approach I use for Joystick components, just uses interpolation to embed variables. I also grabbed a copy of Joystick’s each() method for helping to loop over lists of stuff.

All of this in ~10 minutes. I’ve suggested it before, but this (in my opinion) is how AI should be deployed. Sure, you can stitch together a bunch of code it spits out into a working prototype-grade app, but the real power lies in combining your own skill set with an LLM. If you’re trying to ship a SaaS or any software, it’s the difference between spending an extra month or two building.

That is worth it’s weight in gold.

And this is something worth harping on: it’s kind of scary (and sad) to see developers moving in the direction of solely using an LLM to write code.

That 10 minute timeline only happened because I was able to apply the knowledge and experience to know that the Markdoc solution wasn’t working and specifically what to ask for. Had I just been starting out and had no concept of what the code was doing, I would have either fumbled with the Markdoc approach (or accepted just using React components) or even possibly, given up entirely.

Earlier this week, I got a call from a long-time friend. His 8 year old daughter had asked him about learning to program level designs in Minecraft.

We talked about how best to help her start learning and then I had him put her on speakerphone. I had sent him a link to some Minecraft coding tutorials and said “I sent your dad a link that he can pull up to get you started. You can figure this out, but you gotta sit down and do the tutorials. If it’s hard, don’t give up. Just keep going. If you understand the basics, you’ll be able to build anything.”

Excitedly, she said “okay, I will!” Before we hung up, I told my friend that it’s exciting she wants to learn and to keep encouraging her. I said “if she starts learning now, by the time she gets to college age, with all of her would-be competition only understanding how to code with AI, she’ll be a sharpshooter.”

And I’d give the same advice to anyone reading this who’s just getting started and trying to learn how to write code—whether you’re trying to build a SaaS, make a game, or any other kind of software.

AI and LLMs are a great tool to assist in the coding process, but taking the time to really learn what the code being spit out is doing will dramatically change how much value (and speed) you can get out of using them.

Slow in the short-term, fast in the long-term.

Or, as one of my all-time-favorite one-liners by Baltasar Gracian suggets: “make haste slowly.”

Written By
Ryan Glover

Ryan Glover

CEO/CTO @ CheatCode