Jalees

Cookie Policy

Effective date:

1. What this policy covers

This policy explains the cookies and similar browser-storage technologies Jalees uses on the marketing site (jalees.io) and in the application (app.jalees.io). It supplements our Privacy Policy.

2. Categories of cookies

We group cookies into three categories:

Essential
Required to deliver the Service. They keep you signed in, protect signup and login forms from automated abuse, and remember your cookie choices. These cannot be turned off through the cookie banner without breaking the Service.
Analytics
Help us understand which features are used and where the Service is slow or broken. Off by default; loaded only after you opt in.
Marketing
Reserved for any future personalised outreach. Currently unused; would be off by default and require opt-in if ever introduced.

3. Cookies we set

The table below lists the cookies that Jalees and its processors may set in your browser. Provider-set cookies are listed with their typical name; exact names can vary slightly between versions of the underlying SDK.

NamePurposeCategoryDurationParty
jalees_refreshHttpOnly, SameSite=Lax session refresh token. Required to keep you signed in.EssentialUp to 30 daysFirst-party
jalees_oauth_stateHttpOnly anti-CSRF state for "Sign in with Google". Set when you start the OAuth flow and cleared when you return.Essential5 minutesFirst-party
jalees_consent_v1Points to your consent preference on jalees.io or app.jalees.io using a random identifier. The preference is retrieved only from those approved origins; this cookie does not contain account identifiers or track visits.Essential (preference)Up to 365 daysFirst-party
__Host-jalees_consent_blockedPrevents an older opt-in from being restored if a consent handoff cannot be verified or saved. It is limited to the current host and does not track visits.Essential (preference)Up to 365 daysFirst-party
PARAGLIDE_LOCALERemembers which UI language (English, Arabic or Dutch) you chose, so the app renders in that language on your next visit. Set when you change the language in the app, and once when you sign in or sign up from the Arabic or Dutch pages of our website, which pass your language to the app.Essential (preference)Up to 400 daysFirst-party
cf_chl_*, __cf_bmCloudflare cookies. cf_chl_* holds Turnstile challenge state and is set when you complete a challenge on signup or login. __cf_bm is Cloudflare's bot-management cookie and is set on requests through their network generally, not only when you submit a form. Both keep automated abuse off the service.EssentialUp to 30 minutesThird-party (Cloudflare)
ph_jalees (or ph_*)PostHog anonymous distinct identifier. Set only after you opt in to analytics; used to stitch your visits into a single funnel.AnalyticsUp to 365 daysFirst-party
posthog-session-idPostHog session identifier. Set only after opt-in; expires after 30 minutes of inactivity.Analytics30 minutes (idle)First-party

4. Browser storage we use

Besides cookies, the app keeps things in your browser's own storage — localStorage, sessionStorage, IndexedDB and Cache Storage. Like cookies, these stay on your device and can be cleared from your browser's site-data controls. Almost all of it exists so the app works the way you left it; none of it is used for advertising. Keys shown with<…> have one entry per book, video, note or pane.

Your cookie choices

jalees:consent:v1
Your cookie choices and when you made them, so the banner is not shown again on every page. The version of the optional purposes and providers your choice covers. When these change, optional scripts stay off until you make a new choice.
jalees:consent:handoff:v2
The consent choice published by this origin, with its original policy version, account and consent-record identifiers, and a random handoff identifier. It is stored only in this origin's browser storage so the approved other origin can retrieve it through the preference exchange. It remains until replaced, reset or cleared with your browser's site data.

Record of your consent choices

The entry above is not the only copy. When you sign in, or answer the banner while signed in, we also keep that answer on your account, so that we can demonstrate the consent was given and so that you are not asked again on every device. It is kept even if you clear your browser storage, and it is deleted when you delete your account. Section 2.5 of thePrivacy Policy sets out exactly what each entry holds. If you are not signed in, your choice stays on this device only.

Forms on our website

jalees:form-draft
Session storage, this tab only. If turning analytics off refreshes the page, what you had typed on our contact form (organisation, name, email, role, size and message), sign-up form (name and email) or sign-in form (email) is saved temporarily in this tab so it can be restored once within 60 seconds. The saved copy is deleted the next time a page on our website loads in this tab, whether or not it is restored. Passwords and security tokens are never kept.

Signing in

jalees.link_token
A short-lived token used while linking a sign-in method. Kept in sessionStorage, so it is discarded when you close the tab — not in localStorage.
jalees.signout.purgePending
Set while signing out removes your downloaded books, unsent changes and other account data from this device (all but the account id that jalees-offline keeps), and removed once that has finished. If it is still there the next time the app starts, the app finishes the job.
jalees.signout.logoutOwed
Your account ID and an expiry time, set when you sign out without a connection. It is kept until the sign-out reaches our server on a later start, or until the expiry passes.
jalees:auth-recovery-email
When you choose to sign in after a signup email conflict, the email address and a ten-minute expiry are kept in sessionStorage on that origin for the current tab. The sign-in form consumes this entry once; expired entries are discarded when read, and closing the tab discards it. No password is stored and the email is not added to the URL.
jalees.auth.refreshTtlSeconds
How long, in seconds, our server keeps a sign-in session valid. It is used to set the expiry above and holds no personal data.

Buying credit

jalees:topup-resume
When you hit your usage limit and buy credit, the message or read-aloud you were trying, and the page you were on, so it can be finished for you when the payment brings you back. Kept in sessionStorage, so it is discarded when you close the tab, and deleted as soon as it has run or after 30 minutes.

Answers in progress

jalees:pending-turn
The reply the server is currently writing for you, so a reload, a network switch or a backgrounded app can pick up that same answer where it stopped instead of losing it. Kept in sessionStorage, so it is discarded when you close the tab, and deleted as soon as the reply finishes or is stopped.
jalees:unsent-send
A message you sent while the chat was still busy with another reply, so a reload before it went out can put it back in the message box instead of losing it. It is never sent on its own. Kept in sessionStorage, so it is discarded when you close the tab, and deleted as soon as the message goes out or fails.

Updating the app

jalees:stale-build-reload:<build>
Set when this tab was opened before we released a new version of the app and had to reload to get it. It holds the time of that reload, so the tab reloads at most once every five minutes and never in a loop, and no personal data. Kept in sessionStorage, so it is discarded when you close the tab.

Things you have written

jalees.notes.draft.<note>
Unsaved note drafts, one entry per note, kept so a reload does not lose them. This is your own writing rather than a setting: clearing site data or signing out discards it.
jalees.ink.acked.<book>
Pen strokes and erases on a book that were saved to your account just before the connection dropped, kept until the app has read the book's ink again, so they still show offline. Clearing site data or signing out discards them.
jalees.ink.closing.<book>
Pen strokes and erases on a book drawn just before the tab closed, kept until the app adds them to your unsent changes the next time it opens. Clearing site data or signing out discards them.
jalees.siglum.ctan-proxy-version
The LaTeX package-cache generation, used to discard incompatible cached compiler packages after an upgrade.
siglum-ctan-cache
LaTeX packages downloaded for a project, cached in IndexedDB so later previews do not download them again.

Where you had got to

jalees.reader.state.<book>
Your position in a book, one entry per book.
jalees.video.position.<video>
Your position in a video, one entry per video.
jalees.video.caption.<video>
The subtitle language you picked for each video, kept on this device, one entry per video.
jalees.audio.position.<recording>
Your position in an audio recording, one entry per recording.
jalees.study.moments.reveal
On this device, we remember how many steps of a worked derivation you revealed in a study lesson, so we can show them again when you return. The record contains identifiers, the number of revealed steps and when the record was saved, but no lesson text or answers. We store at most 100 entries. Entries expire after 30 days and are removed the next time a reveal record is saved. The record is also removed when you sign out or switch accounts.
jalees.study.moments.host
On this device, we remember which study experience you chose for a study plan, the new one or the current one, so a lesson you have not started opens in it. The record contains your account identifier, the plan identifier, your choice and when it was saved, but no lesson text or answers. We store at most 100 entries. A lesson you already started opens as you studied it, whatever this record says. The record is removed when you sign out or switch accounts.
jalees.position.sync.<kind>.<id>
For each book, video or recording: which saved position this browser last synced, and whether you have moved on since. This is how a position you reached offline is checked against the server, instead of overwriting a newer one from another device.
jalees.position.sync.moved.<kind>.<id>
For each book, video or recording: the last place you moved to in this browser, and when. Kept in localStorage so that signing out can ask before deleting a position that has not reached the server; signing out then removes it.
jalees.position.sync.settled.<kind>.<id>
For each book, video or recording: the last of those moves the server is known to have received. Kept in localStorage and removed when you sign out.
jalees.position.sync.sent.<kind>.<id>
For each book, video or recording: the position a tab sent as it closed, so that signing out can check it arrived. Kept in localStorage and removed when you sign out.
jalees.device.id
A random identifier for this browser. It is sent with your saved reading and playback positions, so that another of your devices can tell where you left off and on which one. It is not derived from anything about the device.
jalees.subjects.recent
Recently opened subjects.
jalees.workspace.last
The layout you last had open.
jalees.workspace.split.<pane>
How you sized a split pane.

How the app looks and behaves for you

jalees.sidebar
Sidebar expanded or collapsed.
jalees.sidebar.width
Sidebar width.
jalees.reader.fontScale
Reader text size.
jalees.reader.toc
Reader table of contents expanded or collapsed.
jalees.ink.finger
Whether your finger draws or scrolls in Draw mode, set once a pen has drawn on this device.
jalees.editor.fontScale
Note and source editor text size.
jalees.editor.wrap
Source editor word wrap on or off.
jalees.app.fontScale
App text size.
jalees.theme
Light, dark, or following your device, as you chose under Account → Appearance. Kept when you sign out.
jalees.cards.fontScale
Cards text size.
jalees.chat.wide
Chat panel wide or narrow.
jalees.chat.width
Chat panel width.
jalees:chat:model
Which assistant model you picked.
jalees:chat:effort
Which response effort you picked.
jalees:subject-items:sort
Whether subject item lists are sorted by latest update, on this device.
jalees.chatBubble.placement
Where you dragged the chat bubble.
jalees:video-sync-layout
Video/transcript layout.
jalees:video-pip-placement
Where you dragged the picture-in-picture window.
jalees:video-transcript-overlay
Whether the transcript is drawn over videos.
jalees:media-transcript-list
Whether video and audio panes show their transcript list.
jalees:skip-silence
Whether videos and audio skip their silent pauses.
jalees:audio-speed
The playback speed you chose for audio recordings and voice notes.
jalees:study:word-highlight:v1
Whether words are highlighted during a study lesson.
jalees.calculator.open
Calculator open or closed.
jalees.calculator.placement
Where you dragged the calculator.
jalees.calculator.size
Calculator size.
jalees.calculator.dock
Whether the calculator sits at the top or the bottom of a small screen.
jalees.calculator.angle
Degrees or radians.
jalees.calculator.memory
The value in calculator memory.
jalees.calendarPanel.open
Calendar panel open or closed.
jalees.calendarPanel.placement
Where you dragged the calendar panel.
jalees.calendarPanel.size
Calendar panel size.
jalees.calendarPanel.deadlinesOnly
Calendar filter: deadlines only.
jalees.calendarPanel.hideDeclined
Calendar filter: hide declined.
jalees.calendarPanel.view
Calendar view: month, week or day.
jalees.tips.seen
Which tips you have already been shown.
PARAGLIDE_LOCALE
In the iOS and Android app only: the language you chose. The app also keeps it as the cookie in section 3, but on iOS that cookie is dropped, so the app keeps the language here until you clear the app's data. On the website this entry is not used.

Offline copies you asked for

jalees-offline
An IndexedDB database holding content you downloaded for offline use. Each download is marked with the id of the account it was made for, so it is listed and opened only for that account. A different account signing in here removes it, along with any download that finishes for another account while that account is signed in. It also keeps the id of the last account signed in on this device, including after you sign out, solely so the next sign-in here can remove that account's leftover data.
jalees-downloads
On the website, Cache Storage: the files behind a download you started. The iOS and Android app keep a new download's file in jalees-blocks instead.
jalees-api:<account>
Recent API responses, so downloaded content opens without a network, and so your library shows what you saw last while it reloads. One per account signed in on this device. On the website they are in Cache Storage; in the iOS and Android app they are in the jalees-offline database.
jalees-lessons:<account>
Cache Storage: the audio and text of study lessons you downloaded, so they play without a network. One per account; removed when you sign out.
jalees-blocks
Parts of large files, fetched in blocks. On the website they are in Cache Storage. In the iOS and Android app they are in the jalees-offline database, together with the file of each book you downloaded, which stays until you remove the book or sign out.
jalees-share-target
On the website, Cache Storage: files you share to the installed Jalees app from another app, held only until its upload page opens, which removes them. Sharing again replaces them.
jalees-shell-<build>
Cache Storage: the application itself, so it loads offline. One entry per released build; older ones are removed.

Analytics, only if you accept it

PostHog keys
If you accept analytics, PostHog keeps its own identifiers in localStorage, including its record of your opt-in. Removed when you withdraw consent.
jalees:reload-context
If you accept analytics, written as a tab reloads or closes: whether a video was playing or full screen, whether a reload shortcut was pressed, and which part of the app asked for the reload, so the next page can report why the app reloaded. No page content and no personal data. Kept in sessionStorage, deleted when the next page reads it, when you withdraw consent, or when you close the tab.

Your sign-in credential is not in any of these. On the web it is an HttpOnly cookie your browser sends but scripts cannot read; in the mobile apps it is held in the device keystore (iOS Keychain, Android EncryptedSharedPreferences).

5. How to manage cookies

You can change your cookie preferences at any time by opening the cookie settings panel from the link in our footer ("Cookie settings"). You can also block or delete cookies in your browser's settings, but doing so for essential cookies will prevent you from signing in.

Analytics is provided byPostHog(PostHog Inc.), processed in the EU region at eu.i.posthog.com. We honour theDo Not Track browser signal: if your browser sends DNT, PostHog will not be initialised.

On our website (jalees.io) and in the app (app.jalees.io), the analytics choice also coversCloudflare Web Analytics(Cloudflare, Inc.; provider documentation): cookieless, aggregate page-view and performance measurement by Cloudflare. Cloudflare Web Analytics does not use cookies or browser local storage to collect analytics. It is loaded only if you accept analytics, and not at all if your browser sends Do Not Track. When you turn analytics off, the page reloads immediately to stop further measurement.

6. Changes to this policy

We may update this policy to reflect changes to our cookie usage. When we do, we will update the effective date above. Material changes that affect how we use non-essential cookies will be re-surfaced through the cookie banner so you can review and re-confirm your choices.