Privacy Policy
What CourseLite collects, where it goes, and how long it stays.
Effective date: 4 September 2026 Last updated: 4 September 2026
CourseLite is an online software service. In this policy, "we", "us" and "CourseLite" mean the operator of that service; "you" means the person using the website at courselite.org or the CourseLite Chrome extension.
CourseLite is operated from the United States and is offered in the United States. Where a governing law applies, it is the law of the State of California, United States.
CourseLite has no public office and does not take enquiries by post. Every question, request or complaint — including a privacy request, an account question and a legal notice — reaches us at one address, and a person reads it: support@courselite.org.
Every factual claim in this policy was checked against CourseLite's own source code on 4 September 2026.
1. The short version
CourseLite reads a college course you already have access to and turns it into a study assistant that answers from that course's own material.
Six things are worth knowing before anything else.
- Your course files are read in your own browser. The bytes of a PDF, a slide deck or a spreadsheet never reach our servers. What we receive is the text pulled out of them.
- Your course material is sent to an AI provider. That is how the product works. Today that provider is OpenAI. Section 7 says exactly what goes and what OpenAI says it does with it.
- We never see your Canvas password, session cookie or API token. The extension uses the Canvas session you are already signed into, in your own browser, and reads only.
- We ask Google for one narrow permission,
drive.file. It lets us see only the files CourseLite created or that you personally picked. We cannot see the rest of your Drive, and Google enforces that, not us. - We never see your card. Payment happens on Stripe's own pages.
- Your saved chats are stored on our servers, and this changed on 2026-09-04. This policy previously said the opposite, and said it here. The course workspace now keeps your last 10 conversations per course so they are there on your other devices, which means we hold the text of those questions and answers. Section 3.6 says exactly what is kept, for how long, and how to remove it. Deleting your account deletes all of it.
There are also things this policy is honest about being incomplete. Some records survive account deletion, and some retention timers exist in code but are not yet on a schedule, because nothing runs the cleanup on a timer. Sections 12 and 13 say so plainly rather than burying it.
CourseLite is in a private beta. Some of what is described here — Google's review of our app, live payments — is not finished yet, and this policy says where that is the case rather than describing the finished version as if it had arrived.
2. Where your information comes from
| Source | What it gives us |
|---|---|
| You, directly | Your display name, your instructor's name, your questions, and anything you type — and, if you joined before sign-up opened, your waitlist entry (section 3.2) |
| Clerk, our sign-in provider | A user id, and your email address |
| The Canvas course you import | Course structure, assignment text, page bodies, and the text inside course files |
| Google, if you connect it | The permission you granted, and the ids and names of files you pick, and the contents of files you export. Not which Google account you used — see section 8 |
| Stripe, if you subscribe | Your plan, subscription status, and renewal date |
| Your browser, automatically | Which page you are on, that a feature started or finished, and a random session id |
3. What we collect, in detail
3.1 Account and identity
Sign-in is handled by Clerk. Clerk holds your email address, your password or social sign-in method, and your session. We never see your password.
From Clerk we store two things in our own database:
- your Clerk user id, which is what every row of your data is attached to;
- a copy of your email address, so we can reach you and so Stripe can bill the right person. This field can be empty.
Your session token stays in your browser and in Clerk's storage. It is never written to our database. If a token or an email address would otherwise end up in one of our log lines, it is replaced with [jwt] or [email] before the line is written.
We also store, if you provide them:
- the name you want printed on a document you ask CourseLite to draft;
- the name of the instructor for a course, per course.
Both are optional. Both may be sent to the AI provider, because a name on a title page has to come from somewhere.
3.2 The waitlist
The waitlist is closed. There is no form on courselite.org and nothing can join it any more — you sign up for CourseLite directly instead.
Entries collected while it was open are still held. Each one is an email address in plain text, and optionally a university and a feature the person said they wanted. There is nothing else in that record but the date.
Two things about those entries, and neither flatters us.
- An entry is not attached to an account, and deleting your CourseLite account does not remove it. We have no way to connect the two, and connecting them would mean storing the link.
- There is no automatic expiry, and no route in the product that deletes one. Removing an entry is a database statement a person runs. Email support@courselite.org and we will run it — that is a real commitment, and it is the only mechanism there is.
3.3 Canvas course material
This is the largest category, and the reason CourseLite exists.
When you import a course, the extension reads it through the Canvas session you are already signed into, and sends us:
- the course name, code, its Canvas web address, and its Canvas course id;
- modules, module items, and their order;
- assignments: title, description, due, unlock and lock dates, points, the Canvas link, and the submission status Canvas reports;
- page bodies, the syllabus, announcements, discussions and quiz text;
- the text extracted from files — PDF, DOCX, PPTX, XLSX, CSV, Markdown, HTML;
- a hash and byte size of each file, so we can meter your storage;
- your Canvas user id, used only to make an anti-abuse hash (section 3.8).
Two things we want to be precise about.
The file itself does not leave your browser. Unzipping, parsing and text extraction all happen locally, in the extension. What crosses the network is text in a JSON body. CourseLite has no upload endpoint, no object storage, and no code that can accept a file.
Except for images nothing could read. If a page in a PDF is a scan, or a slide is a diagram with no text layer, that one picture is sent — once, at import time — to the AI provider so its contents can be transcribed. We store the transcription as ordinary document text. We do not store the image. The picture is never sent again.
Canvas access is read-only. There is no code in CourseLite that writes to Canvas, and no code that submits anything. Drafting homework is a feature; handing it in is not, and is not something CourseLite can do.
3.4 Anything else you add
If you paste a note, add material by hand, or supply a file you exported yourself, it is stored the same way: as text, in the same table as everything else, attached to the course you added it to.
A course you create yourself — new on 2026-09-09 — is stored the same way as one you import: the same table, the same row. What we hold for it is what you typed: the course name, and the course code, instructor and term if you filled them in. It has no Canvas web address and no Canvas course id, because there is no Canvas behind it, and nothing about it is sent anywhere. Everything in section 12 about how long it is kept, and everything in section 13 about deleting it, applies to it unchanged.
3.5 Google Workspace
Section 8 covers this in full, because Google requires it to be covered in full. In summary, we store the scopes Google told us you granted and the id, name, kind and link of each file you picked or that CourseLite created. If you export a Google Doc or Slides into a course, its text is stored like any other document.
We do not learn which Google account you used. The only permission we ask for is drive.file, which does not tell an app who you are — there is no openid and no userinfo.email in the request — so Google never sends us your Google account id or your Google email address. Columns for them exist in our database and are empty in every row, and the connect endpoint no longer accepts either from a request. If CourseLite ever shows "connected as ...", it will be because we added a verified source for it, and this section will say so first.
We do not store your Google access token anywhere, ever.
3.6 Questions, retrieved context, and AI output
When you ask a question, we send the AI provider your question, up to about eight passages of your own course material, and — for a homework draft — the assignment brief.
We store what comes back: generated answers where a feature saves them, flashcards, practice tests, homework drafts, plans and revisions, and slide or document content.
Saved chats — what changed on 2026-09-04
Until 2026-09-04 this section said "we do not store the conversation. There is no chat, message or conversation table in our database." That was true and it is no longer true. We are stating the change plainly rather than quietly editing the old sentence away.
The course workspace now saves your conversations so that you can come back to one, and so that they are there when you sign in on another device. What that means concretely:
- We store the text of your questions and of the assistant's answers, plus the list of course materials each answer cited, in two tables (
chat_threadsandchat_messages). - Ten per course, and no more. When you start an eleventh conversation in the same course, the one you have not used for longest is deleted. The app tells you this rule in the chat menu before it ever costs you anything.
- You can delete any conversation yourself, at any time, from that menu. Deleting one removes its messages too, immediately and for good.
- Deleting your account deletes every conversation, by database cascade rather than by a cleanup job that could be missed.
- Your conversations are never used for analytics. Our analytics tables record event names and counts, never content, and nothing in the product reads a message body except the request that shows it back to you.
- There is no admin screen that displays your conversations, no search across them, no sharing, and they are not used to train anything.
The chat on a course page and the chat beside an assignment are not saved this way; those still live only in your browser tab, as described in section 6.
Study progress — new on 2026-09-09
Until 2026-09-09 the study modes stored nothing on our servers. Closing the tab lost your place. That has changed, for the obvious reason: eighteen cards into a set of forty is work, and losing it is not a feature. As with saved chats, we are stating the change plainly rather than quietly editing the old sentence away.
What is stored is how far through a set you are in a given mode, and, for the modes that grade an answer, how many times each card has come back right and whether you have ever got it wrong. What is stored is counts. Not what you typed, not the card, not the question, not the answer — Learn compares your typed answer in your own browser and then forgets it. The same applies to a practice test you have started and not handed in: the answers you have typed are kept so you can come back to the paper, and they are the same answers the paper is graded from when you submit it.
It is yours alone. There is no ranking, no comparison with anybody else, and no view of it anywhere but your own screens — and nothing in the product reads it to decide what you are allowed to do. Deleting a set deletes its progress; deleting your account deletes all of it, by database cascade.
What we send to the AI provider is unchanged by this: your question, the passages, and the recent history. See section 4 for what the provider does with it.
3.7 Analytics, errors and logs
CourseLite's analytics are built in-house, on two Postgres tables. There is no PostHog, no Sentry, no Mixpanel, no Google Analytics, and no third-party analytics or advertising SDK of any kind.
We record:
- an event name, from a fixed list of 53 (
src/analytics/catalog.ts, 28 activation events and 25 telemetry events). A client cannot invent one; - the page you are on, as a route pattern —
/course-work/:id, never a real course id, and never a query string. Paths are stripped in the browser and stripped again on the server; - metadata from a fixed allowlist of 47 keys: counts, enums, booleans, positions, status codes, model names, plan names. Never a sentence you wrote;
- your user id, plan, and source, all derived on our server. If a browser sends any of these, we ignore what it sent;
- a random session id for logged-out visitors, described in section 10;
- errors: a redacted message, the route, a status code, and a request id.
What we deliberately do not collect. No canvas-rendering, font, audio, WebGL, battery, screen-geometry, browsing-history, installed-extension, cross-site or behavioural-biometric fingerprint. No advertising identifier. No device model. No user-agent string in our analytics tables.
IP addresses. We do not store your IP address. For rate limiting we derive a one-way hash of your address mixed with the current hour, so two hours of traffic cannot be linked to each other even by someone holding our database and our secret key. Cloudflare, who serve the site, see your IP address the way any network provider does, and Cloudflare's Turnstile bot check receives it for that one check. Neither is written to our database.
3.8 Anti-abuse
CourseLite's free tier attracts people who would like several of it. To stop that, we keep a small ledger of one-way hashes.
Up to five things get hashed, using a secret key that only our server code can read: your Clerk account, a verified email address, your Canvas login id, your Google account id, and a random installation id your browser generated. Raw values are never written down.
In practice the Google one is never used, because as section 3.5 explains we never learn your Google account id. The code that would hash it reads a column that is empty in every row. We describe it here rather than quietly leaving it out, because the mechanism exists and would start working the day that column were ever populated.
The hashes cannot be reversed into a person, are never sent to a browser, and identify nobody on their own. A refusal tells you a code, a reset date, and whether paying fixes it. It never tells you a risk score, a matched signal, or a network detail — those do not exist in the response.
A shared network address contributes to rate limiting and to nothing else. It can never, by itself, deny you anything.
3.9 Payments
If you subscribe, checkout happens on Stripe's own hosted page, and so does the billing portal. Card number, expiry, security code and billing address never touch CourseLite. There is no column for them in our database and no code that could receive them.
We store your Stripe customer id, your Stripe subscription id, your plan, Stripe's status for it, and when the period ends. We send Stripe your email address and your CourseLite user id so it can bill and identify the right account. If you cancel and tell us why, we store the reason.
Plan changes are written only by Stripe's webhook, whose signature we verify.
4. Where your information actually goes
This is the table to read if you read only one.
| Stays in your browser | Sent to CourseLite | Stored by CourseLite | Sent to the AI provider | Sent to Google | |
|---|---|---|---|---|---|
| The bytes of a course file | Yes | No | No | No | No |
| Text extracted from that file | — | Yes | Yes | Yes | No |
| An image nothing could parse | — | Yes, once | No | Yes, once | No |
| Course structure, assignment text | — | Yes | Yes | Yes | No |
| Your Canvas session, cookie, password, API token | Yes | No | No | No | No |
| Your Canvas user id | — | Yes | As a hash only | No | No |
| Your question in a saved chat (the workspace) | Yes, while the tab is open | Yes — last 10 per course | No | Yes | No |
| Your question in an unsaved chat (course page, assignment) | Yes, the history lives here | Yes, per request | No | Yes | No |
| A saved conversation | Yes | Yes — last 10 per course | No | Per request | No |
| An unsaved conversation | Yes | Per request only | No | Per request | No |
| Your Google OAuth token | Yes | No | No | No | Yes, to Google |
| A Google file's id and name | — | Yes | Yes | The name may be | Yes |
| Contents of a Google file you exported | — | Yes | Yes | Yes | No |
| Content CourseLite writes into a Doc | — | It is generated there | A record of the write | It is model output | Yes |
| Your card details | — | No | No | No | No |
| Your email | — | Yes | Yes | No | No |
| Your name, your instructor's name | — | Yes | Yes | Yes | Possibly, on a document |
| Your IP address | — | Seen, not stored | No | No | No |
| Event names and route patterns | — | Yes | Yes | No | No |
Other recipients: Clerk receives your sign-in details directly, because sign-in happens on Clerk's own components, and our server additionally asks Clerk to verify your session token and — for the two lookups in functions/lib/admin.ts and functions/api/courses/ingest.ts — to tell it your email address and role. Stripe receives your email and user id. Cloudflare serves every request and therefore sees your IP address and the URL, and its Turnstile bot check receives a challenge token. Crossref receives a DOI, and only a DOI, if you ask CourseLite to resolve one for a bibliography.
Those are all of them. Our server makes outbound requests to exactly five destinations — api.openai.com, api.stripe.com, challenges.cloudflare.com, api.crossref.org and Clerk's own API — and no user-supplied web address is ever fetched by our server.
Full list with links: docs/legal/subprocessors.md.
5. Why we use it
| Purpose | What it uses |
|---|---|
| Signing you in, and keeping your data yours | Clerk user id, email |
| Importing a course and making it searchable | Course material, embeddings |
| Answering your questions from your own material | Your question, retrieved passages |
| Drafting homework, decks, flashcards and practice tests | The assignment brief, your material, your name |
| Writing into a Google file you chose | Generated content, that file's id |
| Billing and subscription management | Stripe ids, plan, email |
| Enforcing plan limits | Usage counters, keyed to your account |
| Stopping one person from taking many free tiers | One-way hashes, rate-limit buckets |
| Understanding whether a feature works | Event names, route patterns, counts |
| Fixing what broke | Redacted error messages, routes, request ids |
| Keeping the service secure | The above, plus Cloudflare's own protections |
We do not use your information for advertising, we do not profile you for advertising, and we do not sell it. There is no advertising code anywhere in this product.
6. Legal bases
Where a law such as the GDPR requires us to name a legal basis, we rely on:
- Performance of a contract — everything needed to give you the product you signed up for: importing your course, answering from it, drafting, billing.
- Legitimate interests — keeping the service secure, preventing abuse of the free tier, and understanding whether features work. We have kept these narrow on purpose: hashes rather than identifiers, route patterns rather than URLs, and no fingerprinting.
- Consent — connecting your Google account, and, for anyone who joined one before sign-up opened, a waitlist entry. You can withdraw both.
This section is a description of our reasoning, not a legal conclusion. It has not been reviewed by a lawyer.
7. The AI provider, precisely
CourseLite sends your course material and your questions to OpenAI, at api.openai.com, unless we have configured a different provider endpoint. If that ever changes we will update this policy and this section.
What is sent: your question, up to roughly eight passages of your own course material (about 3,000 tokens), the assignment brief when you are drafting, your name and your instructor's name when a document needs them, and — once, at import time — an image that nothing else could read.
What is not sent: your email address, your Clerk user id, your Google token, your Canvas credentials, your payment details, or any identifier of you. Our requests carry an API key and the content, and nothing that names you.
What OpenAI says it does with it. We are quoting OpenAI's own published documentation, because this is their commitment and not ours to make:
"As of March 1, 2023, data sent to the OpenAI API is not used to train or improve OpenAI models (unless you explicitly opt in to share data with us)."
"By default, abuse monitoring logs are generated for all API feature usage and retained for up to 30 days, unless longer retention is required by law, or is reasonably necessary to protect our services or any third party from harm."
Source: OpenAI, Your data — https://developers.openai.com/api/docs/guides/your-data.
Be precise about what that means. Those are OpenAI's terms, which OpenAI can change. CourseLite uses OpenAI's standard API — requests go to api.openai.com under an ordinary API key — so it is OpenAI's published API terms that apply to them. There is no separate agreement, no zero-retention arrangement and no enterprise plan behind this. CourseLite does not send a zero-retention or no-training header on these requests, so we are not enforcing anything beyond what OpenAI's default API terms provide. We are telling you what the provider says, not promising it on their behalf. If you would rather your course material were not processed by a third-party model, CourseLite is not a product you can use, because that processing is the product.
The model has no tools. It returns text. It cannot call a function, change a database row, fetch a web address, or write to your Google Drive. That is a deliberate property of how CourseLite is built: a document in your course that contains instructions aimed at an AI reaches a model that has no way to act on them.
8. Google user data
CourseLite can read and write Google Docs, Slides and Sheets that you choose.
The scope
CourseLite requests exactly one Google scope:
https://www.googleapis.com/auth/drive.fileNot drive. Not drive.readonly. Not documents. Not presentations. Each of those would mean "everything you own". drive.file is per-file, and Google enforces it: CourseLite can see the files it created and the files you explicitly picked, and nothing else in your Drive. That is Google's enforcement, not a promise of ours.
An earlier version of CourseLite requested drive.readonly. It was removed on 1 September 2026 because broad access to somebody's whole Drive is too much to hold for a handful of course files.
The token
Your Google access token lives in the extension's service worker, or in a variable in one page of the website, for as long as that tab is open. It is never written to disk, never stored in our database, never sent to our API, and never sent to OpenAI. There is no refresh token and no client secret anywhere in CourseLite, and no server-side OAuth exchange: every Google operation is something you started, in front of you.
What we store about Google
The scopes Google reported you granted, and the id, name, type and link of each file. The text of a Doc or deck you export into a course is stored as a document, like any other course material.
We do not learn which Google account you used. drive.file does not carry an identity, we ask for no openid or userinfo.email scope, and our server refuses to take a Google account id or email from a request. So there is no "connected as ..." to show, and this policy will not claim one.
What we do with it
Only what you can see us doing: writing a draft into a document you chose, reading a file you picked so it can be part of your course, and showing you a link to a file an assignment points at.
What we never do with it
We do not transfer Google user data to third parties, except as needed to provide the features you can see, to investigate abuse, or to comply with law. We do not sell it. We do not use it for advertising, retargeting, or any profiling. We do not use it to determine anyone's credit-worthiness. No human at CourseLite reads your Google file contents, except with your explicit consent, for a security investigation, or where the law requires it.
The required disclosures
For the CourseLite Chrome extension, in the wording the Chrome Web Store requires:
The use of information received from Google APIs will adhere to the Chrome Web Store User Data Policy, including the Limited Use requirements.
For CourseLite on the web, and for the same data. drive.file is a Google Workspace scope, and the wording Google's current Workspace policy gives is:
The use of information received from Google Workspace scopes will adhere to the Google Workspace API User Data and Developer Policy, including the Limited Use requirements.
The older, more general formulation is also true of us and is kept because several Google surfaces still ask for it by name:
CourseLite's use and transfer of information received from Google APIs to any other app will adhere to the Google API Services User Data Policy, including the Limited Use requirements.
Checked against Google's published policies on 2026-09-03. Both policies say this affirmative statement must appear in the application or on a page the application links to; neither mandates one exact sentence, so the wording above is Google's own example text rather than a phrase we invented.
Google's review of this app
Google reviews apps that request access to user data before they are made generally available. CourseLite has not completed that review yet. While it is outstanding, Google access is available only to accounts we have added as test users, and Google may show you an "unverified app" warning when you connect. Nothing in this section changes when the review completes — the scope is drive.file either way — but you should know which side of it we are on.
CourseLite never deletes a Google file
If you press "start over", CourseLite detaches its reference to a document. The document stays in your Drive. Nothing in this product deletes a Google file, and nothing in it ever will. If you want a file gone, delete it in Google Drive.
Disconnecting
You can revoke CourseLite's access at any time from your Google Account, under Third-party apps & services. Revoking stops all future access immediately. It does not remove the file text we already stored in your course — deleting the course does that.
9. The Chrome extension
The extension is where course material is read, so it is worth being exact about what it does.
Where it runs. The extension's content script is allowed to load on any site's root page and on paths shaped like Canvas's — /courses, /dashboard, /calendar, /grades and a few others. This is broad, and the reason is structural: Canvas is self-hosted, so every university runs it on a different domain. There is no list of hostnames to match against, and there is no narrower pattern that would still work at your school.
What it does on a page that is not Canvas. Nothing visible and nothing sent. The script checks for Canvas's own structural markers, and if they are absent it stops without showing a panel. It does not read the page's content, scrape it, or report that you visited it.
What it reads on a page that is Canvas. The course, when you ask it to. Importing is something you start.
What it never touches. Your Canvas password, your Canvas session cookie, your Canvas API token, or a file access token. None of these leave your browser, and none has a place to go: there is no code in CourseLite that receives one.
Permissions, and what each is for.
| Permission | Why |
|---|---|
scripting, activeTab | Show the CourseLite panel on the Canvas page you are on, on the tab whose toolbar button you clicked |
storage | Hold a file you exported yourself, briefly, before it is read — and cache your CourseLite sign-in session, which the sign-in library requires |
cookies | Read one cookie, on courselite.org only: the sign-in cookie our own website already set, so that signing in on the website signs you in in the extension too, and signing out signs you out. It is read by the sign-in library (@clerk/chrome-extension), never by our own code, and never against the site the panel is shown on — the browser enforces that, because the extension holds a host permission for courselite.org and for no Canvas domain |
identity | Ask Google for the drive.file permission, when you choose to connect |
Host access to courselite.org | Talk to our own API |
| Host access to Clerk's sign-in host | Sign you in |
| Host access to Google's API hosts | Read and write the files you picked |
The cookies permission is the one that sounds worse than it is, so it gets the longest row. It cannot read a cookie belonging to your university, your Canvas, your bank, or any other site: a cookie read needs a host permission for that URL, and the only one this extension holds is for our own domain.
The extension has no host permission for any Canvas domain, because it does not need one: it runs inside the page you are already looking at.
10. Browser storage and cookies
Two different statements, and only one of them is "no cookies".
- Code we wrote sets no cookie, and our API reads no cookie. Not one, on either side. It is structural rather than accidental: CourseLite's API authenticates with a bearer token our own JavaScript attaches to each request, so there is nothing for a browser to send automatically.
- A sign-in cookie is nevertheless set on courselite.org, by Clerk's sign-in library running in the page. Keeping you signed in is what it is for, it is set on our domain, and it is strictly necessary: without it you would sign in again on every visit. We do not read it, our server does not receive it, and nothing about it is analytics or advertising.
Both are true, and the first one on its own would be a misleading way to say it. There is a full determination — what is set, by whom, what it is for, and why no consent banner is proposed — in cookies-and-storage.md.
We do use browser storage, which stays on your device and is never readable by another website.
| Where | What | How long |
|---|---|---|
localStorage | A random session id for analytics, created with crypto.randomUUID() | Until you clear site data |
localStorage | The chat mode you last picked, per course | Until you clear site data |
localStorage | That you dismissed the onboarding checklist | Until you clear site data |
sessionStorage | Your current chat conversation, per course. Saved workspace chats are also held on our servers — see section 3.6 | Until you close the tab |
sessionStorage | Whether a panel is open, whether the extension was detected, dismissed banners, the previous page you were on | Until you close the tab |
chrome.storage.local (extension) | A file you exported yourself, held before it is read | Until it is read |
indexedDB (extension) | A random installation id | Until you remove the extension or clear its data |
The analytics session id is random. It is not derived from your machine. It is not a hash of your device, your fonts, your screen or your browser. If you clear your site data you become a new visitor to us, and that is the intended outcome rather than a hole to plug. Once you are signed in, events are attributed to your account and this id is not sent.
Cookies our providers set. Clerk keeps you signed in with a session cookie on courselite.org and a client cookie on its own sign-in domain. Cloudflare may set its own for security and bot protection, including for the Turnstile challenge that can appear during sign-up. Stripe sets its own on Stripe's checkout pages. Google sets its own when you sign in to Google or use the file picker. Those are governed by each company's policy, linked in subprocessors.md, and by ours only where they are set on our domain.
The Chrome extension reads one cookie, on courselite.org and nowhere else, so that being signed in on the website means being signed in in the extension. Section 9 says exactly what that permission can and cannot reach.
We have not built a cookie consent banner. Every cookie and storage entry described above is either strictly necessary for a function you asked for, or a preference stored on your own device; none of it is advertising, none is cross-site tracking, and there is no third-party analytics or advertising SDK anywhere in this product. Whether that conclusion holds where you live is a question of local law rather than of how we built the product, and the full reasoning — including the one step in it a regulator would most likely push on — is set out in cookies-and-storage.md.
11. Who else sees your information
Nobody, other than the service providers we need to run the product. The full list, with what each one gets and why, is in docs/legal/subprocessors.md.
We do not sell your personal information. We do not share it for cross-context behavioural advertising. We have no advertising partners, no data brokers, and no advertising code.
We would disclose information if we were legally required to — a valid court order, a subpoena, a law we must obey — or where it is necessary to protect someone from harm. If CourseLite were acquired or merged, your information would move with it, and we would tell you before that happened.
12. How long we keep things
Course material, notebooks, drafts and generated work have no time limit. They stay until you delete the course, or delete your account. That is deliberate: a course you imported in September should still be there in December.
The following periods are defined in our code:
| Data | Period |
|---|---|
| Raw page-view records | 14 days |
| Other analytics events | 60 days |
| Error records, once somebody has marked them resolved | 90 days from when they happened |
| Error records nobody has resolved | Kept. An old bug nobody has looked at is not stale, and deleting it would only hide it |
| Purchase and subscription events | Kept — they are the record of money changing hands, not analytics |
| A daily rollup of analytics — day, event, source and route pattern, with no ids | Kept |
| Anti-abuse rate-limit buckets | They expire on their own |
| Anti-abuse free-tier claim records | 400 days, then they expire (CLAIM_RETENTION_DAYS) |
| Saved chats | No time limit, but only the last 10 per course are kept. Starting an eleventh conversation in a course deletes the one you have not used for longest, immediately. Unlike the periods above, this one is enforced on every save rather than by a cleanup job, so it is already happening |
| Study progress for a flashcard set | No time limit. It is where you got to in a set, and it stays until you delete the set, delete the course, or delete your account. It holds counts and nothing you typed |
| Answers to a practice test you have not handed in | No time limit while the attempt is open. They are kept so you can come back to the paper on another device, and they are the same answers the paper is graded from when you submit it |
Two things are worth reading twice. An error record carries a redacted message, the route and a request id — a token or an email address is replaced before the line is written — and its link to you is removed when you delete your account even though the record itself stays. And a page view is folded into the day's totals before its own row is deleted, so what survives 14 days is a count, with no id of any kind in it.
A third: study progress is counts — how many cards you have been through, how many times a card came back right, and whether you ever got it wrong. There is no record of what you answered, in either table, and no card text in them at all.
We have to be honest about a gap. These periods are implemented in functions/lib/lifecycle.ts, but they are not currently on an automatic schedule: there is no cron trigger in this deployment, and the cleanup runs only when an operator calls it. Until that is wired up, treat those numbers as our policy and our intent rather than as something already happening on a timer. When it is running, this section will say so without a caveat. If you want data deleted before then, ask us and we will do it.
13. Deleting your account, and what really happens
How to ask
Settings → Delete your account. The button is in the product, it calls the same endpoint an email would, and it is described on a page you can read without signing in: courselite.org/legal/delete-account.
If you would rather not do it yourself, email support@courselite.org and we will. It is not a slower route — the same operation runs either way.
What deletion removes
One statement removes your users row, and the database removes everything attached to it. 40 tables are covered, and each one is asserted empty afterwards by a test that runs against a real database (tests/release/privacy/deletion-test.mjs): your courses and everything under them, your documents, the text passages and their embeddings, notebooks, flashcard decks and cards, practice tests, homework drafts and answers, assignment plans, revisions, agent workspaces, assignment links, your Google file references and your Google connection, your Google file analyses and the record of every write CourseLite made into a Google file, citations, instructor names, your profile, settings, onboarding state, quota counters and reservations, your usage ledger, your billing account row, your cancellation feedback, your import jobs, your analytics events, your file records, and — new on 2026-09-04 — your saved chats and every message in them, and — new on 2026-09-09 — your study progress for every set, the per-card record of how you have answered, and your notification preferences. One of the tables, device_accounts, is deleted by name a moment before the cascade rather than by it.
Your course material and drafted work are removed, not hidden. If a table that holds something of yours is ever added without the link that makes it cascade, that test fails — which is the point of writing the list as a test rather than as a paragraph.
What deletion does not remove
We would rather you read this here than discover it later.
- Your Clerk account survives. Deleting your CourseLite data does not delete your login at Clerk, so your email address and sign-in method remain there. Ask us and we will delete it at Clerk too, or delete it yourself from your account settings.
- Your subscription is cancelled as part of the deletion, not after it. If you have an active subscription, we tell Stripe to cancel it first, and only then remove your data. The cancellation is scheduled for the end of the period you have already paid for, so you are not charged again — but the account goes today, so the rest of that period is time you cannot use, and it is not refunded automatically. If a payment of yours has already failed and Stripe is still trying to collect, we cancel outright instead, so that a retry cannot charge you after you asked to be forgotten. If Stripe cannot be reached, the deletion stops and nothing is deleted, and we tell you why, rather than destroying the record of a subscription that is still billing you. Stripe keeps its own record of the payments you made, under Stripe's policy and the law that requires them to.
- Three records outlive the account, and none of them names you. They are:
ai_usage— how many tokens each request used, which model, and when. No content of any kind: not your question, not the answer, not the course.abuse_decisions— that a decision was taken about an account: a reason code, a risk band, and the category names of the signals involved ("canvas_identity", "device_key", "velocity"). Never a hash, never an email, never a network address.turnstile_tokens— the hash of a one-time bot-check token, so the same token cannot be replayed. It expires on its own.
Each row survives; your user id is removed from it. We keep the rows because they answer questions that outlive an account — what this service costs to run, and whether an anti-abuse rule is behaving — and neither question needs to know who you were.
This is a recent change and the honest version of it is worth stating. Until migration 0037, the first two kept your Clerk user id verbatim, because they have no database link to your account and the deletion never reached them. That was not a decision anybody made; it was a gap. It was found by asking the database which columns hold a user id and which of those the deletion actually reaches, and it is now checked automatically on every run of tools/deletion-completeness-test.mjs — so a table added later that would keep your id fails a test instead of going unnoticed.
- Some anti-abuse hashes survive, on purpose: records that say "this Canvas login, this verified email, this installation has already had a free CourseLite". Without them, "delete the account and sign up again" would be a one-click way to reset a free allowance, which is the exact loop the system exists to close. What survives is a one-way hash and a date, with the user id removed — that removal happens before the cascade, so it cannot be left half-done — and it expires 400 days after it was made. It cannot be reversed, and it is never sent to a browser. If you believe one is wrong, email us and say so.
- Error records survive, but stop naming you. An error logged while you were signed in keeps its redacted message, route and status; its user id is set to empty. The bug stays visible to us; you do not.
- Google files stay in your Drive. Everything CourseLite created for you is yours and stays yours. Delete it in Google Drive if you want it gone.
- Waitlist entries are separate. They are not linked to an account and are not removed with one. Email us.
- Analytics events from before you signed in carry a random session id and no user id, so we cannot find them to delete them. They expire on the schedule in section 12.
- Backups. Our database provider, Neon, keeps point-in-time backups on a schedule it sets and we do not control. Data deleted from the live database can persist in one of those backups until that window passes, and is gone from there when it does. We would rather tell you that plainly than quote you a window we are not the ones who set.
Your other rights
Depending on where you live, you may have the right to access a copy of your information, correct it, delete it, restrict or object to how we use it, take it elsewhere in a portable form, or complain to a data protection authority.
Email support@courselite.org. We will respond within 30 days and will not charge you or treat you differently for asking.
We do not currently have a self-service export button. Ask and we will produce your data.
14. Security, and what it does not cover
What is actually in place:
- HTTPS everywhere, with HSTS.
- Sign-in through Clerk; every request authenticated with a verified token. Nothing in CourseLite lets a request name a user — identity comes from the token or the request fails.
- Every query is scoped to the account that made it. Something you do not own returns "not found".
- Secrets — the database URL, the API keys, the anti-abuse key — exist only in server-side configuration, never in anything sent to your browser.
- No card data, ever. No raw IP addresses. No raw anti-abuse identifiers.
nosniff,strict-origin-when-cross-originreferrer policy, frame denial, cross-origin opener isolation, and a permissions policy that switches off camera, microphone, geolocation and the rest.- A Content-Security-Policy. It is currently served in report-only mode, which means a browser reports a violation rather than blocking it. That is a deliberate staging step, not an oversight — enforcing a wrong policy removes sign-in for everybody at once — and it is a real reduction in protection until it is switched on. We would rather say so than let "we have a CSP" do work it is not doing yet.
- Regular automated security tests, including an adversarial suite.
What this does not mean. No service is perfectly secure, and we are not going to imply otherwise. CourseLite has not been penetration-tested by a third party, holds no security certification, and is not certified under SOC 2, ISO 27001, or any similar scheme. This policy makes no claim that CourseLite is compliant with FERPA, COPPA, HIPAA, the GDPR, the CCPA, or any other specific law. If your school requires a vendor to hold one of those, CourseLite does not meet that requirement today.
To report a vulnerability, see SECURITY.md.
15. Where your information is processed
CourseLite runs on Cloudflare's global network, which serves requests from wherever you are. Our database is hosted by Neon in the United States (AWS us-west-2, Oregon). Clerk, Stripe, OpenAI and Google each operate their own infrastructure across multiple countries.
If you use CourseLite from outside the United States, your information will be transferred to and processed in the United States and possibly elsewhere. Privacy laws there may differ from the ones where you live.
CourseLite is offered in the United States. We do not offer it in the European Economic Area or the United Kingdom.
That is not a formality, and here is the honest reason for it: no international transfer mechanism has been confirmed with any of our providers, and no data processing agreement has been signed with any of them. Serving people in the EEA or the UK would require both, per provider. We would rather not offer the service there than name a safeguard that does not exist.
16. Age
CourseLite is built for college students. It is not directed to children and we do not market it to them.
You must be at least 13 years old to use CourseLite. By creating an account you are representing that you are. We do not ask for your date of birth, we do not want it, and we do not verify your age.
Being accurate about this: sign-up is Clerk's own form and it does not yet ask you to tick anything about your age. So today the 13+ minimum is a term of this policy and of the Terms rather than a question on a screen. Adding that question is on the release checklist, and this paragraph will change when it lands — in that direction, not the other one.
We do not knowingly collect personal information from anyone under 13. If we learn that an account belongs to someone under 13, we will close it and delete the information we hold. If you believe a child under 13 has an account with us, email support@courselite.org and we will act on it.
If you live in the European Economic Area or the United Kingdom, CourseLite is not offered where you are — see section 15. One of the reasons is this one: under GDPR Article 8 a person between 13 and 16 can need a parent or guardian's consent before using a service like this, with the threshold differing by country, and CourseLite has no mechanism for collecting that consent. We have not built one on a guess, and we do not offer the service where it would be needed.
17. Emails we send you
CourseLite sends transactional email only: things like sign-in and account messages from Clerk, and receipts and billing notices from Stripe. These are part of running your account and you cannot unsubscribe from them while you have one.
We do not send marketing email, and we do not sell or rent your address to anyone who would. If that changes, we will ask you before adding you to anything, we will put an unsubscribe link in every message, and we will update this section first.
If you joined the waitlist before sign-up opened, we may email you once to say so. Ask us to remove you and we will.
Settings → Notifications does not contradict this. Since 2026-09-09 you can say which reminders you would want — an assignment due soon, an overdue one, a course that finished importing. Nothing sends them. There is no email sender, no push, no scheduled job and no third-party notification service in CourseLite, the settings screen says so above the switches, and your answers are stored only so that whatever gets built later starts from what you actually chose. When something does send, this section changes before the first one goes out.
18. Changes to this policy
If we change how CourseLite handles your information, we will update this page and change the "last updated" date at the top.
For a change that materially affects you — a new category of data, a new provider receiving your material, a new purpose — we will tell you before it takes effect, by email or in the product, and not only by editing this page.
19. Contact
| Privacy questions and requests | support@courselite.org |
| Account questions, legal notices, everything else | support@courselite.org |
| Security reports | security@courselite.org — see SECURITY.md |
| Data protection officer / EU representative | None appointed. We would rather say that than publish a role nobody holds |
CourseLite is an online service with no public office, so there is no postal address to write to. Email reaches a person and is the route for everything above.
CourseLite is an independent product. It is not affiliated with, endorsed by, sponsored by, or connected to Instructure, Canvas, Blackboard, Moodle, Google, OpenAI, Clerk, Stripe, Cloudflare, or any university, college or school. The full statement is in non-affiliation.md.