Every term, explained
Every word in this guide in plain English — about fifteen seconds a look-up, and not a page anyone reads end to end.
Each entry links to the page where the term actually matters. Look up the word that stopped you, then go back to what you were doing.
If a term you hit isn't here, that's a bug in the guide. Open an issue and it gets added.
Index#
- A — A record · AAAA record · Absolute and relative URL · Access key · ACM · ALIAS record · Anon key · Apex domain · API · API key · apt · ARN · Audience claim · Auth code · Authentication and authorisation · AWS account ID
- B — bash · Binding · Blast radius · Branch · Browser cache and hard reload · Bucket · Budget alarm · Build command · Build step
- C — Cache · Cache invalidation · Case sensitivity · CDN · Certificate · Certificate authority · CI and CD · Claim · CLI · Clone · Cloudflare Pages · CloudFront · CNAME · CNAME flattening · Cold start · Commit · Cost Explorer · Credential · curl
- D — D1 · Delegation · Deploy · dig · Distribution · DNS · Domain · Domain validation · Durable Objects
- E — Edge · Endpoint · .env · Environment variable · ETag · Eventual consistency
- F — Favicon · Force-push · Fork · Free tier · Function URL
- G — gh · git · Git Bash · .gitignore · GitHub · GitHub Actions · GitHub secret · GitHub variable
- H — Headless browser · Heredoc · History rewriting · Homebrew · Hostname · HSTS · HTML, CSS and JavaScript · HTTP · HTTP header · HTTP status code · HTTPS
- I — IAM · IAM Identity Center · IAM user · ICANN · Identity provider · Infrastructure as code · IP address · Issue
- J — jq · JSON · JWT
- L — Lambda · Least privilege · Let's Encrypt · Licence · localhost · Lockfile
- M — main · Managed platform · Merge · MFA · MIT licence · MX record
- N — Nameserver · NAT gateway · Node.js · node_modules · npm · NS record · NXDOMAIN
- O — Object · OIDC · Open Graph · Open source · Origin (git) · Origin (hosting) · Origin Access Control · Output directory
- P — Package manager · Pages Functions · Personal access token · Policy · Port · PowerShell · Premium domain · Preview deployment · Principal · Propagation · Pull request · Push · Push protection
- R — R2 · README · Region · Registrar · Registry · Remote · Repository · Resolver · Role · Rollback · Root account · Rotate a key · Route 53 · Row Level Security · Runner · Runtime
- S — S3 · Secret · Secret scanning · Secrets Manager · Server · Serverless · Shell · Shell variable · SNI · SOA record · SPA · SPF, DKIM and DMARC · Stage · Static site · Static site generator · STS and AssumeRole · Subdomain · Subject claim · Supabase
- T — Terminal · TLD · TLS and SSL · Topics · Trust policy · TTL · TXT record
- U — UPSERT · URL
- V — Virtual machine
- W — WHOIS · winget · Workers · Workers KV · Workflow · wrangler · WSL
- Z — zip · Zone
Domains and DNS#
A record#
A DNS record that maps a name to an IPv4 address — yourthing.com →
104.21.5.12. It is the most basic answer DNS can give, and on
Track B your domain's A record is a
special alias one pointing at CloudFront rather than a literal
number.
AAAA record#
The same idea as an A record but for an IPv6 address (the longer, colon-separated kind). Pronounced "quad-A". You rarely add these by hand — your host adds them alongside the A record if it supports IPv6.
ALIAS record#
A non-standard record type that behaves like a CNAME but is allowed at the apex, where a real CNAME is forbidden. Route 53 calls it an ALIAS; other providers call it ANAME. See the apex problem.
Apex domain#
The bare domain with nothing in front of it — yourthing.com, not
www.yourthing.com. Also called the root domain, the naked domain or the zone
apex. It matters because the DNS specification forbids a CNAME there,
which is why hosts invent ALIAS records and
CNAME flattening.
Auth code#
A one-time password your current registrar gives you so a different registrar is allowed to take over the domain. Also called an EPP code or transfer code. Transfers take around five days and your site stays up throughout, because the nameservers don't change.
CNAME#
A DNS record meaning "don't ask me, go and look up this other name instead" —
www.yourthing.com → your-project.pages.dev. It is what modern hosts hand you
instead of an IP address, so that when their addresses change your site doesn't
notice. See layer 2.
CNAME flattening#
Cloudflare's answer to the apex problem: you add what looks like a CNAME at the apex, and Cloudflare quietly resolves it and serves an A record instead. You don't configure it — it just happens, which is why Track A never mentions the problem at the point it would otherwise bite.
Delegation#
The moment the registry for your TLD publishes your
nameservers, so the rest of the internet knows who to ask about
your domain. A brand-new registration is not delegated instantly, and until
it is, your DNS records are correct but invisible — which is exactly why
a certificate can hang on a
freshly bought domain. Check with dig NS yourthing.com +short; empty means not
yet.
dig#
The standard command-line tool for asking DNS a question directly, rather than
trusting your browser. dig NS yourthing.com +short shows the nameservers;
dig @1.1.1.1 yourthing.com bypasses your own cache. macOS has it; on Ubuntu
install dnsutils (called bind9-dnsutils on newer releases); Windows without
WSL has no dig — use
nslookup -type=NS yourthing.com or dnschecker.org.
See seeing it for yourself.
DNS#
The Domain Name System — the global phone book that turns a name people can remember into an address machines can use. It is layer 2 of the four, and it is far and away the layer people get stuck on.
Domain#
The name you rent, like yourthing.com. A domain is not a website and not
hosting — this is the single most common confusion in the whole subject. The
domain is only a name plus the right to say who answers questions about it; the
files live somewhere else entirely, which is why you can change host without
changing domain. See the three layers.
Hostname#
One specific name in DNS, including everything in front of the domain.
yourthing.com and www.yourthing.com are two different hostnames, each
needing its own record and its own place in the certificate.
That single fact explains the classic "works with www, not without"
(troubleshooting).
ICANN#
The non-profit that oversees the domain name system. Two things it does affect
you directly: a small fixed fee added to most registrations, and a rule that you
must click the verification email after registering or the domain gets
suspended after roughly a fortnight (Track B). Both apply
to .com-style endings; country ones like .uk set their own rules.
MX record#
A DNS record saying which server receives email for the domain. It matters here for one reason: when you move DNS to Cloudflare and the MX records don't come across, your email silently stops. Check them before you switch nameservers, not after.
Nameserver#
A machine that holds your zone and answers DNS questions about it. Your registrar stores a short list of them against your domain, and changing that list is how you move your entire DNS to a different provider. It is the one registrar setting that genuinely matters.
NS record#
The record type that lists your nameservers. dig NS
yourthing.com +short is usually the first command to run when something is
broken, because it tells you which provider is actually in charge — often not
the one whose dashboard you've been editing.
NXDOMAIN#
DNS's way of saying "that name doesn't exist". In a browser it shows up as "Server not found". It means the failure is at layer 1 or 2 — the name never resolved, so nothing has even tried to reach your host yet.
Premium domain#
A name the registry has flagged as desirable and priced at ten to a hundred times normal, often with a renewal to match. Route 53 refuses to register premium names at all, which makes it a free premium detector: if it offers you the name at a normal price, it isn't premium.
Propagation#
The folklore that DNS changes take 24–48 hours. Mostly untrue — a record with a short TTL is visible worldwide in minutes. What is genuinely slow is a nameserver change, and what fools you is your own machine's cache. See "propagation" — mostly a myth.
Registrar#
The company you buy the domain from — Cloudflare, Namecheap, Route 53 Domains, GoDaddy, Gandi. You're buying a lease, usually annual, plus the right to set the nameservers. This is layer 1 and the least sticky thing you own.
Registry#
The organisation that runs an entire TLD — Verisign for .com, Nominet
for .uk. You never deal with it directly; your registrar does.
It sets the wholesale price, which is why .com costs roughly the same
everywhere and why some newer extensions renew at fifteen times their first-year
price.
Resolver#
The DNS server your computer actually asks — usually your router's or your
internet provider's, sometimes a public one like Cloudflare's 1.1.1.1 or
Google's 8.8.8.8.
Resolvers cache answers, which is why dig @1.1.1.1 yourthing.com is the fastest
way to prove "it works for everyone but me"
is your own machine's fault.
Route 53#
AWS's DNS service, and also an AWS registrar. It is the only piece of Track B that costs money whether or not anyone visits — around $0.50 a month per hosted zone — which is why turning it off properly has its own section.
SOA record#
The "start of authority" record that sits at the top of every zone, carrying administrative settings. You never create or edit it; it appears automatically, and the only time you'll notice it is when deleting a hosted zone, where SOA and NS records are the two you must leave alone.
SPF, DKIM and DMARC#
Three TXT record conventions that between them tell the world
which servers may send email as your domain. Values start v=spf1, or live
under names containing _domainkey or _dmarc. If you receive email at your
domain, these must survive a
DNS move intact.
Subdomain#
Anything in front of the domain: www.yourthing.com, api.yourthing.com,
blog.yourthing.com. Subdomains are free and unlimited once you own the domain,
and a second project on one costs nothing extra —
Track B notes it takes about ten minutes
once the zone exists.
TLD#
Top-level domain — the last part of the name: .com, .co.uk, .dev,
.online. The TLD decides both the price and some behaviour: .dev, for
instance, is on the HSTS preload list, so browsers refuse plain HTTP on
it entirely.
TTL#
Time-to-live, in seconds — a note attached to every DNS record saying "you may cache this answer for this long". A 300-second TTL means the world sees your change within five minutes. Lower the TTL before a change you know is coming, not after (layer 2).
TXT record#
A DNS record holding arbitrary text. Its real use is proving you control a domain: certificate authorities and services like Google ask you to publish a specific string, and read it back to confirm. Also where SPF, DKIM and DMARC live.
UPSERT#
The word Route 53 uses in its JSON change files meaning "create this record, or overwrite it if it already exists". It appears throughout Track B and matters because it makes those commands safe to run twice.
WHOIS#
The public directory of who owns which domain. Registration would otherwise publish your name and home address; privacy protection replaces them with the registrar's details and is free at every registrar this guide mentions. Leave it on.
Zone#
Your slice of DNS — the complete set of records answering questions about your domain. AWS calls it a hosted zone and charges monthly for it; Cloudflare just calls it your domain and doesn't. Records live inside a zone, and editing records in a zone that isn't delegated is a popular way to spend an hour changing nothing.
Security and certificates#
ACM#
AWS Certificate Manager — the service that issues and auto-renews free
certificates for AWS. One rule catches everybody: a
certificate used by CloudFront must be issued in the us-east-1
region, whatever region you or your users are in
(Track B).
Certificate#
A file proving that whoever is serving yourthing.com really controls
yourthing.com, so the browser shows a padlock rather than a red warning. It is
layer 4, it is free, and in both
tracks it is issued and renewed for you.
Certificate authority#
An organisation browsers trust to issue certificates — Let's Encrypt, ACM, and others. Before issuing, it must verify you control the domain, which is why certificate setup so often sits waiting on a DNS record. See domain validation.
Domain validation#
The proof step a certificate authority demands: it
gives you a specific TXT or CNAME record to publish, or
a file to serve, and issues only once it can read it back. A certificate stuck
on "pending validation" is
layer 4 waiting on layer 2
— check the record actually resolves with dig.
HSTS#
A rule a site (or an entire TLD) can publish saying "only ever reach me
over HTTPS". Browsers then refuse plain HTTP with no click-through. The whole
.dev TLD is on the preload list, so a half-finished .dev setup looks
completely broken rather than partly working (Track B).
HTTPS#
HTTP with the connection encrypted, using TLS and a certificate. Browsers now warn on sites without it, so it isn't optional — but both tracks give it to you automatically, and neither charges for it.
Let's Encrypt#
The non-profit certificate authority that made certificates free in 2015, after which everyone else followed. You probably won't use it directly here — Cloudflare and AWS issue their own — but it's the reason layer 4 costs nothing.
Row Level Security#
A setting in Postgres — the open-source database Supabase is built on — controlling which rows each user may read or write. It is the only thing standing between a public anon key and your entire database. If you built on Supabase, confirm RLS is on and the policies are right before the repo goes public.
SNI#
Server Name Indication — the part of the TLS handshake where the
browser says which hostname it wants, so one server can hold certificates for
many sites. You'll only ever see it as "SSLSupportMethod": "sni-only" in the
CloudFront config. Leave it as
written.
TLS and SSL#
The encryption that puts the S in HTTPS. They are the same thing under two names: SSL is the old protocol, TLS the modern replacement, and the industry never stopped saying "SSL" out of habit. When a dashboard says SSL and a command says TLS, they mean each other.
Hosting and the cloud#
ARN#
Amazon Resource Name — the long unique identifier AWS gives every single thing
it owns, like
arn:aws:iam::123456789012:role/github-deploy. You'll copy them constantly on
Track B; the useful habit is reading them left to right as
service, account, then thing.
Binding#
Cloudflare's word for connecting a resource — a database, a
KV store, an R2 bucket — to your code, so it appears on
context.env at runtime with no connection string to manage. Added under
Settings → Bindings (Track A).
Bucket#
A container for files in S3 — think "a folder with a globally unique name". Yours stays completely private in this guide; only CloudFront is allowed to read it. Never put dots in the name, for a TLS reason explained at Track B, 4.1.
Budget alarm#
An AWS setting that emails you when spending crosses a threshold. It is the seatbelt for Track B, because this guide's whole setup should cost under a pound a month — so a $5 alarm means something is wrong, not you're being frugal. Set it before you build anything (accounts).
Build command#
The command your host runs to turn your source into servable files, almost
always npm run build. Static sites with no build step leave it
empty. Getting it wrong shows up as a failed build with a readable log; getting
the output directory wrong shows up as a successful build
and a blank site, which is much more confusing.
Build step#
The stage where source code becomes plain files a browser can read — React, Vue, Svelte, Vite and Astro projects all have one; a folder of hand-written HTML does not. Whether you have one decides several answers in the chooser.
Cache#
A stored copy of something, kept so it needn't be fetched again. There are at least four caches between your files and a visitor's eyes — your browser, your resolver, the CDN, and the host — and "old version still showing" is nearly always one of them rather than a failed deploy (troubleshooting).
Cache invalidation#
Telling a CDN to throw away its stored copies so it fetches fresh ones.
Cloudflare calls it Purge Everything; CloudFront calls it an invalidation
(aws cloudfront create-invalidation --distribution-id $DIST_ID --paths "/*"),
and it takes a couple of minutes. Clear the browser first — it's free and it's
the answer more often.
CDN#
Content delivery network — a fleet of servers around the world that keep copies of your files so visitors are served from somewhere near them. Cloudflare and CloudFront are both CDNs. It is also the thing that serves an old version of your site after you deploy, which is the price of the speed.
Cloudflare Pages#
Cloudflare's hosting product for static sites and Pages Functions: you connect a GitHub repo, it builds on every push and serves the result worldwide with a certificate included. It's the whole of Track A.
CloudFront#
AWS's CDN. On Track B it does three jobs at once: holds your domain name, handles the encrypted HTTPS connection using the ACM certificate (the jargon for that is "terminating TLS"), and reads files from a private S3 bucket that nobody else can touch.
Cold start#
The extra delay on the first request to a serverless function after it has been idle, while the platform starts a copy of it — typically a fraction of a second. It's the honest trade for paying nothing when nobody visits, and at personal-project scale it is not worth engineering around.
Cost Explorer#
The AWS screen that breaks your bill down by service. When a charge appears you don't recognise, group by service there first — it's usually the hosted zone or a NAT gateway created by accident (troubleshooting).
D1#
Cloudflare's managed SQL database — SQLite, the small single-file database engine, run for you — attached to your code as a binding. The right choice on Track A when you need real tables and queries rather than simple key-value storage.
Deploy#
Making the version of your project that's on your machine become the version
strangers see. After both tracks are set up, deploying is git push and nothing
else — the workflow or the host does the rest.
Distribution#
CloudFront's word for one CDN configuration — which origin to
read from, which domain names to answer for, which
certificate to present. Its ID (E1ABCDEF…) is what you pass to
invalidation commands, and it's
safe to publish.
Durable Objects#
Cloudflare's answer for things that must remember where they got to and keep a connection open rather than answering one request and forgetting — a chat room, multiplayer, a live game. (The open-connection technique is called a websocket.) Mentioned once in this guide as the advanced escape hatch for Shape 3; it's a step beyond a first deploy.
Edge#
Shorthand for "the CDN servers near your visitors", as opposed to the single place your files are stored. "Runs at the edge" means your code executes in a data centre close to whoever asked, which is how Workers respond quickly worldwide without you deploying anywhere.
Eventual consistency#
The property that a change to a cloud service may take a few seconds to become
visible everywhere. It's why Track B has a literal
sleep 10 after creating an IAM role: the role exists, Lambda just
can't see it yet, and the error blames the role rather than the timing.
Free tier#
The amount of a paid service you can use for nothing. Two shapes worth telling apart: Cloudflare's free tiers generally stop serving when exhausted, while AWS's generally start charging — which is the real reason the chooser treats bill-shock risk as a temperament question. Always check the live pricing page; published limits change.
Function URL#
An HTTPS address AWS gives a Lambda so it can be called directly. The older way needed API Gateway — a separate, more configurable AWS service that sits in front of a function and routes requests to it — which a first project can happily skip. Creating a function URL is two commands, not one: the URL alone returns 403 until you also add the permission.
Infrastructure as code#
Describing your cloud setup in files you commit, instead of clicking around a provider's web dashboard (AWS calls its dashboard the console) — AWS SAM, CDK and Terraform are the usual tools. Worth looking at after you've done this guide by hand twice, because then you'll understand what the tool generates instead of copying a template you can't debug.
Lambda#
AWS's serverless compute: your code runs when a request arrives, then stops. You pay per request, the free allowance is large, and it's how Track B adds a backend. The equivalent on Track A is a Pages Function.
Managed platform#
A host that runs a whole always-on process for you — Fly.io, Railway, Render, Streamlit Community Cloud, Hugging Face Spaces. (Supabase and Neon are the same idea for a database rather than for your code.) Neither track's free tier suits Shape 3, so this is where a Flask app or a Discord bot should go; the domain and DNS parts of this guide still apply unchanged.
NAT gateway#
An AWS networking component that costs real money per hour and is easy to create by accident when following an unrelated tutorial. Named here only so that if an unexplained charge appears in Cost Explorer, you recognise the usual suspect.
Object#
What S3 calls a file. A bucket holds objects, each with a key (its path) and its contents. The distinction only matters when reading AWS documentation, which never says "file".
Origin (hosting)#
The place a CDN fetches from when it doesn't have a copy — your
S3 bucket, or a Lambda behind /api/*. This word means
something completely different in git — see origin (git) — and
they appear on the same pages of this guide, which is genuinely confusing rather
than your misunderstanding.
Origin Access Control#
The CloudFront feature that lets a distribution read a private S3 bucket that is closed to everybody else. Usually written OAC. It is what makes "private bucket, public site" possible, and it's paired with a bucket policy naming your specific distribution.
Output directory#
The folder your build step produces — dist/, build/, out/,
_site/, public/. Point the host at the wrong one and you get a green build
and a blank site, the most common non-error failure in this guide. To find it,
run the build locally and look at which folder appears
(Track A).
Pages Functions#
Cloudflare Pages' built-in backend: any file in a functions/ folder at the
repo root becomes an API endpoint matching its path, with no
separate deploy. functions/api/ask.js answers at /api/ask. Put the folder
inside src/ and your API returns your HTML instead
(Track A).
Preview deployment#
A complete, separately-addressed copy of your site built from a pull request, so you can look at a change before merging it. Cloudflare Pages does this automatically for every PR, and it's one of the genuinely nice things you get for free (Track A).
R2#
Cloudflare's file storage, compatible with the S3 API and — the reason people choose it — with no charge for data leaving it. Good for user uploads and images (Track A).
Region#
The physical location of an AWS service — eu-west-2 is London, us-east-1 is
Northern Virginia. Mostly you pick one near you and forget it, with two
exceptions on Track B: ACM certificates for CloudFront
must be in us-east-1, and bucket creation in us-east-1 needs the
--create-bucket-configuration flag omitted or it fails with
InvalidLocationConstraint.
Rollback#
Putting a previous version back as the live one. On Cloudflare Pages it's a button next to any past deployment and takes effect immediately without touching your git history (Track A).
Runtime#
The language version a Lambda runs on, written like nodejs24.x.
Runtimes go stale and AWS eventually refuses the old ones, so if a
create-function call rejects your runtime string, check the
supported list
before debugging anything else.
S3#
AWS's file storage, and where your site's files live on Track B. Files go in a bucket; the bucket stays private; CloudFront is the only thing allowed to read it.
Serverless#
Code that runs per request and then stops, on machines you never see or manage. There are still servers — you just don't own, patch or pay for idle ones. Both tracks' backends (Workers, Lambda) are serverless, which is why a personal project's backend rounds to free.
SPA#
Single-page app — a site where JavaScript rewrites the page as you navigate,
rather than the server sending a new document (React Router and Vue Router are
the usual signs). It has one deployment consequence: deep links like
/about return 404 because
there's no about.html, until you configure 403 and 404 to serve
/index.html with status 200.
Static site#
A site made only of files — HTML, CSS, JavaScript, images — with nothing running on the server. It's the cheapest and most robust thing to host, and it includes anything with a build step that outputs a folder. See Shape 1.
Static site generator#
A tool that turns templates and content into a folder of plain files — Astro, Eleventy, Hugo, Jekyll, Next.js in static-export mode. From the host's point of view the result is just a static site; all you need to know is its build command and output directory.
Supabase#
A hosted Postgres (open-source database) platform with logins and live updates built in, commonly paired with either track. Its anon key is designed to be public — but only safely so if Row Level Security is on and your policies are correct (05-github).
Virtual machine#
A whole computer you rent, that stays on and that you're responsible for patching. Sometimes the honest answer for Shape 3 — a Discord bot or a game server — and unlike everything else in this guide it costs money whether or not anyone visits.
Workers#
Cloudflare's serverless platform, running your code at the edge. Pages Functions are Workers with the configuration hidden; Cloudflare is gradually merging the two products, which is why documentation may push you towards Workers when Pages is simpler for a first deploy.
Workers KV#
Cloudflare's key-value store: you save a value under a name and fetch it back by that name. Good for settings, sessions and counters; no good for anything where you need to search or combine records. Attached to your code as a binding; for real tables use D1.
wrangler#
Cloudflare's command-line tool, used for logging in and for deploying Workers.
Run it with npx wrangler … rather than installing it globally, so you always
get a current version. Like the AWS CLI, it holds its own login — which is why
you never paste a Cloudflare secret into a chat.
Git and GitHub#
Branch#
A named line of development. main is the one that deploys; making a branch
lets you work on something without touching what's live, and a
pull request is how it comes back. For a solo project you can
happily work on main for a long time.
CI and CD#
Continuous integration and continuous deployment — jargon for "a server runs your checks and your deploy automatically when you push". You get CD in this guide the moment GitHub Actions or Cloudflare Pages starts building on push; you don't need to say the words to use it.
Clone#
Making a local copy of a repository that stays connected to the
original, with git clone or gh repo clone. Distinct from a fork,
which makes a copy on GitHub under your own account.
Commit#
A saved snapshot of your project, with a message describing it. Commits are
effectively permanent: a secret committed and deleted in the next commit is
still in the history and still fetchable, which is why
.gitignore comes first.
Fork#
Your own copy of somebody else's repository, on GitHub, under your account. It's what GitHub offers when you try to edit a repo you don't own, and it's step one of adding yourself to the showcase — you're editing your copy, not mine, and you can't break anything.
Force-push#
Overwriting the repository's history with a different version of it, needed after any history rewriting. It breaks every existing clone and fork, so it's painless on a repo nobody else has and disruptive on one they do.
gh#
GitHub's official command-line tool. It creates repos, sets
secrets and watches workflow runs without you
opening a browser, and gh auth login handles authentication properly so you
never deal with a personal access token
(05-github).
git#
The program on your machine that tracks changes to your files. git is not GitHub — git is the tool and works entirely offline; GitHub is a website that stores copies of git repositories. Almost every "I don't understand git" moment starts with that conflation.
.gitignore#
A file listing patterns git should never track — .env, node_modules/,
dist/, *.pem. It must exist before your first commit, because it only
prevents things being added, and cannot remove what's already in the history
(05-github).
GitHub#
The website that hosts git repositories, plus everything built around them — pull requests, Actions, issues, secret scanning. Both tracks deploy from a GitHub repo, which is why 05-github comes before either.
GitHub Actions#
GitHub's built-in automation: you commit a workflow file, and
GitHub runs it on a machine it provides whenever the trigger fires. On
Track B it's what makes git push deploy to AWS;
it's also a free way to run a scheduled job.
GitHub secret#
An encrypted value stored on your repository, readable by
workflows as ${{ secrets.NAME }} and never displayable again in
the UI. Track B puts the
AWS account ID here — not because it's a credential, but
because it's reconnaissance you needn't hand out.
GitHub variable#
The same idea as a secret but not hidden — you can read it
back, and it's for values that are effectively public anyway, like a
bucket name or a distribution ID. Referenced as
${{ vars.NAME }}.
History rewriting#
Editing past commits to remove something — usually a leaked secret —
with git-filter-repo or
BFG Repo-Cleaner. It requires a
force-push, and it is always the second step: rotate the key
first, because a public commit is scraped within seconds
(05-github).
Issue#
A numbered discussion thread on a repository — a bug report, a question, a suggestion. Opening one is how you tell this guide it's wrong, and how you'd report a broken step or an out-of-date price.
Licence#
The file saying what others may legally do with your code. Without one, "public" means "you may look and nothing else" — nobody may use, fork or build on it. See MIT; GPL-3.0 if you want changes shared back; Unlicense if you genuinely don't care.
main#
The default branch name on GitHub, and by convention the one that
deploys. Older repositories and documentation call it master; they are the
same thing under an older name.
Merge#
Combining one branch into another — usually accepting a
pull request into main. On a repo with automatic
deploys, merging to main is what makes the change go live.
MIT licence#
The standard "do what you like, don't sue me" licence, and what most personal projects use, including this one. It's three paragraphs long; you edit the year and your name and you're done (05-github).
Open source#
Publishing your code under a licence that lets other people use and change it. It is a legal state, not a quality bar — half-finished things that work are entirely welcome, and adding yourself to the showcase may well be your first contribution to someone else's.
Origin (git)#
The default name for the remote your repository was cloned from or first pushed to — in practice, "the copy on GitHub". This is a completely different meaning from origin in a CDN, and both appear in this guide. If a sentence mentions pushing, it's this one; if it mentions caching, it's the other.
Personal access token#
A long-lived password-substitute some tools want for GitHub. You shouldn't need
one: gh auth login uses a browser flow and stores credentials properly for
both gh and git. If something is asking you to create a
token, check whether gh auth login would do instead.
Pull request#
A proposal to merge one branch into another, with a place to discuss it first. Often shortened to PR. It is also how you contribute to somebody else's project, and the showcase walks through making one entirely in the browser, with no terminal.
Push#
Sending your local commits to the remote, with git push.
Once either track is set up, this is your deploy — everything that follows
happens without you.
Push protection#
A GitHub feature that blocks a push containing something matching a
known credential format, before it ever reaches the server. Free on public
repos, enabled with one gh repo edit flag, and it has saved an enormous number
of people from a very bad afternoon
(05-github).
README#
The file GitHub shows on your repository's front page. People decide in seconds whether to keep reading, so it leads with one sentence, a live link and a screenshot — 30-share-it gives the running order.
Remote#
A copy of your repository that lives somewhere else, referred to
by a short name. You'll almost always have exactly one, called
origin, pointing at GitHub.
Repository#
A project tracked by git — your files plus their entire history. Often
shortened to repo. Both tracks treat the repo as the source of truth: what's on
main is what's live.
Runner#
The temporary machine GitHub provides to execute a workflow, named
in the file as runs-on: ubuntu-latest. Two consequences bite people: it's
Linux, so filename case matters, and it starts empty, so
anything your build needs must be installed or committed.
Secret scanning#
GitHub scanning your repository for strings that look like credentials and alerting you. Free on public repos. Its more useful sibling is push protection, which stops the secret arriving in the first place.
Stage#
Marking changes to be included in the next commit, with git add.
The gap between staging and committing exists precisely so you can run
git status and actually look before anything becomes permanent
(05-github).
Topics#
Keyword tags on a GitHub repository, set from the gear next to About. They're most of how anyone discovers a repo, so pick five or six that genuinely describe it — the language, the kind of thing it is, where it runs (30-share-it).
Workflow#
A YAML file in .github/workflows/ describing what
GitHub Actions should run and when. Track B's is a dozen
lines: check out the code, build it, assume an AWS role via
OIDC, sync to S3, invalidate
CloudFront.
Keys and identity#
Access key#
An AWS credential in two parts: an access key ID (starts AKIA…,
semi-public) and a secret access key, shown exactly once and never
recoverable. Together they let the CLI act as you. Never create one for the
root account, never commit one, and
rotate on suspicion
(03-keys-and-access).
Anon key#
A key deliberately designed to sit in browser code — Supabase's anon key,
Stripe's pk_ publishable key. Safe to publish only if the service's access
rules are correct behind it; for Supabase that means
Row Level Security
(05-github).
API key#
A string that identifies and authorises your app when it calls somebody else's service. It is a password with a bill attached: whoever holds it can spend your money. This is why it lives in an environment variable on the server and never in browser code (03-keys-and-access).
Audience claim#
The aud field in a JWT, naming who the token is for — in
Track B's OIDC setup it must
equal sts.amazonaws.com. Along with the subject claim, it's
one half of what the trust policy checks.
Authentication and authorisation#
Authentication is who you are; authorisation is what you're allowed to do. They're both shortened to "auth", which is why error messages are confusing: a 403 usually means you authenticated fine and simply aren't permitted, and retyping your password will not help.
AWS account ID#
The twelve-digit number identifying your AWS account. Not a credential — it appears in every ARN — but it is useful reconnaissance for an attacker, so this guide puts it in a GitHub secret rather than a variable.
Blast radius#
How much damage a credential could do if it were misused. Track B scopes the deploy role to exactly one bucket and one distribution, so the worst case is "overwrite my site" rather than "empty my bank account" (20-aws).
Claim#
One statement inside a JWT — "this token is for GitHub Actions", "it came from repository X, branch main". AWS reads the claims to decide whether to hand back credentials, which is why the fix for a failing OIDC setup is to print the claims rather than guess at them.
Credential#
Anything that proves identity to a system: a password, an access key, an API key, a private key file. The distinguishing test for this guide is simple — if publishing it would let a stranger act as you, it's a credential and it never touches your repo.
.env#
A plain text file of NAME=value lines holding your local secrets, read by your
app at startup. It must be in .gitignore from the very
beginning. Its committed sibling .env.example lists the names with fake
values so anyone cloning your repo knows what to fill in
(03-keys-and-access).
Environment variable#
A named value handed to a program by whatever started it, rather than written inside it. It's how the same code runs with a real key in production and a test key locally. Two things catch people: variables are read at build or start time, so a change needs a redeploy, and setting one in a terminal lasts only for that terminal (03-keys-and-access).
IAM#
Identity and Access Management — AWS's system of users, roles and policies deciding who may do what. Nearly every confusing AWS error is an IAM error wearing a different hat.
IAM Identity Center#
AWS's newer login system, where aws sso login grants short-lived credentials
and nothing durable sits on disk. Genuinely better than an
access key, and more moving parts than a first project needs —
Track B says start simple and
upgrade later.
IAM user#
A named identity inside your AWS account, separate from the root account, with its own credentials. You create one for the CLI so that a leaked key can be deleted without losing the account itself (accounts).
Identity provider#
A system another system agrees to trust for authentication. Track B registers GitHub as one in AWS, which is what makes keyless deploys possible: AWS believes GitHub when it vouches for a workflow run.
JWT#
JSON Web Token — a signed blob of JSON asserting facts
(claims) about who is calling. GitHub mints one per workflow run and
AWS verifies it. The parts you may print — sub, aud, repository — are not
secret, but the whole token is a credential, so never log it
(20-aws).
Least privilege#
Granting exactly the permissions needed and no more. This guide deliberately
breaks it once, using AdministratorAccess on a personal account, and says why:
fighting permission errors all afternoon is a worse outcome than relying on
MFA and a budget alarm as the real guardrails
(20-aws).
MFA#
Multi-factor authentication, also written 2FA — a code from an app on top of your password. Turn it on for GitHub, Cloudflare and especially the AWS root account before anything else, because it removes an entire category of disaster for two minutes' work (accounts).
OIDC#
OpenID Connect — the standard letting GitHub prove a workflow run's identity to AWS directly, so AWS can hand back credentials that expire in minutes. The point is that no AWS key exists in GitHub at all (20-aws).
Policy#
A JSON document listing permitted actions and the resources they apply to. Two kinds appear in this guide: permission policies attached to a role saying what it may do, and trust policies saying who may become it.
Principal#
The "who" in an AWS policy — an account, a role, or an AWS
service such as cloudfront.amazonaws.com or lambda.amazonaws.com. Every
Principal block in Track B is naming who is allowed to do the
thing described next to it.
Role#
An AWS identity that can be assumed temporarily, rather than logged into. A Lambda runs as one; a GitHub workflow assumes one via OIDC. Roles are how AWS avoids long-lived keys, and are the single most useful IAM concept to actually understand.
Root account#
The email and password you created an AWS account with. It can do anything, including close the account and spend without limit. Give it MFA immediately, never create an access key for it, and use an IAM user for daily work (accounts).
Rotate a key#
Delete a credential and issue a replacement. Do it on suspicion, not proof — it takes thirty seconds, and it's the first step when anything leaks, before any tidying of git history (03-keys-and-access).
Secret#
Any value that would let someone act as you or spend your money. The line is
drawn concretely in 05-github — source
code, domain names and bucket names are fine to publish; .env files, AKIA…
keys, sk_ keys and .pem files never are.
Secrets Manager#
AWS's dedicated store for secrets, with per-secret monthly pricing. Worth graduating to for anything you'd genuinely mind leaking, because Lambda environment variables are visible to anyone with console read access to the function (20-aws).
STS and AssumeRole#
STS is AWS's Security Token Service — the thing that hands out temporary
credentials. sts:AssumeRole is asking to become a role;
sts:AssumeRoleWithWebIdentity is the OIDC variant GitHub uses.
aws sts get-caller-identity is also the quickest way to check your CLI is
working at all.
Subject claim#
The sub claim in GitHub's JWT, identifying which repository
and branch the workflow ran in. It is the security boundary of the whole
keyless-deploy setup. Since mid-2026 GitHub gives every newly created, renamed
or transferred repository an ID-qualified (GitHub calls it immutable)
subject — repo:you@8456990/your-repo@1329892525:ref:refs/heads/main, where the
numbers are the permanent account and repository IDs — so a repo you make while
following this guide almost certainly has one, and patterns you guessed from an
older tutorial won't match. Print the real value rather than guessing, and never
widen it with wildcards
(20-aws).
Trust policy#
The policy attached to a role saying who may assume it —
as opposed to what it can do once assumed. Track B's trust policy is what
restricts an AWS role to workflows from one specific GitHub repository, and a
mismatch there produces Not authorized to perform
sts:AssumeRoleWithWebIdentity.
Web and general#
Absolute and relative URL#
A relative URL (/preview.png) is interpreted against the page it appears on;
an absolute one (https://yourthing.com/preview.png) works from anywhere. It
matters most for Open Graph images: the machine fetching your
page to build a link preview isn't on your site, so a relative path means
nothing to it and the preview comes out blank
(30-share-it).
API#
An interface one program uses to talk to another, over the web in this guide's
sense. Your page calls your API at /api/ask, and your API calls somebody
else's — Anthropic's, say — with an API key the browser never sees.
apt#
The package manager on Debian and Ubuntu, and therefore
inside WSL. sudo apt install git jq curl zip dnsutils installs most of
what this guide needs (00-start-here).
bash#
The shell language this guide's commands are written in — the default on Linux and inside WSL, and available on macOS. Its syntax is not PowerShell's, which is why Windows users are pointed at WSL or Git Bash before Track B in particular (00-start-here).
Browser cache and hard reload#
Your browser keeps its own copies of pages, scripts and images, separately from any CDN. A hard reload — Cmd/Ctrl + Shift + R — fetches fresh copies, and a private window sidesteps the cache entirely. Do this before suspecting a deploy failed; it's five seconds and it's the answer more often than not.
Case sensitivity#
Linux treats Header.jsx and header.jsx as different files; macOS and Windows
usually don't. Since builds run on Linux, a filename whose case
doesn't match the import produces "module not found" for a file you can plainly
see (troubleshooting).
CLI#
Command-line interface — a program you drive by typing rather than clicking, in
a terminal. git, gh, aws and wrangler are all CLIs. They
tend to be more reliable to follow in a guide than dashboards, because a
dashboard's menus get renamed and a command doesn't.
curl#
A command-line tool for fetching a URL, used throughout this guide to check
things from outside a browser. curl -sI https://yourthing.com | head -1 prints
just the status line — the fastest way to tell whether your
site is actually answering.
Endpoint#
One addressable URL that does something — /api/ask, /api/save. On
Track A each file in
functions/ becomes one; on Track B a Lambda behind /api/* does.
ETag#
A short identifier for the current version of a resource, used so that changes can't overwrite each other. It matters in exactly one place here: deleting a CloudFront distribution requires a fresh ETag with each modification, and reusing a stale one fails.
Favicon#
The small icon shown in a browser tab, conventionally favicon.ico or a PNG
linked from your <head>. Not required for anything to work, but its absence
is the difference between a site that looks finished and one that doesn't —
worth adding alongside your Open Graph image
(30-share-it).
Git Bash#
A bash shell for Windows that comes with Git for Windows. Fine for Track A and for getting onto GitHub; Track B's heredocs mostly work but path handling occasionally bites, so WSL is the better answer there.
Headless browser#
A real browser running with no window, driven by a script. It's how the guide's
og-image.sh renders a card to an exact 1200×630 PNG
(30-share-it) — the same rendering as your
screen, just captured instead of displayed.
Heredoc#
The cat > file <<EOF … EOF shape used throughout Track B
to write a config file. It is one command, not three — paste the whole block
including the closing EOF. Paste it line by line and you'll sit at a bare >
prompt with no output and no error, waiting for the EOF; press Ctrl-C and
start again.
Homebrew#
The package manager most people use on macOS, installed with the one-line script
in 00-start-here. After it,
brew install git gh jq awscli gets you everything both tracks need.
HTML, CSS and JavaScript#
The three languages a browser understands: HTML is the content and structure, CSS the appearance, JavaScript the behaviour. A static site is these three plus images, and everything else in web development eventually produces them.
HTTP#
The protocol browsers use to ask for pages and receive them. Plain HTTP is unencrypted; HTTPS is the same thing with TLS around it. Both tracks redirect HTTP to HTTPS for you.
HTTP header#
A name-and-value line attached to a request or response, carrying things the
body doesn't — content-type: application/json, an API key, a cache
instruction. curl -sI shows you a response's headers without its body.
HTTP status code#
The three-digit number in every HTTP response saying how it went. The ones this guide runs into:
| Code | Means | Usually because |
|---|---|---|
| 200 | Fine | Nothing to do |
| 403 | Forbidden | You're identified but not permitted — a bucket policy, or a function URL missing its add-permission |
| 404 | Not found | Wrong output directory, or an SPA deep link with no error-page rule |
| 429 | Too many requests | A free tier limit — Cloudflare's failure mode instead of a bill |
| 500 | Server error | Your code threw — usually a missing environment variable |
| 502 | Bad gateway | The thing in front couldn't reach the thing behind — e.g. CloudFront failing TLS to a dotted bucket name |
IP address#
The numeric address of a machine on the internet — 104.21.5.12 (IPv4) or the
longer colon-separated IPv6 form. DNS exists to save you from ever
typing one, and CNAME records exist so your host can change theirs
without telling you.
jq#
A command-line tool for reading and reshaping JSON. Track B uses it to pull IDs out of AWS responses and to build change files, which is why it's in the install list (00-start-here).
JSON#
A plain-text format for structured data — objects in braces, lists in brackets. Nearly every AWS command returns it, every API in this guide speaks it, and YAML (used by GitHub Actions) is the same shapes with indentation instead of punctuation.
localhost#
The name your computer uses for itself. http://localhost:3000 is a server
running on your own machine, reachable by nobody else — which is precisely the
problem this guide exists to solve.
Lockfile#
A file recording the exact version of every dependency actually installed —
package-lock.json for npm. It must be committed, because it's what
npm ci reads on the build machine; without it, the host resolves different
versions from yours and "works locally, fails on the host" follows.
Node.js#
The program that runs JavaScript outside a browser — used by build tools,
Workers and Lambda. Its version matters: a build that
works locally and fails on the host is most often a version mismatch, fixed by
setting NODE_VERSION (Track A) or node-version (Track B) to match your
node -v.
node_modules#
The folder holding your installed dependencies. It is enormous, machine-specific
and rebuildable from the lockfile, so it belongs in
.gitignore and never in a commit.
npm#
Node's package manager. Three commands cover this guide:
npm install adds dependencies, npm ci installs exactly what the
lockfile says (what build machines use), and npm run build runs
your build command.
Open Graph#
The <meta property="og:…"> convention every social platform reads to build a
link preview card. Four tags — title, description, image, url — decide whether a
shared link looks like something or like a bare blue link nobody clicks. Get it
right before you post, because platforms cache the first version they see
(30-share-it).
Package manager#
A tool that installs software and its dependencies for you: Homebrew on macOS, apt on Ubuntu, winget on Windows for system tools; npm for your project's JavaScript libraries. Same idea, different scopes.
Port#
The numbered door on a machine that a particular program listens at — the
:3000 in http://localhost:3000. Once your project is deployed you stop
thinking about ports, because the web uses 80 and 443 and the host handles both.
PowerShell#
Windows' own shell. This guide's commands are bash and will not all work in it — the heredocs and quoting in Track B especially. Use WSL, or Git Bash, or take Track A, which needs far less terminal (00-start-here).
Server#
A program (on a machine somewhere) that waits for requests and answers them. The useful distinction for this guide is between a static site, where no program of yours runs at all, and a backend, where one does — and between serverless, which starts one per request, and a virtual machine, which keeps one running.
Shell#
The program inside a terminal that reads what you type and runs it. bash and zsh are shells; PowerShell is a different one with different syntax. "Open a shell" and "open a terminal" are used interchangeably in practice.
Shell variable#
A named value in your current terminal, set with export NAME=value and read
back as $NAME. The catch that bites hardest on
Track B: it lasts
only as long as that window. A new tab, and every variable is an empty string
— and commands then fail with something baffling like
Invalid length for parameter rather than "that's empty". Keep them in a file
and source it.
Terminal#
The window where you type commands. macOS has Terminal and iTerm; Windows has Windows Terminal; Linux has several. It is only a window — the thing interpreting your typing is the shell (01-your-machine).
URL#
The full address of something on the web:
https://yourthing.com/api/ask is protocol, hostname, path.
Getting your project one — a real one, that you own — is the entire point of
this guide.
winget#
Windows' built-in package manager.
winget install Git.Git GitHub.cli installs git and gh
(05-github).
WSL#
Windows Subsystem for Linux — a real Ubuntu terminal inside Windows, installed
with wsl --install from an administrator PowerShell. It's the recommended
Windows setup here because every command in the guide then works exactly as
written, heredocs included
(00-start-here).
zip#
The command that packages files into a .zip, used to bundle a
Lambda before uploading it. Preinstalled on macOS; on Ubuntu or WSL,
sudo apt install zip (20-aws).
Next: When it breaks → if something is failing right now — otherwise back to Start here.