<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Internet Menace, Again</title>
    <link>https://internetmenace.com</link>
    <description>New wiki sections, new templates, and changelog entries from the Internet Menace, Again curriculum.</description>
    <language>en</language>
    <lastBuildDate>Mon, 10 Aug 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://internetmenace.com/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>v1.4.0: The template library grows to fifty</title>
      <link>https://internetmenace.com/changelog</link>
      <guid isPermaLink="true">https://internetmenace.com/changelog</guid>
      <pubDate>Mon, 10 Aug 2026 00:00:00 GMT</pubDate>
      <description>Nine templates became fifty: payments, auth, email, analytics, deploys, data pipelines, integrations, and a bench of new agents. Every one is a markdown file you copy, fill in, and hand to your agent. Section 9.2 still applies: write the fifty-first and send it back.</description>
    </item>
    <item>
      <title>v1.3.0: Internet Menace Foundations</title>
      <link>https://internetmenace.com/changelog</link>
      <guid isPermaLink="true">https://internetmenace.com/changelog</guid>
      <pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate>
      <description>The original 2024 curriculum is back, reorganized as sections 0.7 through 0.17. If you finished v1, it&apos;s a reunion; if you didn&apos;t, it&apos;s the 180-day foundation this whole site quietly assumes.</description>
    </item>
    <item>
      <title>v1.1.0: This is not an AI guide</title>
      <link>https://internetmenace.com/changelog</link>
      <guid isPermaLink="true">https://internetmenace.com/changelog</guid>
      <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
      <description>&quot;AI&quot; is a shelf, not a genre. The new manifesto page is about asking which record is actually playing before you pay for the shelf.</description>
    </item>
    <item>
      <title>v1.2.0: Stacks: eight opinionated ways to build</title>
      <link>https://internetmenace.com/changelog</link>
      <guid isPermaLink="true">https://internetmenace.com/changelog</guid>
      <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
      <description>Eight opinionated stacks, from a weekend Vercel-and-Supabase startup to causal agent observability with PyRapide. Hand your agent a coherent set of tools instead of letting it improvise one.</description>
    </item>
    <item>
      <title>Template: Webhook Receiver</title>
      <link>https://internetmenace.com/templates/webhook-receiver</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/webhook-receiver</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A webhook is another company&apos;s server calling yours: Stripe telling you a payment cleared, GitHub telling you someone pushed, Shopify telling you an order landed. Your side of the deal is one public URL, and that URL has three enemies. Strangers, because anyone who finds the URL can POST fake events to it, and &quot;anyone can tell my server a payment cleared&quot; is a sentence you should read twice. Duplicates, because every serious webhook provider retries on timeout or error, which means delivering the same event two or three times is normal operation, not a bug. And your own slow code, because if handling the event takes longer than the sender&apos;s timeout, it marks the delivery failed and retries, and now your slowness is manufacturing duplicates.

The shape that survives all three is the same regardless of provider, and it is worth memorizing: verify the signature on the raw bytes, insert the event ID into a table with a unique constraint, return 200, and do the real work after. Verification keeps strangers out. The unique constraint is your dedupe: the database refuses the second insert, so a retried delivery becomes a no-op without any clever code. Returning 200 fast, before processing, keeps the sender&apos;s timeout from ever seeing your slow parts. Every piece of this spec is one of those three moves.

The naive version, the one an agent writes if you just say &quot;handle the Stripe webhook,&quot; does the work inline and returns 200 at the end. It passes every test you&apos;ll think to run, because your tests don&apos;t time out and don&apos;t retry. Then production delivers a duplicate on a slow night and a customer gets charged twice, or emailed twice, or shipped twice. This is the template other integration templates on this site point at when they say &quot;dedupe before acting.&quot; Fill in your provider; the skeleton does not change.</description>
    </item>
    <item>
      <title>Template: Slack Integration</title>
      <link>https://internetmenace.com/templates/slack-integration</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/slack-integration</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Slack integrations come in two directions, and mixing them up wastes an afternoon. Outbound: your code posts messages into a channel, which needs an incoming webhook URL and nothing else. Inbound: someone types `/yourcommand` in Slack and your server has to answer, which needs a public endpoint, request verification, and respect for one brutal deadline. Most projects want outbound first. It is ten lines of code and it makes your system feel alive: deploy finished, order came in, backup failed. Start there even if you came for the slash command.

The slash command is where the real engineering lives, and it lives in one number: three seconds. Slack sends your endpoint a request when someone runs the command, and if you have not responded in three seconds, the user sees a timeout error, no matter how well your code was doing. The pattern that survives is acknowledge-then-work: reply immediately with &quot;on it,&quot; do the slow thing, then deliver the answer through the `response_url` Slack handed you, which stays valid for thirty minutes. Agents reliably write the naive version that does the work inline, and it even works in testing, because your test query was fast. Production queries are not.

The other thing agents skip is verifying that requests actually come from Slack. Your slash-command endpoint is a public URL; anyone who finds it can POST to it. Slack signs every request, and checking that signature is the difference between an integration and an open door. The spec below treats verification as a hard requirement, and for the general theory of receiving webhooks safely (dedupe, retries, idempotency), see the webhook-receiver template; this one bakes in the Slack-specific parts.</description>
    </item>
    <item>
      <title>Template: File Uploads to S3</title>
      <link>https://internetmenace.com/templates/file-uploads-s3</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/file-uploads-s3</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>There are two ways to get a user&apos;s file into cloud storage. Route it through your server, which means every 200MB video ties up your server&apos;s memory and bandwidth on the way past, and on serverless platforms slams into request-size limits around a few megabytes. Or have the browser upload straight to S3, with your server&apos;s only job being to sign a short-lived permission slip first. The second way is the right way, it is what the presigned URL exists for, and it is what this spec builds.

The flow is three steps and worth having in your head before the agent writes anything. The browser asks your server &quot;I want to upload a JPEG, 4MB.&quot; Your server decides yes or no, and if yes, generates a presigned URL: a link that permits exactly one PUT, to one key it chose, expiring in minutes. The browser PUTs the file to that URL, straight to S3, never touching your server. Then the browser tells your server &quot;done,&quot; and the server verifies the object actually landed before recording it. Your AWS credentials never leave the server; the browser only ever holds the temporary slip.

What agents get wrong here is not the happy path, which every SDK tutorial covers. It is the defaults around it: buckets left publicly readable, filenames taken from the user and used as keys (which is how `../../etc/passwd` and overwritten files happen), size limits enforced only in JavaScript where anyone with curl can ignore them, and no answer for the user who requests a URL and never finishes the upload. The spec below closes each of those, and the bucket stays private the entire time: downloads are presigned too.</description>
    </item>
    <item>
      <title>Template: Postgres Schema Starter</title>
      <link>https://internetmenace.com/templates/postgres-schema-starter</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/postgres-schema-starter</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every table you will ever create has to answer the same three questions: how are rows identified, when did things happen to them, and what happens when someone deletes one. Most people answer these three questions differently on every table, on the fly, while thinking about something else. Six months later the users table has integer ids, the orders table has UUIDs, half the tables know when they were updated and half don&apos;t, and &quot;deleted&quot; means four different things in four places. None of those decisions was wrong. Making them inconsistently was.

This file answers the three questions once, as SQL you can run today, with the reasoning in comments right where each decision sits. That placement is deliberate: your agent reads schema files, and conventions stated where they apply are conventions that survive the tenth table, long after the chat where you explained them has scrolled away. It is data-shape thinking (§5.1) in its most concrete form.

The defaults are boring on purpose: UUID keys, timestamps on everything, soft deletes via a nullable timestamp. Boring is what you want load-bearing infrastructure to be. Where a default has a real cost, the comment says so, and the adaptation notes cover the honest cases for deviating. Rename the example table, keep the skeleton, and apply the conventions to every table that follows.</description>
    </item>
    <item>
      <title>Template: Postgres + pgvector RAG Pipeline</title>
      <link>https://internetmenace.com/templates/pgvector-rag</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/pgvector-rag</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Before you provision a dedicated vector database, look at what you already run. If there is a Postgres in your stack, pgvector turns it into a vector store: your chunks live in a table, joined to real metadata, backed up by the backups you already have, filtered by the SQL you already know. A purpose-built vector store earns its place at scales most projects never reach. Until then, a second database is a second thing that pages you.

The part of RAG nobody puts in the demo: retrieval is where these systems die. The generation step gets the attention, but if retrieval hands the model the wrong chunks, the model composes a fluent, confident answer out of the wrong facts, and fluent-but-wrong is worse than no answer because people believe it. This spec spends its effort accordingly. Vector similarity alone misses exact terms: part numbers, function names, people. Keyword search alone misses phrasing it hasn&apos;t seen. The pipeline below runs both and fuses the results, because each one covers the other&apos;s blind spot, and the blind spots are where your users live.

The section your agent will try to skip is the eval, which is precisely why it&apos;s in the spec with teeth. Twenty real questions with known-correct sources, run before and after every retrieval change. Without it, every tuning decision is vibes, and &quot;it seems better&quot; is how retrieval quality drifts downward one clever tweak at a time. With it, tuning is a measurement. Twenty questions is one honest afternoon.</description>
    </item>
    <item>
      <title>Template: Document Ingestion Pipeline</title>
      <link>https://internetmenace.com/templates/document-ingestion-pipeline</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/document-ingestion-pipeline</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Ingestion is the unglamorous half of every retrieval system, and it is where the real failures start. If a document got mangled on the way in, no amount of clever querying gets the truth back out. The naive version is a script: loop over files, chunk, embed, insert. It works exactly once. Run it again and every chunk exists twice, search returns duplicates, and you paid the embedding bill twice for the privilege.

The property that separates a pipeline from a script is idempotency: run it on the same folder five times and the result is identical to running it once. You get there by making the pipeline check before it works. Every source file gets a content hash; unchanged hash means skip, changed hash means the old chunks die and new ones replace them, in one transaction, so no query ever sees half a document. This also gives you the thing scripts never have: a table you can query to ask &quot;what is actually in my index, and when did it get there.&quot;

The other discipline is treating ingestion as a state machine rather than a loop. Each document moves through discovered, parsed, chunked, embedded, indexed, or lands in failed with an error message attached. When file 412 of 500 is a corrupt PDF, it fails alone and visibly; the other 499 proceed, and the pipeline can resume from wherever it stopped without redoing finished work. A loop that dies at 412 and restarts from zero re-embeds 411 documents to get one file further, and at API prices that habit shows up on your invoice (§4.6).</description>
    </item>
    <item>
      <title>Template: CSV Import/Export Spec</title>
      <link>https://internetmenace.com/templates/csv-import-export</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/csv-import-export</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every internal tool converges on the same feature request: &quot;can I just upload a spreadsheet?&quot; And every naive implementation of it converges on the same incident: someone uploads 2,000 rows, row 847 has a date typed as &quot;next tuesday&quot;, and now either the whole import died with a stack trace nobody can read, or, worse, 846 rows imported and nobody knows which ones. The person doing the upload is not a developer. They have a spreadsheet and a deadline, and the tool&apos;s job is to tell them exactly what&apos;s wrong in language that names their rows, not your exceptions.

The design that survives contact with real spreadsheets has three properties. Validate everything before writing anything: an import is all-checked-then-applied, never check-as-you-go. Default to dry run: the first pass produces a report (&quot;1,994 rows OK, 6 problems, nothing imported yet&quot;), and applying is a separate, deliberate step. And report errors per row, per column, in a file they can open in Excel, fix, and re-upload, because that is the actual workflow: upload, fix six cells, upload again. That loop happening twice is normal. That loop being pleasant is the feature.

CSV itself will fight you more than the database will. Excel exports smuggle in a byte-order mark, Windows line endings, commas inside quoted fields, dates in whatever format the machine&apos;s region settings felt like, and at least one column renamed by a helpful human. The parsing rules below exist because each one is a support ticket I am saving you from filing. Hand the spec to your agent whole; the boring parts are the load-bearing parts.</description>
    </item>
    <item>
      <title>Template: Vercel Deployment Spec</title>
      <link>https://internetmenace.com/templates/vercel-deploy</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/vercel-deploy</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Vercel&apos;s pitch is that deployment is one button, and the pitch is honest. Connect the repo, push to main, the site is live. That is exactly why it needs a spec: the button works whether or not you have thought about what is behind it, and the failures it enables are quiet ones. The site deploys fine. It just happens to be talking to the wrong database.

The thing to internalize is that Vercel gives you three environments: Production, Preview, and Development. Every branch you push gets its own live Preview URL, which is genuinely great, and which also means every pull request is a running copy of your app. If that copy holds your production Stripe key, then every experiment, every half-finished agent branch, every &quot;let me just try something&quot; can charge a real card. Scoping environment variables per environment is not an advanced feature. It is the whole job.

Hand this spec to your agent to do the setup and wiring, but set the secret values in the Vercel dashboard yourself. An agent that never saw your production key cannot paste it somewhere it shouldn&apos;t. Fill in the brackets, then work the post-deploy checklist personally: the agent verifying its own deployment is the fox auditing the henhouse.</description>
    </item>
    <item>
      <title>Template: Scheduled Jobs Spec</title>
      <link>https://internetmenace.com/templates/cron-jobs</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/cron-jobs</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A cron job is code that runs when nobody is watching, which means it fails when nobody is watching. That is the entire discipline in one sentence. An interactive app that breaks gets a bug report within the hour. A nightly job that breaks gets discovered in six weeks, when someone asks why the digest emails stopped, and by then you&apos;re not fixing a bug, you&apos;re reconstructing six weeks of missed work.

On Vercel, a cron job is just an HTTP route that Vercel promises to call on a schedule, and that shape has two sharp edges. First, the route is a public URL: anyone who finds it can trigger your job, so it authenticates or it doesn&apos;t ship. Second, schedulers deliver &quot;at least once,&quot; not &quot;exactly once.&quot; Retries, overlapping runs, and manual triggers all mean your job will eventually run twice for the same period, and it has to be idempotent: running it twice produces the same result as once. A job that sends invoices needs this property before it sends its first invoice, not after its first double-bill.

The spec below covers the Vercel path, the contract every job handler must meet regardless of platform, and the honest line for when serverless cron stops fitting: jobs longer than your platform&apos;s timeout, or schedules tighter than a minute, belong on a worker. The dead-man&apos;s switch is not optional decoration. &quot;The job stopped running&quot; and &quot;the job ran and failed&quot; are different failures, and only the switch catches the first kind.</description>
    </item>
    <item>
      <title>Template: GitHub Actions CI Workflow</title>
      <link>https://internetmenace.com/templates/github-actions-ci</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/github-actions-ci</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>CI is a machine that runs your checks every time code moves, without being asked and without getting bored. That last part is the point. You will run the tests before merging for about two weeks. Then you&apos;ll be busy one afternoon, and the agent will say the tests pass, and you&apos;ll take its word for it, and that is the merge that breaks production. The robot does not get busy. It runs everything, every push, forever, and it does not accept &quot;it worked locally&quot; as evidence.

This matters double when an agent writes most of your code. Agents produce plausible code quickly, and plausible is exactly the quality that slips past a tired human reviewer. A CI run is a checkpoint the agent cannot charm its way through: the lint either passes or it doesn&apos;t, the build either compiles or it doesn&apos;t. Green checkmarks on the PR are the difference between &quot;the agent says it&apos;s done&quot; and &quot;it&apos;s done.&quot;

The template is a working workflow file plus a short spec around it. The spec matters because the file alone isn&apos;t the whole job: a CI that runs but doesn&apos;t block merging is a smoke alarm with the battery out. The branch protection step at the end is what gives it teeth.</description>
    </item>
    <item>
      <title>Template: Docker Compose Local Stack</title>
      <link>https://internetmenace.com/templates/docker-compose-local</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/docker-compose-local</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>&quot;Works on my machine&quot; is not a defense, it is a confession. It means your app depends on things that live outside the repo: the Postgres you installed with Homebrew two years ago, the Redis that autostarts on login, the one environment variable you exported in a terminal that has since been closed. Your agent inherits none of that. Neither does your laptop after it dies, and laptops die.

Docker Compose fixes this by writing the whole environment down. One file declares your app, its database, and its dependencies, with versions pinned. `docker compose up` builds that world from nothing; `docker compose down` removes it without residue. The database version in the file is the database version, period. When your agent needs to run the app to test its own work, it reads this file instead of guessing what is installed, and its guesses about your environment are the source of half its weirdest failures.

The template below is a working compose file for the most common shape: one app, one Postgres, one Redis, wrapped in a short spec telling the agent how to adapt it and which commands do what. The annotations in the YAML are load-bearing. The healthcheck, in particular, is the difference between an app that waits for its database and an app that races it and loses at random, and intermittent startup crashes are miserable to debug precisely because they are intermittent.</description>
    </item>
    <item>
      <title>Template: Backups and Restore Runbook</title>
      <link>https://internetmenace.com/templates/backups-restore-runbook</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/backups-restore-runbook</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Nobody has ever needed a backup. People need restores. A backup is a file you hope contains your data; a restore is the proof. Plenty of businesses have discovered, on the worst day of their year, that they owned three years of nightly backups and zero working restores: the dump was empty, the credentials had rotated, the one person who knew the procedure had left. The backup job ran green every night. Green meant &quot;a file was written,&quot; not &quot;your data is safe,&quot; and nobody had ever checked which.

That is why this template is a runbook and not a script. The script is the easy part, and your agent will write it in five minutes. The runbook is the part that makes it real: what gets backed up, on what schedule, kept how long, stored where, and, as a first-class scheduled step and not a someday, the drill where you restore a backup onto a scratch database and verify the data is actually in it. If the drill isn&apos;t on a calendar, it doesn&apos;t exist. You will not spontaneously test restores on a quiet Tuesday. Nobody does.

Two numbers anchor everything, and you should pick them before any tooling: how much data you can afford to lose (if the answer is &quot;a day,&quot; daily backups are fine; if it&apos;s &quot;an hour,&quot; you need more than dumps), and how long you can afford to be down while restoring. Everything else in the runbook is machinery serving those two numbers. Fill it in with your agent, then put the drill dates on your actual calendar before you close the tab.</description>
    </item>
    <item>
      <title>Template: Sentry Error Tracking</title>
      <link>https://internetmenace.com/templates/error-tracking-sentry</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/error-tracking-sentry</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Right now, your deployed app&apos;s errors go nowhere. A user hits a crash, sees a blank screen, closes the tab, and the only record of it is their opinion of you. Error tracking is how production tells you what broke before users bother to, and Sentry is the standard tool for it. The install is genuinely five minutes. The five minutes is also where most people stop, and a stopped-at-install Sentry is nearly worthless.

Here&apos;s why. Production JavaScript is minified, so without sourcemaps every stack trace reads like `t is not a function at a.js:1:48213`, which tells you a thing broke somewhere in your app, a fact you already had. Without releases, Sentry can&apos;t tell you which deploy introduced the error, which is usually the single most valuable clue, because &quot;what did we just ship&quot; is the first question anyway. And without alert rules, errors pile up in a dashboard nobody opens; you find out about the crash from a user email, which is the exact outcome the tool exists to prevent.

So this spec treats sourcemaps, releases, and alerts as part of the install, not as advanced options, and it adds the two hygiene items that keep Sentry useful past week one: scrubbing user data you shouldn&apos;t be storing, and filtering the noise (browser extensions, bots, ad-blocker fallout) that otherwise trains you to ignore the feed. An alert channel you&apos;ve learned to ignore is the same as no alert channel, with worse morale.</description>
    </item>
    <item>
      <title>Template: PostHog Setup</title>
      <link>https://internetmenace.com/templates/posthog-setup</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/posthog-setup</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Analytics is the one system where bugs don&apos;t throw errors. Wire PostHog wrong and everything looks fine: the dashboard fills with numbers, the charts go up and to the right, and six months later you make a real decision based on data that was double-counted, half-anonymous, or missing every purchase that happened while a tab was closed. Nothing crashed. You just steered with a bent compass.

The wiring mistakes are specific and repeatable, which is good news, because it means a spec can prevent them. Single-page apps navigate without full page loads, so pageviews need to be captured on route change or you&apos;ll record one view per visit and wonder why your funnel starts at the front door and ends there too. `identify` ties events to a user; call it with your database&apos;s user id, not an email, because emails change and when one does, that user&apos;s history splits in half. And the events you actually bill decisions on, signups and payments, belong on the server, because ad blockers eat somewhere around a third of client-side events and they do not eat them evenly.

One more habit this spec bakes in: every event that gets captured is written down first, in a small table your agent keeps in the repo. Untracked event sprawl is how you end up with `signup`, `sign_up`, and `user_signed_up` all meaning the same thing and no funnel that trusts any of them. The event taxonomy template goes deeper; this spec just refuses to let the sprawl start.</description>
    </item>
    <item>
      <title>Template: Event Taxonomy</title>
      <link>https://internetmenace.com/templates/event-taxonomy</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/event-taxonomy</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Six months from now you will open your analytics tool to answer one question: where do people drop off before paying? And you will find `signup`, `sign_up`, `Signup Completed`, and `user_registered`, all live, all slightly different, none documented. Which one goes in the funnel? Nobody remembers. The person who added the third one was you, and you don&apos;t remember either. The data was collected faithfully the entire time; it just can&apos;t be queried into meaning anymore.

This happens because event names get invented at the call site, one at a time, in the heat of shipping the feature. Each individual name looked fine. Taxonomy is the boring fix: one naming convention, one tracking plan file in the repo, and one rule that no event ships without a row in the plan. It costs about an hour up front and roughly nothing per event after that. The alternative costs you every funnel you&apos;ll ever want to build.

This matters double when agents write your code, because an agent asked to &quot;add analytics to this feature&quot; will cheerfully invent event names in whatever style the surrounding file suggests. Give it this plan and the naming rules become constraints it follows instead of decisions it improvises. The template below is the plan file itself: fill in the starter rows, commit it, and point every future analytics task at it.</description>
    </item>
    <item>
      <title>Template: Transactional Email Set</title>
      <link>https://internetmenace.com/templates/transactional-email-set</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/transactional-email-set</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every product that has accounts needs exactly three emails before it needs any others: a welcome when someone signs up, a receipt when someone pays, and a reset when someone forgets their password. Ship these three and you can ignore email for months. Skip them and users assume the product is abandoned, accountants chase you for receipts, and locked-out customers simply leave.

Transactional email is not marketing email, legally or socially. These messages are triggered by something the user did, they contain information the user needs, and that&apos;s the entire justification for sending them. The moment a &quot;quick product update&quot; sneaks into your receipt template you&apos;ve converted a message people trust into one they filter, and you&apos;ve done it in the one channel where trust was the whole point.

Two of the three have teeth. Receipts must be idempotent: a payment webhook that retries, and they all retry, must not produce a second receipt, because a duplicate receipt reads as a duplicate charge and generates a support ticket every single time. And the reset email is a security surface: it must not confirm whether an account exists, and its token must be single-use, short-lived, and never logged. The spec below hands your agent all of that as requirements, not suggestions.</description>
    </item>
    <item>
      <title>Template: Contact Form with Resend</title>
      <link>https://internetmenace.com/templates/resend-contact-form</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/resend-contact-form</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The contact form is usually the first real backend a site needs. A `mailto:` link is not one: it hands your address to every scraper that reads your HTML, and on half the phones on earth it opens nothing at all. The grown-up version is small: a form, a serverless function, and an email API. Resend is the API here because the free tier covers any normal contact form many times over and the integration is one POST request.

Spam is the part people get backwards. The instinct is a CAPTCHA, which taxes every legitimate visitor to inconvenience bots that increasingly solve them anyway. Start with the cheap tricks instead: a honeypot field that humans never see and bots dutifully fill, and a rate limit so one IP can&apos;t submit four hundred times a minute. That combination kills the overwhelming majority of form spam and costs your actual visitors nothing. Escalate only if reality demands it.

The one rule you cannot bend: the Resend API key lives in an environment variable on the server. The moment it appears in browser-side code it belongs to the internet, and the internet will use your domain to send things you will have to apologize for. That&apos;s §6.4, and this template is where a lot of people meet it for the first time.

Hand the spec below to your agent from inside your site&apos;s repo.</description>
    </item>
    <item>
      <title>Template: Supabase Email Auth</title>
      <link>https://internetmenace.com/templates/supabase-auth-email</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/supabase-auth-email</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Do not build your own auth. Not because you couldn&apos;t: because the failure modes are invisible until they&apos;re catastrophic, and password storage is a problem the industry already solved and keeps re-solving every time someone&apos;s homemade version leaks. Supabase gives you signup, login, email confirmation, and session management on top of Postgres, and your job shrinks to wiring it in without undoing its guarantees.

That wiring is where beginners get bitten, in two specific places. First, the confirmation flow: a user signs up, Supabase sends a confirmation email, and the link in it has to land somewhere in your app that completes the handshake. Skip that route and every new user hits a dead end with a valid account they can&apos;t use. Second, where you check the session: a login check that lives only in client-side JavaScript is a curtain, not a lock. Anyone can call your API directly, no browser required. The session check has to happen on the server, on every protected route, every time.

This spec hands your agent the full circuit: signup, confirm, login, logout, protected routes checked server-side, and a profiles table with row-level security so the database enforces who sees what even if a bug slips through the app layer. Defense at the data layer is not paranoia. It&apos;s the layer that holds when the other one doesn&apos;t.</description>
    </item>
    <item>
      <title>Template: Role-Based Access Control</title>
      <link>https://internetmenace.com/templates/role-based-access</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/role-based-access</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Hiding the admin button is not access control. The button is a suggestion; the API route it calls is the door, and if the door only checks &quot;is logged in&quot; rather than &quot;is allowed&quot;, every member of your app is one copied fetch request away from being an admin. This is the single most common security hole in agent-built apps, because the happy path demos perfectly: the admin sees admin things, the viewer doesn&apos;t, and nobody in the demo thought to ask the database directly.

So this spec enforces roles at the database layer with row-level security. The app checks roles too, for UX and for clean error messages, but the policy that actually holds is the one Postgres evaluates on every query. A bug in your route handler, a forgotten check in a new endpoint, an agent that helpfully adds a query somewhere: RLS catches all of it, because the database doesn&apos;t care how the query arrived.

Two design decisions in here are load-bearing, so know why they exist. Roles live in their own table, not as a column on profiles, because profiles are user-editable and a user who can edit the row that stores their role will eventually promote themselves. And the role lookup happens through a `security definer` function, because an RLS policy that queries a table which itself has RLS recurses; the function is the standard Postgres escape hatch, and your agent will get this wrong without being told.</description>
    </item>
    <item>
      <title>Template: Password Reset Flow</title>
      <link>https://internetmenace.com/templates/password-reset-flow</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/password-reset-flow</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Password reset is the back door to every account in your app. An attacker who can&apos;t guess a password doesn&apos;t need to if the reset flow will hand them the account instead, and reset flows fail in quiet ways that demo perfectly. The form works, the email arrives, the password changes, everyone moves on. Meanwhile the token never expires, works twice, and the &quot;no account with that email&quot; error message is happily confirming to a stranger exactly which of your users exist.

Four properties separate a real reset flow from a liability, and this spec treats every one as a hard requirement. Tokens expire, in minutes, because reset emails sit in inboxes for years and an inbox is only as private as its weakest moment. Tokens are single-use, because a link that works twice works for whoever sees it second. The request endpoint answers identically whether the email exists or not, because &quot;we couldn&apos;t find that account&quot; is a user-enumeration oracle: it lets anyone test your user list one address at a time. And a successful reset kills every existing session, because the entire reason people reset passwords is the fear that someone else is already inside; a reset that leaves the intruder&apos;s session alive is theater.

If you&apos;re on Supabase or another managed auth provider, most of this is handled and your job is to not break it: the spec marks exactly which parts remain yours. If you&apos;re rolling the flow yourself, the token table and handler sketch are in here too. Either way, hand your agent the spec, then run the verification list personally. This is the one flow where &quot;the agent says it works&quot; is not good enough.</description>
    </item>
    <item>
      <title>Template: Stripe Webhook Handler</title>
      <link>https://internetmenace.com/templates/stripe-webhooks</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/stripe-webhooks</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every Stripe integration is secretly a webhook integration. Checkout, subscriptions, refunds, disputes: the browser sees a redirect, but the facts arrive later, server to server, as events. If your handler is sloppy, every feature built on top of it inherits the sloppiness, and billing bugs are the expensive kind. Customers notice them, and they notice in the direction that costs you either money or trust.

Three properties make a webhook handler trustworthy, and none of them are optional. It verifies signatures against the raw request body, because an unverified webhook endpoint is a public API that edits your billing table; anyone with curl can call it. It is idempotent, because Stripe delivers at-least-once and will happily send you the same event twice; a handler that isn&apos;t idempotent sends two receipts, grants two credits, or double-fulfills an order. And it treats the event as a doorbell, not a database: events can arrive out of order, so on anything that matters you fetch the current object from the Stripe API and write that, instead of trusting a payload that may already be stale.

There is a fourth rule that isn&apos;t about the handler at all: UI state never substitutes for webhook truth. The success redirect is a hint. The customer&apos;s card can be declined on retry, the subscription can lapse, the dispute can land, all without a single click in your app. The webhook is where the database learns the truth, which means it is the only code allowed to write it.

This spec builds the handler as shared infrastructure: verify once, dedupe once, then dispatch to small per-event functions. Hand it to your agent before you build the features that depend on it.</description>
    </item>
    <item>
      <title>Template: Stripe Subscription Billing</title>
      <link>https://internetmenace.com/templates/stripe-subscription</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/stripe-subscription</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Here is how most subscription integrations die. Someone wires up the Checkout button, sees the success page, and updates the database right there on the redirect. It works in the demo. Then month two arrives, a card gets declined, Stripe cancels the subscription, and the app never hears about it because nobody clicked anything. The customer keeps full access, forever, free. That is not a hypothetical: it is the default outcome of trusting the browser to tell you about money.

The fix is a rule, and this spec enforces it: the webhook handler is the only code allowed to write billing state. Checkout starts the process, the customer portal lets people cancel and update cards without you building any of that UI, and the webhook is where the database learns what actually happened. Everything else just reads.

The other thing this spec bakes in: Stripe&apos;s customer portal instead of hand-rolled cancel and upgrade screens. People burn weeks building subscription management UI that Stripe already hosts, keeps compliant, and updates when card networks change the rules. Your job is one redirect. Take the free win.

Hand this to your agent with the placeholders filled in. It assumes auth already exists; if it doesn&apos;t, build that first, because a subscription without a user to attach it to is just a donation.</description>
    </item>
    <item>
      <title>Template: Stripe One-Time Checkout</title>
      <link>https://internetmenace.com/templates/stripe-one-time-checkout</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/stripe-one-time-checkout</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Selling one thing once is the easiest money problem you will ever have, which is exactly why people get it wrong: it looks too simple to need a spec. You make a Checkout Session, the customer pays, they land on your thank-you page, and you hand over the goods right there in the page code. Then someone&apos;s connection drops between paying and redirecting, and you have a paid customer staring at nothing, emailing you at 11pm. Or someone bookmarks the success URL and gets the goods for free every time they visit it.

The thank-you page is decoration. Stripe tells you about the payment the reliable way, server to server, through a webhook, and that is where fulfillment happens: mark the order paid, send the download link, grant the access. The page the customer lands on just reads the order and displays its state. If the redirect never happens, they still get what they paid for. That is the entire trick, and it&apos;s the difference between a checkout that works in a demo and one that works on a bad hotel wifi.

This spec is deliberately smaller than the subscription one. No customer portal, no recurring state machine, no plan table. One product, one payment, one webhook event that matters. Fill in the placeholders and hand it to your agent.</description>
    </item>
    <item>
      <title>Template: Research Agent</title>
      <link>https://internetmenace.com/templates/research-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/research-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A research agent without citation rules is a confident summary machine. It reads three pages, remembers a fourth that doesn&apos;t exist, and hands you a tidy report where the real findings and the invented ones are typeset identically. You can&apos;t tell which sentences to trust, so you can trust none of them.

The fix is structural, not motivational. Telling an agent &quot;don&apos;t hallucinate&quot; does approximately nothing. Forcing every claim to carry a source URL, and forcing the synthesis step to draw only from notes gathered in phase one, does a lot: a claim with no note behind it has nowhere to hide. This template splits the work into gather, cross-check, and synthesize, with a paper trail at each step.

Hand it to any agent with web access: Claude Code with web search, a deep research tool, whatever you run. The output is a draft report for you to read, not a finished truth. You still spot-check the citations. Two minutes of clicking links beats an afternoon of acting on a source that never existed.</description>
    </item>
    <item>
      <title>Template: Monitoring Alert Agent</title>
      <link>https://internetmenace.com/templates/monitoring-alert-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/monitoring-alert-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Checking whether a URL returns 200 is not agent work. It&apos;s a loop and an if-statement, it costs nothing, and it should run every minute forever. The agent earns its keep in the thirty seconds after the check fails: pulling recent logs, noticing the disk filled up an hour before the crash, and writing an alert that says &quot;the site is down, here&apos;s probably why, here&apos;s the likely fix&quot; instead of just &quot;DOWN.&quot;

That split is the workflow-versus-agent decision from §3.6 in miniature. Deterministic checking stays deterministic. The model only runs when there&apos;s something to diagnose, which also means you&apos;re not paying inference costs to confirm, sixty times an hour, that everything is fine.

Two rules keep this from becoming its own incident. The agent suggests fixes; it never applies them. An agent that restarts services on its own diagnosis will eventually restart the wrong thing at the worst time, and you&apos;ll spend a weekend learning why. And alerts are deduplicated through a state file, because the fastest way to stop reading alerts is to receive forty identical ones. An ignored monitoring system is decoration.</description>
    </item>
    <item>
      <title>Template: Invoice Chasing Agent</title>
      <link>https://internetmenace.com/templates/invoice-chasing-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/invoice-chasing-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Nobody likes chasing invoices, so nobody does it. The reminder you meant to send on day 7 goes out on day 40, apologetic and mistimed, and the client learns that your invoices are optional. Meanwhile the businesses that get paid on time are not braver than you. They just have a system that sends the awkward email so no human has to feel awkward.

This agent runs a three-rung ladder: a friendly nudge at 7 days, a firm note at 21, and a final notice at 45 that says what happens next. Tone is the whole game here. The day-7 email assumes the invoice slipped their mind, because it usually did. The day-45 email is still professional, because you may want this client again, and because an agent that threatens people on your behalf is a liability, not an employee.

Two safety rails are non-negotiable. First, every message is a draft for your approval; a payment that crossed in the mail plus an auto-sent final notice equals a lost client. Second, a sent-log makes the run idempotent, so running the script twice on Tuesday never double-reminds anyone. The agent also never invents late fees, discounts, or legal threats. If it&apos;s not in your invoice terms, it doesn&apos;t go in the email.</description>
    </item>
    <item>
      <title>Template: Document Processing Agent</title>
      <link>https://internetmenace.com/templates/document-processing-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/document-processing-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A shoebox of invoices, a folder of scanned receipts, a decade of PDFs someone needs in a spreadsheet by Friday. This used to be a data-entry job. A multimodal model does it in minutes, and does it well, right up until it reads a smudged 7 as a 1 and your books are off by six hundred dollars with total confidence. The model does not know when it&apos;s wrong. That&apos;s the entire design problem.

So the design has three parts. A schema, decided before you extract anything, because &quot;pull out the important stuff&quot; produces a different shape for every document and §5.1 already told you why that ruins everything downstream. A confidence score on every field, reported by the model itself. And a review queue: extractions below your threshold go to a human, and until you&apos;ve audited the pipeline against documents you&apos;ve checked by hand, the threshold is effectively &quot;everything.&quot; Auto-accept is a privilege the pipeline earns, not a default it ships with.

This one is tagged advanced because it calls the model API directly instead of hiding behind a framework, and because the failure mode is quiet. A broken website looks broken. A wrong number in a spreadsheet looks exactly like a right number.</description>
    </item>
    <item>
      <title>Template: Customer Support Agent</title>
      <link>https://internetmenace.com/templates/customer-support-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/customer-support-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The nightmare version of a support agent is the one that improvises policy. A customer asks about refunds, your docs say nothing, and the model helpfully invents a 90-day money-back guarantee in your brand voice. Now you&apos;re either honoring a policy written by a language model or telling a customer the robot lied to them. Both options are bad, and both were avoidable.

The rule that prevents it is grounding: the agent may only state what it can quote from your docs folder. No doc, no answer. Anything it can&apos;t ground gets escalated to you with a note explaining what the customer needs and what&apos;s missing from the docs. That second part is quietly the best feature here: your escalation queue becomes a list of documentation you should have written.

Every reply is a draft printed for your approval. The stub tools are stubs on purpose, same as the other agent templates on this site: wire them to your real inbox one at a time, verify each, and let the agent earn autopilot on the easy tickets before you even think about the hard ones.</description>
    </item>
    <item>
      <title>Template: Code Review Agent</title>
      <link>https://internetmenace.com/templates/code-review-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/code-review-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>&quot;Review this PR&quot; is an underspecified request, and an agent handles it the way a bored intern would: three style nitpicks, a compliment about naming, and a missed SQL injection. The problem is not the model. The problem is that you didn&apos;t say what a finding is, where the bar sits, or what shape the output should take.

This template fixes all three. It gives the agent a checklist ordered by what actually hurts (correctness, security, tests, then style), and it demands findings as structured records with a file, a line, evidence, severity, and confidence. Structured findings are the difference between a review you act on and a review you skim.

One counterintuitive rule is baked in: the agent reports everything it finds, including low-severity and low-confidence items, and you filter afterward. Modern models follow &quot;only report serious issues&quot; faithfully, which sounds great until you realize they found the bug, judged it below your stated bar, and quietly dropped it. Coverage first, filtering second. And the agent files findings only. It never approves, never merges, never pushes a fix into your branch uninvited. That call is yours.</description>
    </item>
    <item>
      <title>Template: Portfolio Site</title>
      <link>https://internetmenace.com/templates/portfolio-site</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/portfolio-site</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A portfolio site has one job: a stranger with your link and ninety seconds decides whether to email you. Everything on the page either helps that decision or delays it. Most portfolios delay it, because they are organized around the owner&apos;s history instead of the visitor&apos;s question, which is always the same question: can this person do the thing I need done?

The answer to that question is not a skills grid. It is three or four pieces of work, each shown as a small case study: what the problem was, what you did about it, what happened because of it. One project explained beats nine projects thumbnailed. If you&apos;re switching careers or returning to work and the honest answer is &quot;I don&apos;t have client work yet,&quot; case-study your practice projects the same way. The problem-action-result structure is doing the persuading, not the client&apos;s logo.

The technical decision baked into this spec is that your projects live as data, separate from the layout. When you finish something new, you add one entry to one file and the site updates. Portfolios die when adding a project means re-opening the code, so the spec makes adding a project the easiest operation on the site.</description>
    </item>
    <item>
      <title>Template: Landing Page with Waitlist</title>
      <link>https://internetmenace.com/templates/landing-page-waitlist</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/landing-page-waitlist</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The waitlist page is the smallest real project there is. One page, one form, one table of email addresses. It is also the fastest way to find out whether anyone wants the thing before you spend three months building it. If a hundred strangers hand you their email, build it. If nine people sign up and six of them are you testing the form, you just saved a quarter of a year.

The trap is treating &quot;small&quot; as &quot;doesn&apos;t need a spec.&quot; A vague prompt like &quot;make me a landing page with email signup&quot; gets you a page that stores emails in the browser, or in a public spreadsheet, or nowhere at all: the form animates nicely and the address evaporates. Emails are personal data. The moment you collect one, you own its storage, its privacy, and the awkward question of what happens when the same person signs up twice.

This spec pins down the parts an agent will otherwise improvise: where the emails actually live, what happens on a duplicate, what the visitor sees after submitting, and what keeps a bot from filling your table with garbage overnight. The copy is yours to write. The plumbing is what you&apos;re handing over.</description>
    </item>
    <item>
      <title>Template: Command-Line Tool</title>
      <link>https://internetmenace.com/templates/cli-tool</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/cli-tool</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Command-line tools are where agents look best and behave worst. No UI to fuss over, so an agent will hand you something runnable in minutes. Then you pipe its output into another command and discover the &quot;table&quot; is decorated with box-drawing characters, errors print to stdout where they poison the pipe, and the exit code is 0 no matter what happened, so your script can&apos;t tell success from disaster.

The fix is knowing that a CLI has a contract, and the contract is older than you are. Arguments and flags follow conventions. `--help` exists and tells the truth. Exit code 0 means success and nonzero means failure, because that single integer is how every shell script, cron job, and CI pipeline ever written decides what to do next. Human-readable output goes to stdout, diagnostics go to stderr, and a `--json` flag gives programs a stable shape to parse. None of this is hard. All of it gets skipped when the spec doesn&apos;t demand it.

This template is the spec that demands it. Fill in what your tool actually does; the contract section rides along unchanged, and it is the part doing the work. A CLI that honors the contract composes with fifty years of existing tooling. One that doesn&apos;t is a program you can only operate by hand, which on a command line is a strange thing to have built.</description>
    </item>
    <item>
      <title>Template: Chrome Extension</title>
      <link>https://internetmenace.com/templates/chrome-extension</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/chrome-extension</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A browser extension is three small programs pretending to be one. The popup is a tiny web page that appears when you click the icon. The content script is code injected into someone else&apos;s website, where it can read and change the page. The background service worker is the coordinator that owns state and talks to APIs. They run in separate worlds and can only communicate by passing messages, and that message passing is where agent-built extensions go to die: the agent writes each piece correctly and wires them together wrong, or writes Manifest V2 patterns from its training data into your V3 project.

The other thing to get right before any code exists is permissions. Every permission you request is a scary line in the install prompt and a bigger attack surface if your extension is ever compromised. &quot;Read and change all your data on all websites&quot; is what `&lt;all_urls&gt;` looks like to the person installing. If your extension works on one site, say that one site. This spec forces the permissions list to be written down and justified up front, because an agent left to guess will request everything, and it will work in testing, and you will only feel the cost at review time or install time.

One hard rule baked in below: no secrets in the extension. Anything shipped in an extension can be unzipped and read by anyone who installs it. If your extension needs an API that requires a key, the key lives on a server you control and the extension talks to that server.</description>
    </item>
    <item>
      <title>Template: Blog with MDX and RSS</title>
      <link>https://internetmenace.com/templates/blog-mdx</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/blog-mdx</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The fastest way to not have a blog is to start by choosing a CMS. You will compare five of them, sign up for two, wire one halfway in, and write nothing. A blog needs a folder of files, a way to turn them into pages, and a feed so people can subscribe. That&apos;s the whole machine. Your posts as files in your own repo means version history for free, no vendor to outlive, and writing that happens in the same editor you already live in.

MDX is markdown that can embed components. The honest pitch: you will write plain markdown ninety-five percent of the time, and the five percent where you want an interactive chart or a demo embedded mid-post, MDX makes that possible without a rewrite. You are buying the escape hatch, not the habit.

The RSS feed is not optional, and it is the piece agents most reliably get wrong: absolute URLs where relative ones sneak in, valid dates, correct content types. The spec makes the feed a first-class requirement with its own checks, because a subtly broken feed fails silently. Nobody&apos;s reader updates, nobody tells you, and you conclude nobody reads the blog.</description>
    </item>
    <item>
      <title>Template: Test Plan Spec</title>
      <link>https://internetmenace.com/templates/test-plan-spec</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/test-plan-spec</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Ask an agent to &quot;add tests&quot; and you will get tests. Lots of them, green, fast, and aimed wherever the code was easiest to aim at. Coverage of the function that formats dates: extensive. Coverage of the checkout flow that takes money: one test, mocked so thoroughly it would pass if the payment provider ceased to exist. The agent did what you asked. You asked for tests when you meant protection, and those are different orders.

A test plan is you deciding what needs protecting before anyone writes a test. The structure is deliberately small: three to five happy paths, three to five edge cases, one or two failure modes. Happy paths are the promises on the tin: the thing a user came to do, working start to finish. Edge cases are the borders: empty, maximum, duplicate, zero, the unicode name, the second click on a button that should only work once. Failure modes are the world misbehaving: the API that doesn&apos;t answer, the file that doesn&apos;t parse. You are not aiming for coverage of everything. You are aiming for a written answer to &quot;if this breaks tonight, what did we lose?&quot;

The other half of the plan is defining &quot;passing,&quot; and it is less obvious than it sounds. A test that asserts the function returns something is green whether the answer is right or garbage. Every case in the plan states its expected outcome concretely, so the agent has to assert against reality instead of against existence. And one rule carries most of the weight of the whole document: when fixing a bug, the test gets written first and must fail. A test you never saw fail has told you nothing about whether it can.</description>
    </item>
    <item>
      <title>Template: Migration Plan Spec</title>
      <link>https://internetmenace.com/templates/migration-plan-spec</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/migration-plan-spec</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Everything else you build with an agent has an undo button. Bad code: revert the commit. Bad deploy: roll back to the last one. A migration is the exception, because it touches the one thing that can&apos;t be regenerated: the data. Run an UPDATE with a missing WHERE clause on a live database and git cannot help you. This is the single place in this whole curriculum where I will tell you to be slow on purpose.

The plan has one structural idea: never make a change that breaks the currently running code. That is the expand-and-contract pattern. Add the new column while the old one still works. Ship code that writes both and reads the old. Backfill. Flip reads to the new column. Only when nothing has touched the old column for a comfortable while do you contract: drop it. At every point in that sequence, the live version of the app and the live shape of the database are compatible, which means at every point you can stop, and stopping safely is the entire feature.

Two disciplines make the plan real rather than ceremonial. Every step gets a verification: a command you run, and the output you expect, written down before you start, because mid-migration is the worst possible moment to decide what &quot;looks right&quot; means. And every step gets a rollback, written before you execute the step, because writing the rollback is how you find out whether the step is actually reversible. Some aren&apos;t. Dropping a column isn&apos;t. Those steps wait until the end, after everything else has been verified, when rolling back is something you no longer need.

Hand this plan to your agent to help draft and to write the scripts. Do not hand it the production credentials and walk away. You run the irreversible parts, awake, with the backup verified first.</description>
    </item>
    <item>
      <title>Template: Data Model Spec</title>
      <link>https://internetmenace.com/templates/data-model-spec</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/data-model-spec</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The data model is the one part of a project you cannot cheaply redo. Rip out a frontend and your data survives. Swap frameworks and your data survives. Get the tables wrong, let six months of real records pile up inside the wrong shape, and you are now doing surgery on a patient who is awake. Which is why the data model is the worst possible place to let an agent improvise, and exactly where an unspecced agent will improvise most, because every app it has ever seen had a slightly different schema and it will happily average them.

So you write the shape down before any code exists, and you write it twice. First in plain language: what things exist, what facts you store about each one, how they relate. This is the version you can actually check, because you know your own domain. Whether a customer can have two open invoices is not a database question. It is a question about your business, and you are the only one in the room who knows the answer. Then a SQL sketch, which is the same information made precise enough that nothing is left to interpretation: types, required-or-not, unique-or-not, what happens on delete.

The sections people skip are the rules and the sensitive-fields list, and they are the ones with teeth. Rules are the invariants the schema alone can&apos;t express, and unstated rules get discovered as production bugs. The sensitive-fields list is your privacy obligations written where the agent will actually see them, before it helpfully logs email addresses to the console.</description>
    </item>
    <item>
      <title>Template: Bug Report with Repro Steps</title>
      <link>https://internetmenace.com/templates/bug-report-repro</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/bug-report-repro</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>&quot;It&apos;s broken&quot; is not a bug report. It is a mood. An agent handed a mood will guess at what you meant, fix something adjacent to the problem, and report success, and you will not find out it fixed the wrong thing until the real bug bites again.

A usable bug report has three properties. It is reproducible: numbered steps that take a stranger from a clean start to the wrong behavior, every time. It is specific: what you expected, what you got instead, quoted exactly, not paraphrased from memory. And it separates observation from theory: what happened goes in one section, what you suspect goes in another, clearly labeled, so the agent investigates your evidence instead of inheriting your assumptions.

Write the repro steps as if the reader has never seen your project, because functionally, a fresh agent session hasn&apos;t. If you cannot reproduce it reliably, say so and describe the pattern; an intermittent bug honestly labeled is workable, an intermittent bug reported as consistent burns hours.</description>
    </item>
    <item>
      <title>Template: Architecture Decision Record</title>
      <link>https://internetmenace.com/templates/architecture-decision-record</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/architecture-decision-record</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Six months from now you will open your own project and ask, out loud, why the database is SQLite when everything else in your life is Postgres. There was a reason. It was probably a good reason. It is gone now, and the person who could have told you was you, on a Tuesday, in a hurry.

An architecture decision record is the fix, and it is deliberately small: one markdown file per decision, a dozen lines, written the day you decide. Not documentation of the system. Documentation of the fork in the road: what you picked, what you didn&apos;t, and what would have to change for you to reverse it. The rejected options are the valuable part. &quot;We chose X&quot; is a fact you can read from the code. &quot;We rejected Y because of Z&quot; is knowledge that exists nowhere else, and it is exactly the knowledge that stops you from spending a weekend re-evaluating Y when Z is still true.

ADRs matter double when you work with a coding agent. A fresh agent session knows nothing about last month&apos;s reasoning, so it will cheerfully suggest the thing you already rejected, argue for it well, and you will half-remember disagreeing but not why. A folder of ADRs turns that argument into a file lookup. Point your CLAUDE.md or AGENTS.md at the folder and the agent stops relitigating settled questions.

Number them, never edit a decided one, and when a decision changes, write a new ADR that supersedes the old one. The history is the point.</description>
    </item>
    <item>
      <title>Template: API Contract Spec</title>
      <link>https://internetmenace.com/templates/api-contract-spec</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/api-contract-spec</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>An API written without a contract is negotiated one endpoint at a time, in the moment, by whoever is typing. The agent picks a URL shape at 2pm and a different one at 4pm. One endpoint returns errors as strings, another as objects, and your frontend grows a small museum of error-handling styles to cope. None of this is the agent being bad at its job. It answered every question you left open, and it answered them inconsistently because you asked them separately.

The contract closes the questions before the code exists. It says, once, how URLs are shaped, how errors look, how auth works, and how lists paginate, and then every endpoint inherits those answers. The endpoint entries themselves get short, because they only carry what is actually specific to them: the path, the shapes in and out, and the ways they fail.

This is also the document that makes an agent genuinely fast. Hand it the contract and it can build the backend, the frontend client, and the tests against the same shapes, in any order, and the pieces meet in the middle. Skip it and you build the same API twice: once in code, and once in the debugging sessions where you find out what the code decided.

Write the conventions section first. It is the highest-value ten minutes in the file.</description>
    </item>
    <item>
      <title>Template: AGENTS.md</title>
      <link>https://internetmenace.com/templates/agents-md</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/agents-md</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Same job as CLAUDE.md, different address. CLAUDE.md is the project-context file Claude Code reads at the start of every session; the CLAUDE.md template on this site covers it. AGENTS.md is the vendor-neutral version of the same idea, and enough tools have adopted the convention (Codex, Cursor, Copilot, and a growing list of others) that it is now the closest thing to a standard location for &quot;here is what any agent needs to know about this repo.&quot;

Whether you need it depends on who, and what, touches your repo. If you use Claude Code exclusively, CLAUDE.md alone is fine and this file is a maybe. The moment a second tool enters the picture, a collaborator on Cursor, a CI bot, you trying a different agent for an afternoon, the calculus flips, because context that lives only in a Claude-specific file is invisible to everything else, and an agent without context reverts to guessing. You already know how guessing goes.

Do not maintain two full copies; two copies of the same facts diverge, and then your agents disagree about reality depending on which file they read. Put the real content in AGENTS.md and make CLAUDE.md a pointer: a single line saying &quot;Read AGENTS.md,&quot; plus anything genuinely Claude-specific, like skill or subagent notes. One source of truth, every tool sees it, nothing drifts.

The content rules are the same as for CLAUDE.md, so I&apos;ll compress: write facts an agent can act on, not vibes (&quot;use pnpm, never npm&quot; beats &quot;we care about consistency&quot;), keep it current or it becomes a well-formatted lie, and treat &quot;What NOT to do&quot; as the section that pays the rent.</description>
    </item>
    <item>
      <title>Template: Inventory and Reorder Agent</title>
      <link>https://internetmenace.com/templates/inventory-reorder-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/inventory-reorder-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Written for a restaurant, but the structure fits any business where inventory depletes against sales. The agent takes your sales, walks them through recipes to ingredient usage, checks the math against stock on hand, and drafts the reorder; the sales-to-recipe-to-inventory math is already in the file.

It drafts, you send. Keep it that way until the numbers have been right for a month straight.</description>
    </item>
    <item>
      <title>Template: Customer Scheduling Agent</title>
      <link>https://internetmenace.com/templates/customer-scheduling-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/customer-scheduling-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>For the roofer, the plumber, the cleaning service: any business where booking currently happens by phone tag. Customers book themselves; the agent confirms, reschedules, and reminds, and every message is a draft for your approval until you decide it has earned autopilot.

The stub tools are stubs on purpose. Wire them to your real calendar and inbox one at a time, and verify each one before wiring the next.</description>
    </item>
    <item>
      <title>Template: Gmail + Calendar Agent</title>
      <link>https://internetmenace.com/templates/gmail-calendar-agent</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/gmail-calendar-agent</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>This template builds a CrewAI crew that reads your Gmail, reads your
Google Calendar, and creates calendar events for actionable emails.</description>
    </item>
    <item>
      <title>Template: REST/GraphQL API Skeleton</title>
      <link>https://internetmenace.com/templates/api-skeleton</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/api-skeleton</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A backend skeleton for people who already know which stack they want and why. It carries the decisions that hurt to change later: JWT auth, money stored in cents, soft deletes via deleted_at, consistent error shapes. Disagree with any of them if you like, but disagree now, before the agent generates forty endpoints on top of them.</description>
    </item>
    <item>
      <title>Template: Internal Dashboard</title>
      <link>https://internetmenace.com/templates/internal-dashboard</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/internal-dashboard</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A single-page app for the numbers your team checks every day, which currently live in a spreadsheet or in somebody&apos;s head. The spec covers the layout, the components, and the API calls behind them; your job is to name the actual metrics and exactly where they come from. Be precise about the data source. &quot;Pull the sales numbers&quot; is how dashboards end up confidently wrong.</description>
    </item>
    <item>
      <title>Template: Small Business Website</title>
      <link>https://internetmenace.com/templates/small-business-site</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/small-business-site</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Five pages, a contact form, a domain: the site a small business actually needs, specced completely enough for an agent to build it in an afternoon. Swap in your business name, your services, and your words, then hand the whole thing over. Spend your review time on how it looks on a phone, because that is where your customers are.</description>
    </item>
    <item>
      <title>Template: CLAUDE.md</title>
      <link>https://internetmenace.com/templates/claude-md</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/claude-md</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>CLAUDE.md is the file your coding agent reads at the start of every session: what the project is, how it is laid out, which commands run things, and which conventions you refuse to relitigate. Without it, every session starts with the agent guessing at all four and you correcting it. Write it on day one, keep it current, and treat &quot;What NOT to do&quot; as the most valuable heading in the file.</description>
    </item>
    <item>
      <title>Template: Feature Specification</title>
      <link>https://internetmenace.com/templates/feature-spec</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/feature-spec</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A PRD describes the product; a feature spec describes one change to it, tightly enough that an agent can build it without interviewing you first. The discipline is in the edges: inputs, outputs, error states, and what is explicitly out of scope. If writing it feels slower than just asking the agent, count the round trips your last vague request cost you.</description>
    </item>
    <item>
      <title>Template: Product Requirements Document</title>
      <link>https://internetmenace.com/templates/prd</link>
      <guid isPermaLink="true">https://internetmenace.com/templates/prd</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The PRD is the one-page answer to &quot;what are we building and why,&quot; written before any code exists and read by every session after. Fill it in badly and your agent will happily build the wrong thing at full speed. Fill it in honestly, including the non-goals, and most of the clarifying questions disappear before they get asked.

The AFD considerations section is not decorative. Fill it in or rethink the project, but do not delete the section.</description>
    </item>
    <item>
      <title>§9.3 What &quot;functional&quot; Looks Like Now</title>
      <link>https://internetmenace.com/wiki/9/what-functional-looks-like-now</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/9/what-functional-looks-like-now</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>v1 ended with &quot;now you&apos;re functional.&quot; This is what functional means
two years later, with the new tools.</description>
    </item>
    <item>
      <title>§9.2 Contributing Templates Back</title>
      <link>https://internetmenace.com/wiki/9/contributing-templates-back</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/9/contributing-templates-back</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>This curriculum has nine templates. You&apos;ll write the tenth, the
hundredth, the thousandth. Send them back.</description>
    </item>
    <item>
      <title>§9.1 The Community</title>
      <link>https://internetmenace.com/wiki/9/the-community</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/9/the-community</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You&apos;re not alone. The people doing this work are mostly happy to help
the next person.</description>
    </item>
    <item>
      <title>§8.9 Inventory And Reorder Agent (restaurant)</title>
      <link>https://internetmenace.com/wiki/8/inventory-and-reorder-agent-restaurant</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/inventory-and-reorder-agent-restaurant</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.9.</description>
    </item>
    <item>
      <title>§8.8 Customer Scheduling Agent (small Business)</title>
      <link>https://internetmenace.com/wiki/8/customer-scheduling-agent-small-business</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/customer-scheduling-agent-small-business</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.8.</description>
    </item>
    <item>
      <title>§8.7 Gmail + Calendar Agent (crewai)</title>
      <link>https://internetmenace.com/wiki/8/gmail-calendar-agent-crewai</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/gmail-calendar-agent-crewai</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.7.</description>
    </item>
    <item>
      <title>§8.6 Rest/graphql Api Project Skeleton</title>
      <link>https://internetmenace.com/wiki/8/restgraphql-api-project-skeleton</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/restgraphql-api-project-skeleton</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.6.</description>
    </item>
    <item>
      <title>§8.5 Internal Dashboard (svelte Or React)</title>
      <link>https://internetmenace.com/wiki/8/internal-dashboard-svelte-or-react</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/internal-dashboard-svelte-or-react</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.5.</description>
    </item>
    <item>
      <title>§8.4 Small Business Website (one-shot)</title>
      <link>https://internetmenace.com/wiki/8/small-business-website-one-shot</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/small-business-website-one-shot</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.4.</description>
    </item>
    <item>
      <title>§8.3 Claude.md Template (project Context For Coding Agents)</title>
      <link>https://internetmenace.com/wiki/8/claudemd-template-project-context-for-coding-agents</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/claudemd-template-project-context-for-coding-agents</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.3.</description>
    </item>
    <item>
      <title>§8.2 Feature Specification Template</title>
      <link>https://internetmenace.com/wiki/8/feature-specification-template</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/feature-specification-template</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.2.</description>
    </item>
    <item>
      <title>§8.1 Product Requirements Document (prd) Template</title>
      <link>https://internetmenace.com/wiki/8/product-requirements-document-prd-template</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/8/product-requirements-document-prd-template</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 8.1.</description>
    </item>
    <item>
      <title>§7.4 The Data Analyst Leveling Up (dashboards And Pipelines)</title>
      <link>https://internetmenace.com/wiki/7/the-data-analyst-leveling-up-dashboards-and-pipelines</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/7/the-data-analyst-leveling-up-dashboards-and-pipelines</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You finished v1. You&apos;re functional in Python and SQL. You want to ship
faster. Here&apos;s the loadout.</description>
    </item>
    <item>
      <title>§7.3 The Solo Consultant (research, Follow-up, Scheduling)</title>
      <link>https://internetmenace.com/wiki/7/the-solo-consultant-research-follow-up-scheduling</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/7/the-solo-consultant-research-follow-up-scheduling</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You sell your time. Your time is finite. The activities that make you
money — meetings, calls, deliverables — get crowded out by activities
that don&apos;t. Here&apos;s the loadout.</description>
    </item>
    <item>
      <title>§7.2 The Restaurant Manager (operations And Inventory)</title>
      <link>https://internetmenace.com/wiki/7/the-restaurant-manager-operations-and-inventory</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/7/the-restaurant-manager-operations-and-inventory</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You manage a restaurant. Food costs 30%+ of revenue. Half your time
is firefighting. Here&apos;s the loadout.</description>
    </item>
    <item>
      <title>§7.1 The Roofer (small Home-services Business)</title>
      <link>https://internetmenace.com/wiki/7/the-roofer-small-home-services-business</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/7/the-roofer-small-home-services-business</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You install roofs. You&apos;re good at installing roofs. You&apos;re losing
hours every day to phone tag, scheduling, and follow-up. Here&apos;s the
loadout.</description>
    </item>
    <item>
      <title>§6.6 The Deployment Cliff: Making It Run While You Sleep</title>
      <link>https://internetmenace.com/wiki/6/the-deployment-cliff-making-it-run-while-you-sleep</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/the-deployment-cliff-making-it-run-while-you-sleep</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Building an agent that works on your laptop is one thing. Having it
work at 3 AM when you&apos;re asleep is a different thing. This is the
deployment cliff.</description>
    </item>
    <item>
      <title>§6.5 Data Privacy: When Local Models Are Non-negotiable</title>
      <link>https://internetmenace.com/wiki/6/data-privacy-when-local-models-are-non-negotiable</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/data-privacy-when-local-models-are-non-negotiable</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Some data should never leave your machine. Knowing which is which is a
business skill, not a technical one.</description>
    </item>
    <item>
      <title>§6.4 Secrets, Api Keys, And What Not To Put In A Prompt</title>
      <link>https://internetmenace.com/wiki/6/secrets-api-keys-and-what-not-to-put-in-a-prompt</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/secrets-api-keys-and-what-not-to-put-in-a-prompt</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>This section is short because the rules are short. Read all of them.</description>
    </item>
    <item>
      <title>§6.3 Testing Without Being A Tester</title>
      <link>https://internetmenace.com/wiki/6/testing-without-being-a-tester</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/testing-without-being-a-tester</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You don&apos;t need to learn pytest to ship working software. You need a
basic verification habit.</description>
    </item>
    <item>
      <title>§6.2 Git Discipline For Ai-generated Code</title>
      <link>https://internetmenace.com/wiki/6/git-discipline-for-ai-generated-code</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/git-discipline-for-ai-generated-code</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>v1 covered git. This section is what changes when an agent is the one
making most of the commits.</description>
    </item>
    <item>
      <title>§6.1 Reading Code You Didn&apos;t Write</title>
      <link>https://internetmenace.com/wiki/6/reading-code-you-didnt-write</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/6/reading-code-you-didnt-write</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The single highest-leverage skill for vibe coders. Most of the difference
between people who ship and people who don&apos;t is whether they can read
their agent&apos;s output and tell when it&apos;s wrong.</description>
    </item>
    <item>
      <title>§5.6 Api Design For Vibe Coders</title>
      <link>https://internetmenace.com/wiki/5/api-design-for-vibe-coders</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/api-design-for-vibe-coders</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You probably won&apos;t write the API. You will have to describe what it
does. Here&apos;s how.</description>
    </item>
    <item>
      <title>§5.5 User Roles And Permissions</title>
      <link>https://internetmenace.com/wiki/5/user-roles-and-permissions</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/user-roles-and-permissions</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Most apps have at least two kinds of users. Most apps fail to think
this through up front. Don&apos;t be most apps.</description>
    </item>
    <item>
      <title>§5.4 Design Preferences (radii, Shadows, Fonts, Spacing)</title>
      <link>https://internetmenace.com/wiki/5/design-preferences-radii-shadows-fonts-spacing</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/design-preferences-radii-shadows-fonts-spacing</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The aesthetic choices. Most people skip these and end up with the
default &quot;AI-generated SaaS&quot; look. A few specifications get you out
of that valley.</description>
    </item>
    <item>
      <title>§5.3 Component Vocabulary (tabs, Buttons, Modals, Drawers)</title>
      <link>https://internetmenace.com/wiki/5/component-vocabulary-tabs-buttons-modals-drawers</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/component-vocabulary-tabs-buttons-modals-drawers</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Within the layout, the components. Here&apos;s the cheat sheet so you can
name what you want.</description>
    </item>
    <item>
      <title>§5.2 Describing Interfaces Accurately (top Menu, Side Menu, Panels)</title>
      <link>https://internetmenace.com/wiki/5/describing-interfaces-accurately-top-menu-side-menu-panels</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/describing-interfaces-accurately-top-menu-side-menu-panels</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You&apos;re going to ask an agent to build a UI. The agent has read every UI
ever made. You have to tell it which one you want.</description>
    </item>
    <item>
      <title>§5.1 Data Shape: The Prerequisite To Good Prompts</title>
      <link>https://internetmenace.com/wiki/5/data-shape-the-prerequisite-to-good-prompts</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/5/data-shape-the-prerequisite-to-good-prompts</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>We touched on this in 2.5. Here&apos;s the longer treatment, because data
shape is the bottleneck for most projects.</description>
    </item>
    <item>
      <title>§4.6 Cost Literacy: Tokens, Context Windows, And The $200 Question</title>
      <link>https://internetmenace.com/wiki/4/cost-literacy-tokens-context-windows-and-the-200-question</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/cost-literacy-tokens-context-windows-and-the-200-question</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You can&apos;t make smart routing decisions if you don&apos;t know what you&apos;re
paying for. Here&apos;s the cheat sheet.</description>
    </item>
    <item>
      <title>§4.5 Self-hosting On Nvidia (spark, Orin, Full Gpus)</title>
      <link>https://internetmenace.com/wiki/4/self-hosting-on-nvidia-spark-orin-full-gpus</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/self-hosting-on-nvidia-spark-orin-full-gpus</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The NVIDIA path. More flexible, more setup, often cheaper for
comparable capability.</description>
    </item>
    <item>
      <title>§4.4 Self-hosting On Mac (mini, Studio, Pro)</title>
      <link>https://internetmenace.com/wiki/4/self-hosting-on-mac-mini-studio-pro</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/self-hosting-on-mac-mini-studio-pro</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Apple&apos;s the easiest on-ramp to self-hosting. Here&apos;s the lineup.</description>
    </item>
    <item>
      <title>§4.3 Ram, Vram, And Unified Memory</title>
      <link>https://internetmenace.com/wiki/4/ram-vram-and-unified-memory</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/ram-vram-and-unified-memory</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The number that determines whether you can run a model is &quot;how much
memory do you have, and what kind.&quot; The kinds matter.</description>
    </item>
    <item>
      <title>§4.2 How Models Actually Work (weights, Parameters, Active Parameters)</title>
      <link>https://internetmenace.com/wiki/4/how-models-actually-work-weights-parameters-active-parameters</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/how-models-actually-work-weights-parameters-active-parameters</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You don&apos;t need to understand the math. You need to understand the
vocabulary so you can read a model&apos;s spec sheet and make a buying
decision.</description>
    </item>
    <item>
      <title>§4.1 Frontier Vs. Local: When Each Makes Sense</title>
      <link>https://internetmenace.com/wiki/4/frontier-vs-local-when-each-makes-sense</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/4/frontier-vs-local-when-each-makes-sense</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>This is the most important budgeting decision you&apos;ll make. Not every
problem deserves Claude Max.</description>
    </item>
    <item>
      <title>§3.6 Crewai For Agents</title>
      <link>https://internetmenace.com/wiki/3/crewai-for-agents</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/crewai-for-agents</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The most useful new tool in this curriculum. Read this section twice.</description>
    </item>
    <item>
      <title>§3.5 Fastapi Vs. Devii: When To Write An Api Vs. Generate One</title>
      <link>https://internetmenace.com/wiki/3/fastapi-vs-devii-when-to-write-an-api-vs-generate-one</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/fastapi-vs-devii-when-to-write-an-api-vs-generate-one</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Every application needs a way for the frontend to talk to the database.
That layer is called an API. You can write one (FastAPI) or generate
one (Devii). Here&apos;s how to choose.</description>
    </item>
    <item>
      <title>§3.4 Mage (still The Move) For Data Pipelines</title>
      <link>https://internetmenace.com/wiki/3/mage-still-the-move-for-data-pipelines</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/mage-still-the-move-for-data-pipelines</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>v1&apos;s recommendation holds. Mage is still the move for data pipelines.
What&apos;s changed: now you don&apos;t have to write the Python yourself.</description>
    </item>
    <item>
      <title>§3.3 Voice-to-text: Wispr Flow And The Dictation Workflow</title>
      <link>https://internetmenace.com/wiki/3/voice-to-text-wispr-flow-and-the-dictation-workflow</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/voice-to-text-wispr-flow-and-the-dictation-workflow</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You think faster than you type. Stop typing.</description>
    </item>
    <item>
      <title>§3.2 Coding Agents: Claude Code, Openclaude, Others</title>
      <link>https://internetmenace.com/wiki/3/coding-agents-claude-code-openclaude-others</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/coding-agents-claude-code-openclaude-others</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The IDE is the room. The agent is the engineer. The agent landscape has
gotten more interesting since v1; here&apos;s the current map.</description>
    </item>
    <item>
      <title>§3.1 Ides And Editors: Vs Code, Cursor, Anti Gravity</title>
      <link>https://internetmenace.com/wiki/3/ides-and-editors-vs-code-cursor-anti-gravity</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/3/ides-and-editors-vs-code-cursor-anti-gravity</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You need somewhere to write code. Not all editors are equal anymore.</description>
    </item>
    <item>
      <title>§2.6 The Claude Code Playbook</title>
      <link>https://internetmenace.com/wiki/2/the-claude-code-playbook</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/the-claude-code-playbook</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You have requirements (2.1), specs (2.2), structured prompts (2.3),
context discipline (2.4), and data shape (2.5). What&apos;s missing is the
loop you run them through. This section is the loop.</description>
    </item>
    <item>
      <title>§2.5 Prompting Based On Data Shape</title>
      <link>https://internetmenace.com/wiki/2/prompting-based-on-data-shape</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/prompting-based-on-data-shape</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Effective prompts come from understanding your data. Most bad prompts come
from people who don&apos;t actually know what&apos;s in their data.</description>
    </item>
    <item>
      <title>§2.4 Context Engineering (the Missing Discipline)</title>
      <link>https://internetmenace.com/wiki/2/context-engineering-the-missing-discipline</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/context-engineering-the-missing-discipline</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The principle that explains why the playbook in 2.6 works the way it does.
You can ship without reading this. You&apos;ll ship better if you don&apos;t.</description>
    </item>
    <item>
      <title>§2.3 Structured Markdown: The Format Coding Agents Read Best</title>
      <link>https://internetmenace.com/wiki/2/structured-markdown-the-format-coding-agents-read-best</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/structured-markdown-the-format-coding-agents-read-best</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>You wrote a spec. The agent needs to read it. The format matters more than
you think.</description>
    </item>
    <item>
      <title>§2.2 Specifications: What The Machine Actually Needs</title>
      <link>https://internetmenace.com/wiki/2/specifications-what-the-machine-actually-needs</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/specifications-what-the-machine-actually-needs</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Requirements are for humans. Specifications are for machines. The machine
needs more.</description>
    </item>
    <item>
      <title>§2.1 Requirements: What You Actually Want</title>
      <link>https://internetmenace.com/wiki/2/requirements-what-you-actually-want</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/2/requirements-what-you-actually-want</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Most software fails because nobody wrote down what it was supposed to do.
This is true of $50 million enterprise projects and your weekend side
project. Start here.</description>
    </item>
    <item>
      <title>§1.4 When Not To Use Ai To Write Your Code</title>
      <link>https://internetmenace.com/wiki/1/when-not-to-use-ai-to-write-your-code</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/1/when-not-to-use-ai-to-write-your-code</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Counterintuitive section, but the most important one in Part 1. If you
read nothing else, read this.</description>
    </item>
    <item>
      <title>§1.3 The New Skills Stack: Requirements → Specs → Structured Prompts → Agents</title>
      <link>https://internetmenace.com/wiki/1/the-new-skills-stack-requirements-specs-structured-prompts-agents</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/1/the-new-skills-stack-requirements-specs-structured-prompts-agents</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>There&apos;s a pipeline from &quot;I have an idea&quot; to &quot;the software exists.&quot; Here are
the four stages, in order, with the skill each one requires.</description>
    </item>
    <item>
      <title>§1.2 What &quot;vibe Coding&quot; Actually Means (defined On Our Terms)</title>
      <link>https://internetmenace.com/wiki/1/what-vibe-coding-actually-means-defined-on-our-terms</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/1/what-vibe-coding-actually-means-defined-on-our-terms</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>&quot;Vibe coding&quot; gets thrown around to mean ten different things. Here&apos;s what
it means in this curriculum.</description>
    </item>
    <item>
      <title>§1.1 Why The Old Foundation Matters More Now</title>
      <link>https://internetmenace.com/wiki/1/why-the-old-foundation-matters-more-now</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/1/why-the-old-foundation-matters-more-now</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The grift you&apos;re going to hear is: &quot;AI will write code for you, you don&apos;t
need to learn programming.&quot; The grift is wrong. Here&apos;s why.</description>
    </item>
    <item>
      <title>§0.17 Projects And The Final Boss</title>
      <link>https://internetmenace.com/wiki/0/projects-and-the-final-boss</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/projects-and-the-final-boss</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>NOW IT&apos;S TIME TO MAKE SOME PROJECTS</description>
    </item>
    <item>
      <title>§0.16 Day 100: Cloud, Cli, And Tools</title>
      <link>https://internetmenace.com/wiki/0/day-100-cloud-cli-and-tools</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/day-100-cloud-cli-and-tools</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>SO YOU&apos;RE ABOUT 100 DAYS IN, CALL IT 16 WEEKS. MAYBE LONGER. YOU HAVE THE
BASICS DOWN. LET&apos;S LEARN SOME TOOLS.

Now you need to learn how to put all these skills into use with some tools.
This is by no means a complete list, but it is a list of tools that I
personally use, or tools that I know my peers use.

More importantly, tools that you will actually use, and can use to turn data
into things that employers like… you know… money and value related shit.

Let&apos;s surf through the most common tools that will help you engineer problems
into solutions.</description>
    </item>
    <item>
      <title>§0.15 Day 60: Docker, Kubernetes, Git</title>
      <link>https://internetmenace.com/wiki/0/day-60-docker-kubernetes-git</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/day-60-docker-kubernetes-git</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>YOU DID ALL THE HARVARD STUFF, SO MY GUESS IS YOU&apos;RE AROUND 60 DAYS IN

Now we move into Docker, Git, tools, and the things that turn code, theory and
basics into functional skills.

We call this DevOps, but it&apos;s essential.</description>
    </item>
    <item>
      <title>§0.14 Day 30: The Wall And Cs50</title>
      <link>https://internetmenace.com/wiki/0/day-30-the-wall-and-cs50</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/day-30-the-wall-and-cs50</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>AT 30-ISH DAYS, YOU&apos;RE ABOUT TO HIT &quot;THE WALL&quot; IN LEARNING TO CODE

This is a good time to go to Harvard. For free.

Seriously. This is where we take a break and get into some theory. You&apos;ve seen
how Python and SQL can work, you have some understanding, and now it&apos;s time for
the same exact Harvard course that people literally pay for at Harvard… but for
free.</description>
    </item>
    <item>
      <title>§0.13 Day 20: Add Sql</title>
      <link>https://internetmenace.com/wiki/0/day-20-add-sql</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/day-20-add-sql</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>AROUND DAY 20, START ADDING IN SOME SQL

The best way to do this is to tackle more than one course at a time. That&apos;s why
you take multiple courses in college. I think about 20 days of Python is enough
to make you &quot;start thinking like a computer&quot; and that&apos;s a good time to dive
into SQL.</description>
    </item>
    <item>
      <title>§0.12 Day 1: Python</title>
      <link>https://internetmenace.com/wiki/0/day-1-python</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/day-1-python</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>AND NOW YOU BEGIN. THIS IS STILL DAY 1. PYTHON. LFG.

This is where all the actual coding and learning to code starts. (Holy crap
that was 25 intro slides. My God what have I done?) I&apos;m still glad I did all
that explaining because it all matters.</description>
    </item>
    <item>
      <title>§0.11 Set Up Your Environment</title>
      <link>https://internetmenace.com/wiki/0/set-up-your-environment</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/set-up-your-environment</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>HOW DO WE MAKE CODE HAPPEN? LET&apos;S START DOWNLOADING STUFF.

What kind of computer do you need, by the way? Literally fucking anything
works.</description>
    </item>
    <item>
      <title>§0.10 The Stack: Python, Sql, Docker, Git</title>
      <link>https://internetmenace.com/wiki/0/the-stack-python-sql-docker-git</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/the-stack-python-sql-docker-git</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>DIVE INTO PYTHON, SQL, GIT AND DOCKER/KUBERNETES

Here we go… (and now the intro to the stuff you&apos;re gonna learn starting out).</description>
    </item>
    <item>
      <title>§0.9 How Code Thinks: Mvp, Mvc, And What A Computer Is</title>
      <link>https://internetmenace.com/wiki/0/how-code-thinks-mvp-mvc-and-what-a-computer-is</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/how-code-thinks-mvp-mvc-and-what-a-computer-is</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>MVP — Most Valuable Player.

After winning the 2013-14 MVP award, Kevin Durant said his mother was &quot;da real
MVP&quot;, which isn&apos;t what we&apos;re talking about here today.</description>
    </item>
    <item>
      <title>§0.8 What This Covers (and Why Not A Bootcamp)</title>
      <link>https://internetmenace.com/wiki/0/what-this-covers-and-why-not-a-bootcamp</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/what-this-covers-and-why-not-a-bootcamp</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The core foundation of data engineering and analytics, in the next 180 days.</description>
    </item>
    <item>
      <title>§0.7 Foundations: Start Here (or Skip It)</title>
      <link>https://internetmenace.com/wiki/0/foundations-start-here-or-skip-it</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/foundations-start-here-or-skip-it</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>[COPY: 1-2 sentences framing sections 0.7-0.17 as Internet Menace Version 1.1 — the original curriculum, released July 8, 2024 — folded into this wiki as a day-ordered path, plus who should skip it (already finished v1 → jump to Part 1) — VOICE: Shane — LENGTH: 2-3 sentences]</description>
    </item>
    <item>
      <title>§0.6 How To Use This Curriculum (core Path Vs. Deep-dives)</title>
      <link>https://internetmenace.com/wiki/0/how-to-use-this-curriculum-core-path-vs-deep-dives</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/how-to-use-this-curriculum-core-path-vs-deep-dives</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>This is a wiki, not a textbook. You don&apos;t have to read it in order.</description>
    </item>
    <item>
      <title>§0.5 What Changed Since Internet Menace V1</title>
      <link>https://internetmenace.com/wiki/0/what-changed-since-internet-menace-v1</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/what-changed-since-internet-menace-v1</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>A lot. Not all of it for the better. Most of it for the better.</description>
    </item>
    <item>
      <title>§0.4 Who This Is For</title>
      <link>https://internetmenace.com/wiki/0/who-this-is-for</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/who-this-is-for</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Internet Menace, Again is for three kinds of people:

1. People who finished Internet Menace v1 and want to know what&apos;s next.
2. People who own or run a small business and want to use AI to handle
   work that&apos;s eating their week.
3. People who are not engineers, never wanted to be engineers, but have
   an idea for software they want to exist.</description>
    </item>
    <item>
      <title>§0.3 Sponsor</title>
      <link>https://internetmenace.com/wiki/0/sponsor</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/sponsor</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>There&apos;s no sponsor.</description>
    </item>
    <item>
      <title>§0.2 Acknowledgments</title>
      <link>https://internetmenace.com/wiki/0/acknowledgments</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/acknowledgments</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Wiki section 0.2.</description>
    </item>
    <item>
      <title>§0.1 Welcome Back (or Welcome For The First Time)</title>
      <link>https://internetmenace.com/wiki/0/welcome-back-or-welcome-for-the-first-time</link>
      <guid isPermaLink="true">https://internetmenace.com/wiki/0/welcome-back-or-welcome-for-the-first-time</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>Two years ago I wrote Internet Menace because I was tired of watching people get
fleeced by $20,000 bootcamps that taught them less than a free YouTube playlist.
About 2,000 people downloaded that curriculum. Some of you got jobs. Some of
you got better jobs. A few of you sent me very nice emails. One of you sent
me a meme so good I screenshotted it.

Now it&apos;s 2026, and the ground has moved under all of us.</description>
    </item>
    <item>
      <title>v1.0.0: Internet Menace, Again is live</title>
      <link>https://internetmenace.com/changelog</link>
      <guid isPermaLink="true">https://internetmenace.com/changelog</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <description>The curriculum, the templates, the glossary, and the site go public. Internet Menace, again, the second pass.</description>
    </item>
  </channel>
</rss>