Day One: From "Do I Even Have Docker?" to a Live Automation
I spent 25 years directing enterprise technical programs at Level 3, Microsoft, and Meta. I have sat in thousands of meetings where engineers explained what they built. Today I wanted to find out, hands on keyboard, what the first day of that work actually feels like. Not to become an automation engineer. I'm not one, and this project won't make me one. The goal is narrower and, I'd argue, more useful for what I do: understanding the day-to-day reality of the engineers I direct and translate for, by doing a small version of it myself.
So: learn n8n, the open-source automation platform, by building one real thing and writing down what actually happened. Including the parts that make me look like a beginner, because on day one, I was one.
The false paywall
I'd signed up for n8n's cloud trial weeks ago, never touched it, and let it expire. My assumption walking in: the free window is gone, day one starts with a credit card.
Wrong, and instructively wrong. n8n's Community Edition is free, open source, and self-hosted, with no execution limits. The features it lacks versus paid plans are enterprise IT concerns like SSO and compliance logging. For learning, it's the whole product. The paywall I believed in was a story I'd told myself from the trial-expiry email. First lesson of the day, and I hadn't installed anything yet: check whether the wall is real before paying the toll.
Self-hosting also turned out to be the better fit for the actual goal. The engineers I want to understand don't work in a hosted trial account. They work in containers, credentials, ports, and environment quirks. Cloud hides exactly the layer I came to see.
Seventeen minutes
Terminal check number one: docker --version. Command not found. Check two: node --version. Also not found. Check three: uname -m returned arm64, which told me which Docker download my Mac needed, a detail I would not have known to check and would have paid for later.
From those checks to a running n8n instance took 17 minutes. Most of that was two downloads: Docker Desktop, then the n8n container image. The one command that mattered:
docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8nI did not write that command. Claude did, and then we unpacked it piece by piece, because the vocabulary inside it is half of what agency engineers say all day. A container is a disposable box with the software and everything it needs inside, which is why I never needed to install Node. A volume is the storage that survives when the box gets thrown away. A port mapping is the plumbing that lets my browser reach the thing. When someone says "hit the orders endpoint" or "check the volume," those are no longer noises to me.
The startup log printed hundreds of lines of database "migrations," the entire history of the product's data structure replayed onto my machine in seconds, then: Editor is now accessible via http://localhost:5678.
Worth saying plainly: 17 minutes got me a blank canvas, not an accomplishment. The accomplishment question is whether something real works.
What I built
The thing I automated is small and honest: every morning I check whether my JG BeatsLab site made any sales overnight. Manual ritual, every day, first coffee. Now it's a workflow that runs at 5:00 AM, calls the Squarespace Orders API, filters to orders created in the last 24 hours, excludes refunds, and emails me a summary. Four nodes: a schedule trigger, an HTTP request, a small JavaScript step, an email send.
Getting there involved more real decisions than I expected from a four-node workflow:
Credential hygiene. The Squarespace API key got the minimum permissions that could do the job: Orders only, read-only. On the n8n side, the credential is domain-locked so it physically cannot be sent anywhere except api.squarespace.com, even by a future mistake. Two layers of "this key can only do the one thing it exists for." Somewhere in the middle of this I also caught myself handling sensitive data too casually before I'd built the habit of treating it carefully by default. Redaction has to be a reflex, not an afterthought. That's a lesson I'd rather admit now, on a low-stakes personal project, than learn later on someone else's.
A vocabulary trap. Squarespace's permission screen offers Orders and Transactions, both plausible-sounding for "did I make sales." Orders is what sold; Transactions is money movement, the accounting view. I initially reached for the wrong one. Small traps like this are the actual texture of API work.
My own data taught the best lesson. The first successful API call returned orders sorted by modification date, and the top of the list was a batch of week-old orders that had been refunded that morning. If we'd naively built "show recent orders," my 5 AM email would report week-old refunds as news. The fix, filtering on creation date and excluding refunded payment states, came directly from reading my own real data instead of a tutorial's clean sample.
The empty morning is a design decision. Some nights nothing sells. I decided the email arrives anyway, saying "no sales," because silence is ambiguous: it could mean no sales or it could mean the workflow died. That decision is also why there's JavaScript in my no-code tool. Visual nodes only run when data flows into them; a zero-result night would produce no email at all. A small code step always outputs exactly one summary. Claude wrote the code, I placed it, tested it, and can now read it. That division of labor is my actual job description, enacted in miniature.
The bugs were the education
Three things went wrong, and all three were caught by looking at artifacts rather than trusting memory.
The first email arrived with a subject line that literally read {{ $json.subject }}. The body rendered correctly, the subject shipped its raw wiring. Cause: n8n fields have a Fixed mode and an Expression mode, and one field was in the wrong one. Same syntax, two fields, one worked. Partial success is what config bugs usually look like.
Second: an instruction to add a required User-Agent header silently didn't stick, and the API call worked anyway because the HTTP client sent a default one. Working for the wrong reason is a category of bug I now respect. The workflow export, a JSON file that shows the actual configuration rather than what I remembered configuring, is what caught it.
Third, the humblest one: I typed a command into a terminal that was busy running n8n's live logs, where it did exactly nothing, and sat there confused until I understood the terminal was occupied. Everyone who works in a terminal has done this. Nobody screenshots it.
Demo config versus production config
The command that started n8n was built for a learning session: attached to my terminal, container deleted on exit. A thing that must run unattended at 5 AM needs the opposite: detached, restart-on-reboot. Swapping meant stopping the container, deleting it, and starting a new one, and here the morning's abstract lesson became physical: the workflow, credentials, everything survived, because it all lives in the volume, not the container. I destroyed the box and lost nothing.
The Mac itself needed instructions too. A laptop asleep at 5 AM runs nothing, so a one-line macOS command now wakes the machine at 4:57 daily. And publishing the workflow turned out to be a versioned release, with a name and a description of what changed, the same discipline software teams use to ship. The demo mental model and the production mental model are different things, and today I got to hold both.
What's still rough, on purpose
I'm leaving these unfixed for now rather than pretending day one was tidier than it was: the User-Agent header still isn't actually set, it's riding on a client default. The credential still carries the generic name n8n gave it. The workflow only reads the first page of API results, fine at my volume, a real gap at scale. And an order created overnight and refunded before 5 AM vanishes entirely, which is exactly what "exclude refunds" means at the edge, and exactly the kind of edge case you only find by shipping something real.
What's true and what isn't yet
True: I started at 3:26 PM not knowing whether Docker was on my machine, and at 4:44 PM, 78 minutes later, there's a self-hosted automation platform running as a background service, a domain-locked credential, a working pipeline with my own filtering rules, and a live scheduled workflow.
Not yet true: that it works unattended. Every test so far had a human pushing a button. The sleep-wake-trigger-send chain runs for real at 5:00 tomorrow morning, and I'll report what actually happens, including if what actually happens is nothing.