The Copilot Stack is a static website. Pages are pre-rendered HTML served as files, which removes most of the ways a site would ordinarily collect information about you.
There is one exception, and it is opt-in: if you choose to sync your lesson progress between devices, that uses a small server with a database holding your email address. Nothing on this site asks you to, and every lesson works identically if you never do.
What is stored in your browser
16 kinds of entry may be written to your browser's localStorage, and only when you use the feature that writes one. None holds a name, an address or an identifier — lesson numbers, paths and scores are the whole of it. None is transmitted anywhere unless you have turned on progress sync, which copies the7 marked below and nothing else. Some features also send one anonymous count to analytics when you use them; the complete list is further down, and none of those counts carries anything from your browser's storage.
| Feature | Key | What it holds | Synced |
|---|---|---|---|
| Lesson progress | tcs:progress:cluster-N | A list of lesson numbers you marked complete | If you turn on sync |
| Progress timestamps | tcs:progress:meta | When each lesson last changed, so two devices merge without one overwriting the other | Never |
| Assessment results | tcs:assessment:cluster-N | Your best and latest score for a cluster assessment, and the lessons behind the questions you missed | If you turn on sync |
| Labs | tcs:labs:completed | Which labs you marked complete | If you turn on sync |
| Saved lessons | tcs:bookmarks | The lessons you saved, as a list of paths | If you turn on sync |
| Recently viewed | tcs:progress:recent | The last few lessons you opened, so Continue Learning knows where you were | If you turn on sync |
| Learning path | tcs:path | The role-based path you chose | If you turn on sync |
| Milestones | tcs:milestones:seen | Which milestones have already been announced, so a badge is celebrated once | If you turn on sync |
| Short sessions | tcs:sessions | Which steps of each short session you ticked, and when you started and finished it | Never |
| Lab checkpoints | tcs:lab-checkpoints | Which checkpoints of each lab you ticked, and when you started and finished — never the output you pasted | Never |
| Project Setup Kit | tcs:setup-kit | Your last selections in the Setup Kit (stack, editor, testing, docs, team, and the project name you typed) — never the generated files | Never |
| Knowledge checks | tcs:checks:completed | Your best score on each lesson's knowledge check, and when you last took it | Never |
| Changes page | tcs:changes:last-seen | When you last opened the changes page, to mark what is new since | Never |
| Sync timestamps | tcs:sync:stamps | When each saved item last changed. Only written once you turn on sync | Never |
| Sync removals | tcs:sync:tombstones | Items you removed, held until the server has been told, so a removal is not undone by another device | Never |
| Lesson feedback | tcs:feedback:/lesson-path/ | Whether you clicked "Yes" or "No" on a specific lesson | Never |
By default these entries stay on the device that created them. They are not uploaded, not synced between devices and not shared with anyone, which is also why your progress will not follow you to another browser unless you ask it to. Turning on progress sync changes that for the progress entries only, and for nothing else on this list — your feedback answers are never uploaded either way.
To remove it, use the button below, clear site data for this domain in your browser settings, or un-mark the lessons individually — the completion control toggles both ways.
Cleared entries. If you are signed in, your account still holds a synced copy — delete that from the account page.
Feedback buttons
The "Was this lesson helpful?" control does two things. It stores your answer in this browser, so the buttons still show your choice when you come back. It also sends one anonymous event to our analytics, carrying the lesson's path and whether you found it helpful, and nothing else — no identifier, no cookie, no session, nothing that distinguishes you from any other reader who clicked the same button.
The event fires only when your answer changes, so reloading a page does not send it again. If you block analytics, the control still works as a device-local bookmark and we simply learn nothing.
This tells us which lessons land and which do not. It cannot tell us why. If something here is wrong rather than merely unhelpful, the corrections process is the route that reaches a person.
Progress sync accounts
This is the only part of the site that stores anything personal, and it only exists if you go to the account page and ask for it. If you never do, there is no record of you here at all.
If you do, we store exactly this:
| What | Why | Kept for |
|---|---|---|
| Your email address | To send the sign-in link and to attach your progress to | Until you delete your account |
| Which lessons you completed, and when | The thing being synced; the timestamp is what lets two devices merge | Until you delete your account |
| Saved lessons, completed labs, assessment scores, your chosen path and recently viewed lessons | The rest of what syncing carries, so a second device shows the same dashboard as the first | Until you delete your account |
| Whether you asked for email, and what about | So we can send what you asked for and nothing else. Separate from your account on purpose — signing in is not subscribing | Until you unsubscribe or delete your account |
| What you have bought, if anything | To unlock the files you paid for. Card details are never seen by this site — Stripe handles payment and we store only a customer reference | Until you delete your account |
| Sign-in links you requested | Stored hashed, never in readable form, so the database cannot be used to sign in as you | 15 minutes, or one use |
| Request counts | Rate limiting, so nobody can use us to send mail at someone | 24 hours |
There is no password, because we would rather not be responsible for one. Signing in sends a single-use link that expires in 15 minutes.
Signing in sets two cookies on this domain: tcs_session, which is what actually authenticates you and is marked HttpOnly so page scripts cannot read it, and tcs_signed_in, a flag with no authority that simply lets a page know whether to bother asking the server. Both are first-party, both expire after 90 days, and neither is used for tracking or sent anywhere else.
We do not store your IP address against your account, we do not profile you, and we will not sell or share any of it.
Email you have to ask for
Signing in is not subscribing. The only message an account gets by default is the sign-in link you requested. Anything else —copilot changes, new research, new lessons, product updates, monthly learning summary — requires ticking a box on the account page that starts unticked, and untick it and we stop. We record when you ticked it, so there is an answer to "when did I agree to this".
Deleting it
The account page has a delete button. It removes your address, your synced records, your email preferences, any purchase record and any outstanding sign-in links immediately — not flagged as deleted, actually deleted — and the sign-in session stops working at once. A test enumerates the database and fails if any table holding your address is missed. Progress already saved in your browser is left alone, so deleting your account does not wipe the lessons you have read.
Deleting is complete rather than polite, and that includes anything you have bought: the record of the purchase goes with everything else, so signing up again later does not restore access automatically. The confirmation dialog says so before you confirm.
Analytics and tracking
This site uses Plausible Analytics to count page views and a small number of anonymous interaction counts. Plausible is cookieless and stores no personal data: it records no IP address, sets nothing on your device, and cannot follow you between sites or between visits. There is no consent banner because there is nothing to consent to.
Beyond the page view itself, the complete list of what is counted is:
- Feedback clicks — whether you answered yes or no to “Was this lesson helpful?”, and which lesson.
- Lesson completions — that a lesson was ticked complete, and which one. Un-ticking is not counted.
- Code copies — that a code block was copied, and the page it was on. Not the code.
- Searches — that a search returned results, or that it returned none. Never what you typed. A count of searches that found nothing is enough to tell us the index has a gap; what you were looking for is yours.
- Outbound clicks and file downloads — which external link was followed or which file was fetched.
- Learning progress — that a lab was started or completed, a cluster completed, a knowledge check or assessment started, completed or passed (with the score as a fraction, never which answers), a bookmark added, a milestone earned, a learning mode or learning path chosen, and which lesson or path. Only the identifier of the lesson, never anything you wrote.
- Navigation choices — that a “what to do next” recommendation was shown or followed, a practice link or a continue-learning link clicked, a task-start link followed, a link from an article into a lesson, lab or tool followed, and on which page.
- Short sessions and lab checkpoints — that a session was started, resumed, reset or completed, which step was ticked, and that a lab checkpoint was ticked and whether it was self-reported or browser-checked. Identifiers only; the ticks stay in your browser and any output you paste into a lab checkpoint is tested in the page and never stored or sent.
- Tools and calculators — that a tool was opened or produced a result. For the Workflow Rescue, which of the four problems you picked and which environment — never the prompt you edited, and never the boxes you tick in its checklist. For the usage calculator, one word: whether the projection was within or over the allowance. Never the numbers you entered. For the instruction diagnostic, the environment and symptom you selected from the lists — nothing typed, no paths, no file contents. For the Project Setup Kit, that a kit was started and generated and which of the three stacks — never the project name you typed, never the generated files. For the team readiness assessment, the resulting stage word — never the answers.
- Account and purchases — that a product page, the Pro preview, or a pricing section was viewed; that a sign-in, newsletter opt-in, checkout or purchase happened; and which product. No account identifier is attached.
- Research and datasets — that a dataset was downloaded, a research page shared, a changes page viewed, or a project repository opened.
Every event carries at most a handful of properties from a fixed list of short identifiers — a lesson slug, a placement, a session id, a step id, an outcome word. The analytics code drops anything else before sending, so a value you typed cannot reach the tracker even by mistake. Measurement events that fire because a block was seen or a step was ticked are sent as “non-interactive”, which tells Plausible not to treat them as engagement.
Every one of these is a count with no identifier attached, so none of them can be joined together into a picture of one person. You can switch all of it off for your own browser here; automated traffic is discarded before it is sent at all.
This browser is excluded from analytics. Nothing it does here is counted.This browser is counted in analytics, as a number with no identifier.
Stored as tcs_analytics_ignore in this browser's local storage and nowhere else. Clearing site data resets it.
Beyond that, this site ships no advertising tags, no social media pixels, no session recording and no fingerprinting. The only cookies this site ever sets are the two sign-in cookies described below, and they exist only if you create an account. There are no analytics, advertising or tracking cookies.
Third-party requests
Pages load their own assets — HTML, CSS, JavaScript, fonts and the Pagefind search index — from this domain. Web fonts are self-hosted rather than fetched from a font CDN.
That includes the analytics tracker. It is not fetched from plausible.io — it is bundled into this site's own JavaScript from Plausible's published package, so your browser downloads it from this domain like any other asset.
There is exactly one exception: the page view it counts is sent to plausible.io. So loading a page does disclose to Plausible that somebody viewed this URL — but not who, because nothing identifying is collected or sent. That single outbound request is the whole of this site's third-party surface; there is nothing else.
Lessons link out to external documentation, mostly GitHub's. Following such a link takes you to a site with its own privacy practices, over which we have no control.
Server logs
Whoever hosts this site may keep standard access logs — IP address, timestamp, requested URL, user agent — as a normal part of operating a web server. We do not use that data to build profiles or to identify individual readers.
Children
This site is aimed at software developers and engineering teams. It is not directed at children and does not knowingly collect information from them.
Changes
If this policy changes materially, the "Last updated" date above will change with it. Since the site collects nothing, most future changes are likely to be clarifications rather than expansions of data collection.