Cookies on Notom

Pick which categories of cookies you're OK with.

Read our cookies policy and the privacy policy.

Loading…

Changelog

Listed below are the key changes in each update release of Notom, the newest release is listed first.

v0.44.0 - 2026-10-20

Changed

  • The note editor's toolbar buttons are bigger and easier to tap, and the editor box has the same corners and focus outline as every other text box.

Security

  • A script slipped into part of a page that loads in place, without a full reload, no longer runs unless it was sent with that page's own security key. Scripts in a full page load were already held to this.

v0.43.0 - 2026-10-20

Changed

  • The focus page is called One again, in the app's top nav and across the website, as it was before 0.42.0. "AI assistants" stays, and so does Done keeping you on the page.

Fixed

  • /health now reports the running release (e.g. v0.42.0) instead of "unknown", so a deploy can be confirmed from it.

v0.42.0 - 2026-10-20

Added

  • AI assistant sign-in honours prompt=consent, and prompt=none with max_age or id_token_hint. The ID token's auth_time is the real sign-in time, and a self-registered assistant can read or delete its own registration.
  • Your notes list, search, archive, Actions and Do now include your personal graph alongside the space's, and never another member's.

Changed

  • Light and dark now come from the shared library rather than this app's own copy of it. Notom's version was the best of the five in the estate - the only one that respected a visitor who declined functional cookies, survived a page swap, and worked under the strict content-security policy - so the library took all three, and this is the same behaviour with one copy of it instead of five. The theme menu on the marketing pages and the signed-out bar now closes when you pick something and puts you back on the button, rather than leaving you at the top of the page.
  • The cookie banner now says what Notom actually stores: sign-in and consent cookies, your light/dark choice under Preferences, how PostHog measurement works before and after you choose, and what the Google Ads tag does when it's switched on. Nobody who has already chosen is asked again.
  • Staging and other non-production instances now tell search engines not to index them (X-Robots-Tag: noindex). Production is unchanged.
  • The first start after this release runs twad migrations that move its remaining date and time columns (invites, events, contact-form enquiries, saved values, entitlements and others) to time-zone-aware timestamps, reading stored values as UTC. The events table's indexes are rebuilt, so that first boot can take longer where there are a lot of events. Startup now also stops with an error naming any index left INVALID by an interrupted concurrent build, rather than carrying on without it.
  • The cookie banner and its dialogs now render at the top of the page body instead of inside . Browsers closed at the banner, so the canonical link, robots meta and Open Graph tags after it landed in the body, where search engines ignore them. The dialogs' titles are no longer h2 headings either, so every page's heading outline starts with its own h1.
  • On phones the cookie banner is now a slim edge-to-edge bar (about 98px tall, down from a 173-210px card) with Customise, Reject all and Accept all on one row, so it no longer covers the bottom third of the first screen. Buttons are 44px touch targets on phones and touch screens, and Reject all and Accept all look identical. In the preferences dialog the category list scrolls between a fixed title and a pinned footer, so Save and Back are always on screen.
  • Daily active users are now counted by London's day rather than New York's, so the daily figure rolls over at UK midnight. The day this deploys counts a few hours more or less than a real day. Plan limits are lifetime counts and don't move.
  • Pages load slightly lighter: the stylesheet and script are now minified, about a third smaller before compression and a few KB less over the wire. Nothing looks or behaves differently.
  • The app's client scripts (toasts, modals, the rich-text editor and the rest of tamlib's page scripts) now ship from the tamlib version the app pins rather than whatever was checked out when it was built. The editor loads as its own cached file, which cuts the app's main script from 234 KB to 57 KB.
  • Notom runs on htmx 4 (was 2). Navigation, Back and Forward, every form, confirm, toast and live list behave as before, checked at desk and on a phone. A few things work that didn't: completing, reopening, cancelling or deleting an action, saving preferences and adding, saving or deleting a category now say so with a toast; hitting a plan limit from an in-page action takes you to the plan page rather than pasting it into the list; and the Light, Dark and Auto theme options can be reached from the keyboard.
  • Pages draw sooner: the note editor now loads alongside the page rather than holding it up.
  • The sign-in page's cookie line says you choose whether we use analytics or advertising cookies, instead of claiming they're only used with consent - outside the UK, EU and Canada they're on until you switch them off.
  • The privacy policy says which cookies are on before you choose: in the UK, the EU/EEA, Switzerland and Quebec none until you agree, elsewhere on until you turn them off. It used to say they were only ever set with consent.
  • Confirmations ("Action completed", "Action added") show as a light tinted notice with an icon rather than a solid coloured bar, and are announced to screen readers.
  • The Actions page's tabs (Open, Overdue, Today, Week, All, Completed, Cancelled) now switch in place, with no page load: every tab's list arrives with the page. They're a proper tab list - arrow keys, Home and End move between them - and the tab you picked stays picked when the list refreshes itself. A ?filter= link still opens on its tab, and completing, cancelling or deleting from a tab brings you back to it. Switching tabs no longer changes the address, so a reload opens on the tab in the address.
  • The 'Install Notom' offer on a fresh notes page now gives iPhone users the Share, then Add to Home Screen steps, has a Not now that sticks for 30 days, and stays hidden once Notom is installed.
  • The selected tab on Actions now carries a coloured line along its top edge, so it's easier to tell which list you're looking at.
  • The top navigation on the public site says "Use cases" rather than "Who it's for", matching the footer and breadcrumbs, and now marks Use cases or Use with AI as the current section when you're on one of those pages.
  • The browser suite's route sweep is @tam/e2e's sweepApp: every page is now held to HTML structure, axe (WCAG 2.2 AA) and fit at every width from 320 to 1920px, as well as status, render and console.
  • The focus page is called Focus everywhere, in the app's top nav and across the website, instead of "One". The website's "Use with AI" link now says "AI assistants", since it's about connecting your own assistant to Notom.

Fixed

  • The --port flag works on the command line again. Config-arg registration moved from preRun into main before Execute: cobra parses argv before PersistentPreRunE runs, so flags registered from preRun were registered after the command line had already been rejected with "unknown flag". Environment variables and config.yml were never affected.
  • Picks up the shared-library fixes. A HEAD request now returns the same Content-Type as its GET, where before it returned none whenever the type was sniffed rather than set - that is what link checkers, uptime monitors and preview scrapers send. Rendered HTML that sets a status before writing its body (every error page) now carries Cache-Control: no-store instead of no directive at all. A POST to a path that also has a content page falls through to the router rather than being answered with the rendered page. And the shared frontend bundle is ~176KB smaller, the rich-text editor no longer pulling in prismjs for highlighting that was never rendered.
  • Privacy, Terms and the docs pages no longer print their title twice.
  • A silly db_max_connections value is clamped and logged instead of silently wrapping into a negative pool size.
  • Deleting your account, unlinking a sign-in method and revoking an API key now ask you to confirm first. The prompts were written but never shown, so each ran on the first click.
  • Deleting an account now erases everything twad held about the person. Connected-device names, saved values, notification and campaign records, sign-in tickets, OAuth codes, log lines, open invites to their address and their contact-form enquiries were previously left behind. Payment records are kept for the books, and the person now shows as 'Deleted user' rather than 'someone'.
  • Server-side events for a signed-in person are now attributed to them in PostHog rather than to their browser's anonymous id, so what they do joins up across sessions and devices. 4xx responses served to declared crawlers are no longer reported to error tracking as exceptions.
  • Cookie preferences: Back now closes the dialog instead of showing a second copy of the banner's buttons on top of the banner, reopening it always starts from what you last saved (ticks from an abandoned visit no longer linger), and the banner hides while a dialog is open. The privacy-policy reader is titled after the policy page rather than its first subheading.
  • A page no longer prints its own title twice. The API keys and Choose a space screens rendered their heading and then had a second one drawn above them by the app shell; the page owns its heading now, and every screen has exactly one. Privacy, Terms and the docs pages keep theirs, now in the same type as the rest of the app.
  • The Access choice on the API keys screen no longer runs under its dropdown arrow on a phone. The options now say just Read & write or Read only, with what each allows written underneath.
  • Creating an API key that you're not allowed to create now says so ("You can't create that key", or "You're not a member of that space") instead of "Please try again".
  • Server-side analytics events from in-page navigation now carry the browser window's real id, not the session id.
  • The cookie banner's Privacy and Cookies links are now readable in the sentence's colour. They were 3.8:1 and failed WCAG AA.
  • Every change to a note or an action is saved together with its activity-log entry, or not at all, so the log never misses one. Deleting a note with a picture can no longer lose the picture if the delete fails, live updates only go out once a change has actually saved, and opening a note in a personal notebook no longer writes a stray notebook link.
  • Assistants connecting to the MCP endpoint are now pointed at OAuth metadata for /mcp/notes itself (the RFC 9728 path-inserted form), whose resource matches the URL you entered, and are asked only for the notes scopes. Clients that check the resource strictly would previously have rejected discovery; lenient ones were unaffected.
  • An administrator no longer sees "Delete my account", and is told why if they try, instead of getting an error.
  • Once your account deletion has started, Account settings and the banner say it's being deleted rather than offering a Cancel that can't work, and a late Cancel says why instead of failing with "please try again". Cancelling a scheduled deletion now confirms it with a toast.
  • Revoking an API key or removing a sign-in method now confirms it with a toast; the confirmation was being lost in the page reload.
  • A refused API key or plan request now says why instead of leaving a blank page.
  • The Review link action a link note adds is due by your space's timezone, not UTC.
  • Actions work on a note in a personal graph as they do in a space's own: inference puts them there, linked to the note, where it used to fail and retry, and completing, deferring, editing or deleting them works. A personal graph stays its owner's, even attached to a space they share.
  • The note and reply editors now start from what the page shows. After an in-page swap they could briefly start from the previous form's text, so a box redirected back to its own page could carry what was just posted into the next save.
  • On a phone, an action's buttons (Defer, edit, cancel, delete) now sit on a line of their own under it. Beside it they left the action's text a word wide, one word per line. The Defer menu opens centred under its button there, rather than off the left of the screen.
  • A due time typed into the Actions page's add form now saves as that time in your own timezone. A London 11:30pm used to save as 12:30am the next day.
  • Signing out now stops live updates from the account you left reaching that tab, and signing in from a time zone like Etc/GMT+5 now records it correctly.
  • After moving between pages, a confirm question no longer asks once per page visited, and pasting on the notes page makes one note rather than one per visit. Pasting on Actions or Search no longer quietly makes a note either.
  • Pressing Enter in Search no longer reloads the whole page.
  • Asking the notes API for a note or action that isn't in your space now answers "not found" rather than failing with a server error.
  • On the home page and the other marketing pages, the cookie banner's buttons now work. They showed but didn't take a click, so nobody could accept or reject cookies there.
  • An API key that can't be checked because of a passing server fault now gets a 503 to retry on, rather than a 401 saying the key is invalid. Hitting the sign-up or sign-in-link limit shows a proper page with a way back, not a bare 'too many requests'.
  • Starting a subscription checkout now closes any other one still open for the space, so paying for monthly and then yearly can no longer bill two subscriptions. A lost chargeback on the current period's payment now cancels the subscription instead of billing again next month.
  • Every page now meets WCAG 2.2 AA colour contrast, in light and dark. Muted copy, footer links, the marketing eyebrows and the light theme's amber and status colours were all too pale to read as text; the amber is a shade deeper and buttons on it carry white. Pages also gain a main landmark, the top bar a banner and breadcrumbs a labelled nav, the marketing pages arrive settled for anyone who asks for reduced motion, and the settings tabs wrap on a 320px phone.
  • Done on the Focus page keeps you there, and the next action appears in its place. It used to take you off to the Actions list.

Security

  • Three things around user-uploaded media are tightened. A redirect between the app and the media host can no longer be pointed anywhere else: it used to be built by gluing a configured address onto whatever path the request asked for, and is now constructed from the parsed address with only the path and query carried across. Uploaded files are written 0600 in 0750 directories rather than world-readable. And a file is now opened through a handle scoped to the media directory, so the moment between checking a file and opening it can no longer be used to swap in a link pointing somewhere else. A media request arriving in proxied absolute form is also no longer bounced off the host meant to serve it.
  • A space's role check no longer grants every permission to any member of the space. It now answers only for the space's own notes, so anything that is account or admin authority - changing another user, say - is decided by the account's own permissions and can't be picked up just by being in a space.
  • Five HTTP/2 vulnerabilities in golang.org/x/net are fixed (GO-2026-6603, GO-2026-6610, GO-2026-6611, GO-2026-6612, GO-2026-6617): a server crash from an HPACK encoder race, memory exhaustion through trailer headers, excessive CPU from repeated window-size changes, a flow-control double refund on server streams, and malformed framing headers accepted by the HTTP/2 client. All five were reachable from this app's code.
  • Opening /signin while already signed in now only ever sends you to a path on this site. The old check let a crafted return-to path through (a tab after the first slash, which browsers drop and then follow to another site), so a link could bounce a signed-in person off-site.
  • Analytics now records only a visitor's country and, where available, region, and tells PostHog not to geolocate the IP address itself, so no city or coordinates are stored. The same-origin analytics proxy no longer forwards the visitor's IP address to PostHog at all, refuses request bodies over 20 MB (PostHog's own limit, so nothing it would have accepted is lost), and the server's debug logs no longer carry raw event properties.
  • Per-IP rate limits on sign-in and on OAuth client registration (how AI assistants connect) now key on the real client address. They used a forwarded-for header the client could set, so a bot rotating fake values got a fresh allowance on every request.
  • AI assistants connected over OAuth, and API keys, are now held to what they were granted on account-level operations too: workspaces, members, invites, events, entitlements, billing and your own account record. A key limited to one workspace can no longer see, list or act in its owner's other workspaces, a scoped key can no longer create a broader one, and leaving a workspace revokes your keys for it.
  • Content-Security-Policy violation reports now go to the framework's shared endpoint (/.tam/csp-report), which de-duplicates, rate limits and trims URLs to their origin before logging, so a token in a page URL query string no longer reaches the logs. The old /.csp-report endpoint is gone.
  • /oauth/userinfo no longer accepts an access token in the query string, and the OAuth metadata no longer advertises DPoP, which was never enforced.
  • Account deletion can't be partly undone by settings, OAuth consent or events written at the same moment, and a workspace only you were in loses any name or web address you gave it.
  • The live-update stream no longer sends you the ids and kinds of changes in another member's personal graph when it's attached to a space you share.
  • An API key or assistant connection that's only allowed to read your notes can no longer create, edit or complete them. The notes API and the AI-assistant tools now check what each key may do on every call.
  • Analytics no longer records clicks, mouse movement or scrolling for heatmaps before you've answered the cookie banner, and rejecting cookies on one Notom page now clears the analytics identifier left on the others.
  • Visitors from EU territories with their own country code (Réunion, Guadeloupe, Martinique, French Guiana, Mayotte, Saint Martin, Åland), Gibraltar, the Crown Dependencies, and anyone whose country can't be told (including Tor) now get the cookie banner, with analytics off until they choose. They used to get analytics on by default and no banner.

v0.41.1 - 2026-08-22

Fixed

  • Web analytics records every page of a visit again, not just the first one. Visitors who had not yet answered the cookie banner were counted as a single-page visit no matter how much of the site they read, which has made bounce rate and session duration meaningless since 16 August. Figures either side of this fix are not comparable.

v0.41.0 - 2026-08-16

Added

  • Cookieless measurement before the consent click: a visitor with no decision on record is now counted with no cookie, no localStorage and no identifier that survives a page load, so first-visit pageviews are no longer lost in opt-in jurisdictions. A visitor who declines is still not measured at all.

Changed

  • Cookie banner no longer interrupts visitors outside the EU/UK/EEA/CH/CA, where opt-in consent is not required. Those visitors keep analytics on by default and reach their choices through a Manage cookies link in the footer. The banner is unchanged for visitors in opt-in jurisdictions.

v0.40.0 - 2026-08-15

Changed

  • Observability: exports additional OTel metrics from the shared libs (domain events, blob operations, page renders) - visible in Grafana.

v0.39.0 - 2026-08-14

Changed

  • Observability: apps now export a tiny headline runtime metric set (goroutines, process RSS, CPU) instead of the full Go-internals firehose - so per-app memory and CPU are finally visible on the dashboards.

v0.38.0 - 2026-08-14

Changed

  • Internal: render all pages through the shared web.RenderTemplate helper instead of a bespoke panic-recoverer guard, so client-disconnect handling matches the rest of the estate (skel, kythene-www, hikaru). No behaviour change from v0.37.4 - disconnects stay quiet.

v0.37.4 - 2026-08-14

Fixed

  • Client disconnects mid-response (navigated away, closed tab, dropped bot) are no longer logged as recovered panics with a stack trace and reported to error tracking - they're benign hangups, not server errors. Cuts the bulk of prod ERROR-log and PostHog error-tracking noise.

v0.37.3 - 2026-08-14

Fixed

  • Telemetry: service.instance.id is now unique per running instance (tamlib #49), so metrics from two instances sharing a config no longer collide into one series and request/error-rate panels read correctly.

v0.37.2 - 2026-08-13

Fixed

  • Inline scripts on pages reached via a boosted (htmx) navigation now run. The per-request CSP nonce previously mismatched on swap and the browser blocked them, which showed as console errors and silently disabled page-specific behaviours (e.g. search URL sync, paste/drag capture) after an in-app navigation.

v0.37.1 - 2026-08-13

Fixed

  • Attribute server-side PostHog events to the deployment environment (app_env), silencing the 'AppEnv is empty' warning from libposthog.

v0.37.0 - 2026-08-13

Changed

  • Update the workspace libraries and the OpenTelemetry logging/trace stack to the 12 August set; server request spans now redact secret URL path params.

Fixed

  • The cookie preferences link ("cookie settings" / "Manage cookies") works again under the Content-Security-Policy. libconsent now opens the panel via a delegated handler instead of an inline onclick the nonce policy blocked.

v0.36.1 - 2026-08-13

Fixed

  • Report the running version to Tam Central, so the control plane can show what this instance is on and whether it is behind its latest release.
  • Restore UI actions blocked by the Content-Security-Policy. The strict nonce policy (no unsafe-inline, no unsafe-eval) silently killed every inline on* handler and every htmx hx-on attribute: SSO sign-in buttons, theme switching, add-note, note links, inline note actions, replies, API-key copy, admin row navigation, and - a safety bug - the category-delete confirmation (deletes had stopped prompting). All are reworked as CSP-safe delegated behaviours; boosted card links no longer navigate when their inner action buttons are used.

v0.36.0 - 2026-08-04

Added

  • Operator alerting on key account events (new sign-ups, contact submissions, purchases).

v0.35.2 - 2026-07-28

Fixed

  • The staging environment now provisions its QA test accounts. It was configured specifically to allow them but created none, so nothing could be signed in as and no behaviour could be exercised there before a release reached production.

v0.35.1 - 2026-07-28

Fixed

  • Over-limit messages no longer tell you to delete notes to free up space. The note allowance is a lifetime one, so deleting does not give any back and the advice could not work - upgrading is the only way to keep writing.

v0.35.0 - 2026-07-28

Added

  • "next month" now sets a due date. It was offered as an example on the home page and in the feature list but produced an action with no date at all. "end of the month" works too.
  • A Content-Security-Policy is now enforced on every response. This is the defence-in-depth layer under the existing output escaping, and it matters here because the app renders your note text and metadata harvested from third-party pages: it stops the browser running any script the app did not itself emit. Violations are reported to /.csp-report.
  • A note now lists the to-dos Notom pulled out of it, with the same controls as the Actions list. The link between a note and its actions existed in the data but nowhere in the interface, so opening a note to see what was found showed only an edit box.
  • Cancelled actions have a tab of their own and can be reopened. Cancelling used to remove an action from every view with no way to review or undo it - while a separate Delete sat next to it, implying Cancel was the recoverable one.
  • You can now attach an image or video from the New note dialog. Previously the only way in was to drag a file onto the page, which is undiscoverable on a desktop and impossible on a phone - the product's main capture surface.

Changed

  • Worker concurrency and database connection pool are now bounded to the shared-infrastructure budget, preventing the app from starving neighbouring services under load
  • make dev now operates the project dev fleet via tam dev (detached process-compose + tam devserver): fleet stays up in the background, logs captured to ~/.cache/tam-devserver/logs, Ctrl-C only stops following
  • Static assets (CSS and JS) are now cache-busted on a per-build value rather than the per-request CSP nonce, so a returning visitor reuses the cached bundle instead of re-downloading roughly 730KB of JavaScript and the stylesheet on every navigation.
  • Finished background jobs are now pruned automatically after 14 days, sweeping in bounded batches, and the failed-jobs count reflects the live dead-letter set rather than every failed attempt ever made. NOTE for operators: the first sweep after deploy will delete pre-existing job history older than the window.
  • Database queries carry a statement-timeout backstop and the connection pool now reaps idle burst connections, so a pathological query or a traffic spike cannot hold resources indefinitely on the shared database host.
  • The database pool now requests a connection budget sized for the shared database host rather than one connection per CPU core. The previous request was silently clamped on every boot, and the startup log reported the size that had been asked for instead of the one actually granted.

Fixed

  • Failed knowledge-graph embeddings are flagged and retried instead of being lost, and edge listings are bounded.
  • "Stay signed in" is now honoured - leaving it unticked gives a session cookie that ends with the browser session instead of a persistent one.
  • The consent cookie now derives its Secure flag from the actual request rather than the configured app URL, so consent is no longer lost on deployments reached over a scheme the config did not anticipate.
  • Toast notifications no longer break on redirect: the trigger header now emits valid JSON, and a toast raised before a redirect is carried across and shown on the destination page.
  • Code blocks stored in a note now render as a preformatted block, preserving newlines and indentation - previously they were emitted without a wrapper and collapsed into a single run-on line.
  • AI action extraction is more resilient under provider rate limiting and stream errors: Retry-After is parsed in both HTTP-date and seconds form, a stream that emits a delta before its start event now recovers instead of failing the job, and a conversation is always started on a valid turn. Cache writes are also costed at the correct tier, so usage figures are no longer understated.
  • The frontend asset manifests are now regenerated automatically when the dev server starts. The app was missing the go:generate directive the devserver invokes, so a change to the web assets shipped by a shared library was never picked up locally and could reach a build without the matching styles or scripts.
  • The database pool now takes its connection budget from the shared-infrastructure sizing rather than naming its own number, so the budget follows the platform default instead of drifting per app.
  • The "Fix payment" and "Manage subscription" buttons on the plan page now work. They were being intercepted client-side, so the redirect to the Stripe customer portal was blocked and the buttons did nothing at all - with no error shown. This is the path a customer with a failed payment uses to update their card.
  • "Download export" now downloads a file instead of rendering the archive as text in the page. This is the data-portability path, so it was failing for every real user despite the server sending the file correctly.
  • The contact form is rate-limited again. The limit was counted per network connection rather than per sender, so it never engaged and the only abuse control on a public endpoint that writes to the database and sends mail was inert.
  • Declining the optional "Preferences" cookie category now actually prevents the theme choice being written to browser storage. The consent dialog offers theme storage as optional and the app stored it regardless. The theme still applies for the rest of the session, and is saved if the category is later accepted.
  • On the contact form, the helper text under Email no longer runs into the Message label on the following line.
  • A completed action no longer shows a red "overdue" warning. It now reads when it was completed - whether it was finished late is history, not something to act on.
  • The account, sign-in methods and Connect-your-AI-assistant pages no longer render their heading twice, which was a document-outline error for screen readers.
  • Deadline phrases now resolve to the right date. A bare weekday landed a day late ("Friday" gave Saturday), and a weekday with something attached to it ("before Monday's standup") lost the day entirely. The phrases the app advertises are now worked out directly against your configured working week instead of being left to the AI, so they are consistent every time.
  • A link to a note or action that no longer exists now shows the branded "not found" page instead of a blank white screen. These were being reported as server errors, which also meant genuine faults were buried in the error rate.
  • Mistyped and stale public URLs now show the branded "not found" page. The site was serving a plain-text error, and an empty response entirely in production.
  • Error messages now actually appear. Any error raised on a background request was written to the response after it had already been sent, so the notification was silently discarded and the action just appeared to do nothing.
  • App pages now have a name in the browser tab. The notes list, actions list and note pages all rendered an empty title, so several open tabs were indistinguishable, bookmarks saved with no name, and the installed app showed no label in the task switcher.
  • A note page is now named after the note itself, in the tab and in the breadcrumb, rather than every note reading "Edit".
  • Icon-only controls now announce their purpose to screen readers. The account menu, the theme switcher, the note and action capture fields, and the bold/italic/link buttons in the editor all announced as an unnamed "button" or had no label at all.
  • The screenshot on the marketing pages can now be opened from the keyboard. It was reachable by tab and announced as a button, but only ever responded to a mouse. It is now a proper dialog, so focus moves into it, stays inside while open, and Escape closes it.
  • Removed a console error on every background request. The loading indicator pointed at an element that only existed on signed-in pages, so public pages logged an error each time and the intended loading feedback never showed.
  • Confirmation messages read properly again. The first toast a new user saw on their first note rendered as "Note+added.+Reading+it+for+to-dos" - spaces showed as plus signs - because the message was encoded one way and decoded another.
  • HEAD requests to public pages now succeed instead of returning "method not allowed". Link checkers, uptime monitors, crawlers and social-preview scrapers send HEAD before fetching, so the site appeared down to all of them.
  • Toast notifications now announce their message to screen readers. They carried a label of "Close", which replaced the message being delivered.
  • "end of the week" now sets a due date. It is the phrase the home page uses as its own example, and it was the one form of the wording that was not being recognised. "this morning" and "this afternoon" work too.
  • Image and video notes now show the picture or the video, in the list and on the note page. They only ever rendered a small generic icon - the file was uploaded and served correctly the whole time, the interface just never displayed it.
  • Being refused now says why. A permission refusal or a spent plan limit showed the generic "something went wrong, we have recorded what happened" page, which is misleading - nothing is broken and there is nothing for us to look at. There is now a page that states the actual reason.
  • The usage banner now says "you are out of notes" once the allowance is spent, instead of "almost out". At exactly the cap it read as a warning while capture was already being turned away.
  • Acting on a to-do from a note now keeps you on that note. Completing or deferring one from the note page bounced you to the Actions list, losing your place in what you were reading.

Security

  • Hardened authentication and authorization via the libtwad bump: OIDC refresh-token rotation now prevents concurrent double-spend and revokes outstanding access tokens when token reuse is detected, and an authorization check now fails closed if space-role resolution errors rather than silently skipping a per-space deny.
  • Closed server-side XSS/injection sinks and a stability bug via the tamlib bump: escaping in the XML sitemap, dropdown attributes and event line rendering, plus a concurrent-map crash in the viewport widget system under simultaneous requests and connection churn in the no-context dbx query path.
  • Fixed a cross-tenant exposure via the libstripe bump: the Stripe billing-portal session is now authorized against the caller space membership before creation (previously any authenticated caller could open another tenant portal - view invoices, cancel the subscription), and webhooks whose livemode does not match the configured key are rejected.
  • Platform auth hardening from the twad/tamlib bump: session tokens are now stored hashed with sign-in state held server-side, OIDC refresh re-checks scopes, invite/member operations are permission-gated, and the HTTP server gains an idle timeout and header caps.
  • Authentication hardening from the twad bump: the avatar endpoint no longer discloses whether an account exists, PKCE verifiers are compared in constant time, the /twad/self debug surface is gated out of production, the guest sign-in path is rate-limited, and a suspended space is now refused by the space guard rather than only hidden in the UI.
  • Encrypted values now use a v2 scheme with a per-message key derived via HKDF and the ciphertext bound to its context (AAD), so a ciphertext cannot be replayed into a different field or record; existing values migrate lazily on next write.
  • The Connect/MCP API gained a per-method fail-closed authorization backstop: a service method with no explicit permission mapping is now denied rather than served.

v0.34.0 - 2026-06-27

Changed

  • Inbound request spans now record the client user_agent.original attribute (via tamlib bump), so traffic can be segmented by user-agent in tracing - e.g. distinguishing search-engine crawlers from human visitors.

Fixed

  • The PostHog analytics proxy now forwards the real visitor IP and user-agent (via libposthog bump); they were previously masked, so geo, device and bot attribution in PostHog were inaccurate.

v0.33.0 - 2026-06-21

Changed

  • MCP tool permissions are now derived from the request verb rather than a hand-maintained per-RPC list; the permissions gating each tool are unchanged.

v0.32.0 - 2026-06-21

Changed

  • URL notes now open in a read-only view showing the page title, link and crawled summary, rather than an editable form; category remains editable.

v0.31.0 - 2026-06-18

Changed

  • User count reported to Central now excludes service accounts (bots), so the dashboard reflects real users.

v0.30.1 - 2026-06-17

Fixed

  • Changelog page now shows the correct product name (was a stale codename) and has a page description.

v0.30.0 - 2026-06-17

Changed

  • Public content review: the "Use with AI" page is now linked from the nav and footer on all pages; copy and SEO tidy-ups across the marketing pages, docs and policies (meta descriptions added, view labels and product name corrected, testimonial sections reframed as illustrative).

Fixed

  • Comparison hub structured data (/vs and /for) referenced the old preview domain instead of notom.app.

v0.29.0 - 2026-06-17

Changed

  • Updated workspace library dependencies to their latest versions.

v0.28.0 - 2026-06-16

Changed

  • Internal: MCP tools are now generated from the notes service methods via a shared libapi bridge (input schemas derived from the API definitions), reducing hand-maintained boilerplate. No change to the available tools.

v0.27.0 - 2026-06-16

Changed

  • Updated workspace library dependencies to their latest versions (including libcentral - Status/QueryStats pull endpoints and running pull handlers as the system service account).

v0.26.0 - 2026-06-16

Changed

  • Updated the "Connect your AI assistant" guide: Claude connectors are added on claude.ai in a desktop browser (the phone app inherits them), note the paid-plan requirement, and the "Allow" authorisation step.

v0.25.5 - 2026-06-16

Fixed

  • The AI-assistant authorisation screen is now styled and reliably completes when you press Allow, including in apps that block third-party cookies (it previously could loop on the consent step).

v0.25.4 - 2026-06-16

Fixed

  • Pressing "Allow" on the AI-assistant authorisation screen now completes the connection instead of reloading the page (the consent step lost the session on the cross-site form submission).

v0.25.3 - 2026-06-16

Fixed

  • Signing in to connect an AI assistant now completes successfully end to end - approving access returns you to your assistant connected, with your notes and to-dos available (several steps of the sign-in were failing).

v0.25.2 - 2026-06-16

Fixed

  • The "Allow access" screen when connecting an AI assistant now displays correctly (it was a blank page), so you can approve the connection and finish signing in.

v0.25.1 - 2026-06-16

Fixed

  • Connecting an AI assistant by signing in now works: dynamic client registration no longer fails for clients (Claude, ChatGPT, …) that omit optional fields, which previously returned "registration failed".

v0.25.0 - 2026-06-16

Added

  • gRPC/Connect API: a notom.notes.v1 service (GetNote, ListNotes) mounted at /api (enable with api_enable), callable over gRPC and Connect-JSON. Authenticated with a libtwad API key (X-API-Key or Authorization: Bearer twk_...) or an OAuth bearer token, running as the authenticated user in their space.
  • OpenAPI v3 spec for the API services, served at /api/openapi.json (generated from the protos, describing the Connect JSON endpoints).
  • API notes service expanded to the full set of typical interactions: CreateNote and UpdateNote (plain text in), GetNote/ListNotes, and the "one thing to do right now" via GetNext (the most-imminent open action) and CompleteNext. Available over gRPC, Connect-JSON and in the OpenAPI spec.
  • MCP server for notom at /mcp/notes (streamable-HTTP), exposing the notes operations as permission-gated tools: list_notes, get_note, create_note, update_note, get_next (the one thing to do now) and complete_next. Authenticated with a libtwad API key or OAuth bearer; tools are filtered per caller permission.
  • AI assistants (Claude, ChatGPT, Cursor, …) can now connect to notom by signing in: an OAuth 2.1 / OIDC server with dynamic client registration (enable with oauth_enable), so connecting needs only the URL https://notom.app/mcp/notes and a sign-in, no key to copy. API keys can also be scoped read-only or read-and-write and optionally pinned to one space.
  • New "AI assistants & API" settings page (/settings/api-keys): create an API key (shown once), choose read-only or read-and-write access and optionally pin it to a space, see your keys and revoke them. Shown in the account menu when api_enable is on.
  • New guide "Connect your AI assistant" (/docs/connect-ai/) with step-by-step instructions for Claude, ChatGPT and Cursor, plus a public page (/ai) explaining how to use notom from your AI assistant.

v0.24.0 - 2026-06-16

Changed

  • Updated workspace library dependencies (libcentral, libtwad) to their latest versions.

Fixed

  • Note and action creation events now always record the space the note/action belongs to. Previously a creation path with a non-space-scoped token (e.g. the PWA share-target) logged the event with a nil space, so the events log was missing the space id for some note/action creations. Space is now mandatory on these events.

v0.23.0 - 2026-06-16

Changed

  • Updated the libcentral dependency to its latest version.

v0.22.0 - 2026-06-15

Added

  • ADHD landing pages now lead with real app screenshots (capture box, notes list, Actions, and the One focus view), with light/dark variants. The marketing nav gains a "Who it's for" link and a light/dark/system theme switcher on every page, and the homepage feature grid adds a sixth card ("Capture from any app"). ADHD copy simplified and the hub now states "for ADHD brains" up top.

Changed

  • Action due times now read by calendar day - "today", "tomorrow at 9am", "Mon at 2pm" - instead of 24h countdowns ("in 20h"), so same-day items read calmly as "today" and next-day items are no longer confusingly shown as "in 20h". The defer control now always shows its "Defer" label (was icon-only on narrow screens).

Fixed

  • Cookie consent banner now renders correctly (centred card, rounded corners, dimmed backdrop) instead of falling back to the browser default (top-left, bordered). libconsent ships dialog-positioning CSS and template classes that were never wired into the app Tailwind build; they are now included.

v0.21.0 - 2026-06-15

Changed

  • SEO: robots.txt now also disallows /admin (auth-gated admin UI should not be crawled).
  • ADHD landing page (/for-adhd) restructured from one long scroll into a short hub linking four focused single-idea sub-pages (/for-adhd/capture, /no-setup, /auto-actions, /one-thing) - better for the audience it targets. Each is in the sitemap with a four-deep breadcrumb trail.

v0.20.0 - 2026-06-15

Changed

  • Telemetry: product-prefixed service.name for readable SigNoz service list.

v0.19.0 - 2026-06-15

Changed

  • Telemetry: three-tier service identity (product=notom, app=notom, instance.id).

v0.18.0 - 2026-06-15

Changed

  • Switch telemetry export to config-driven OTLP (SigNoz) via otlp.InitFromConfig.

v0.17.0 - 2026-06-15

Added

  • Defer actions: snooze an action to a preset (in 3 hours / tomorrow morning / this weekend / next Monday) or a custom date-time. Deferring drops the action off the do-now and One pickers until the chosen time, then it reappears. Presets resolve to natural anchor times (e.g. 9am) in your timezone. Available from the Actions list, the do-now card, and the One page, alongside a new inline edit form.

Changed

  • OTLP telemetry config keys renamed: grafana_endpoint_trace / grafana_endpoint_metric / grafana_endpoint_log / grafana_apikey are replaced by otlp_traces_endpoint / otlp_metrics_endpoint / otlp_logs_endpoint / otlp_headers. Operators must update config before deploy; the old keys are no longer read.

v0.16.0 - 2026-05-31

Added

  • Search: dedicated /s/{spaceID}/search page with a type-filter dropdown and URL-preserved query state (q + kind round-trip via history.replaceState, so reload / back-forward / pasted links all restore the filter).
  • One: dedicated /s/{spaceID}/one focus page showing the single most-imminent open action big, with a Done button. Hit Done and the next-most-imminent slides in via the realtime channel.
  • 13 public SEO landing pages: 6 comparisons (vs Notion / Apple Notes / Google Keep / Evernote / Obsidian / Todoist) and 7 audience pages (for ADHD / founders / freelancers / parents / writers / students / recovering Notion users). Each carries hero, pillar sections, comparison table or typical-day scenario, who-it-fits cards, FAQ + JSON-LD FAQPage, and cross-links to siblings.
  • /vs and /for index/hub pages linking to the comparison and audience pages, plus a CollectionPage + ItemList JSON-LD schema for each.
  • BreadcrumbList JSON-LD on every secondary marketing page (Home > Compare > vs Notion etc.) for SEO-friendly SERP breadcrumbs. Wired centrally via the seo plugin so adding a new marketing page only requires an entry in the URL -> leaf-name map.
  • Health providers for the SSO signin-state queue (twad) and the consent audit log table (consent), exposed via the app /health endpoint. Warn/fail thresholds defend against brute-force on /auth//login and silent draining bugs.

Changed

  • Actions page reworked: grouped view (Overdue / Today / This week / Later / No date / Completed) when the filter is broad, relative-time display ("2 days overdue", "in 3h", "tomorrow at 9am") alongside absolute date, in-place htmx capture (no full reload), source-note link on inferred actions, and per-tab counts that stay in lockstep with the displayed list. Default tab renamed from "Upcoming" to "Open" (the ?filter=upcoming URL is still accepted as an alias). The "Today" boundary uses the users timezone, not the servers, and "Week" is now strictly the next 7 days from now (no longer silently includes overdue).
  • Authenticated chrome: sticky body-scroll navbar replaces the old inner-scroll layout. Mobile nav-tab labels collapse to icons on narrow viewports (with title tooltips); avatar no longer pushed against the viewport edge.
  • Marketing-page screenshots are now theme-aware via <picture> + a MutationObserver on data-theme, so each visit fetches only the variant that matches the active theme (rather than always pulling both light and dark assets).
  • Sitemap.xml now lists 22 URLs (was 6), covering the 15 new SEO landing pages, the 2 hub pages, and /contact, with priorities reflecting editorial importance (core 0.8 / hubs 0.7 / leaves 0.6).
  • Cookie consent banner: category labels shortened ("Marketing measurement" -> "Marketing", "Remember my preferences" -> "Preferences", "Help us improve" -> "Improvement") so the dialog fits comfortably on narrow viewports. Descriptions reworded to match.
  • Em-dashes stripped from all user-facing marketing copy, page titles, the notes "Note added" toast, and inline JS comments emitted in served HTML. Voice consistency across public content.
  • All 4 existing marketing pages (index, how-it-works, pricing, contact) now use a shared footer partial; the footer gains links to /vs and /for so the new SEO landing pages are discoverable from anywhere on the site.
  • How-it-works and pricing pages each carry an inline "Coming from another tool?" cross-link to the relevant vs-* comparison pages.

Removed

  • Sidebar drawer in the authenticated chrome (drawer wrapper, {{define "menuitem"}}, {{define "sidebar"}}, and the $hideSidebar flag are all gone). The app has no side nav; the markup was unused.
  • ui/assets/robots.txt deleted. The seo plugin already serves /robots.txt directly with proper dev (Disallow: /) vs prod (real Robots) gating, so the static asset was dead and confusing.

Fixed

  • Vertical scroll on mobile was broken by a leftover body { overflow-y: hidden } rule from the previous inner-scroll layout. Rule removed; scroll restored on all viewports.
  • og:description and twitter:description now reflect each pages own description on shared links. Previously every marketing-page link shared on Twitter/LinkedIn/etc. showed the same generic site-wide blurb in the social-card preview, because the apps FnOutput was clobbering the per-page description before the seo plugins finalize() could pull it from rc.Head().
  • SSO signin self-heals stale parent-domain neighbours of the binding cookie, so signin no longer intermittently fails with "invalid state binding" after a deployment that previously set the cookie with a Domain= attribute. Same fix shape as the earlier auth-cookie self-heal.

Security

  • HSTS (max-age=1 year, includeSubDomains), X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, and X-Frame-Options: SAMEORIGIN are now set on every response via the new web.SecurityHeaders middleware. CSP is intentionally not set globally - a useful CSP needs per-app allow-lists and nonces.

v0.15.3 - 2026-05-30

Fixed

  • more fix scrolling!!!

v0.15.2 - 2026-05-30

Fixed

  • Fixed broken vertical scrolling

v0.15.1 - 2026-05-30

Fixed

  • Mobile layout fixes

v0.15.0 - 2026-05-30

Changed

  • Various layout/content tweaks

Fixed

  • Fixed login errors caused by libtwad cookie changes

v0.14.0 - 2026-05-29

Changed

  • Removed Anthropic/Claude references -> just AI
  • Slight font size increase

Fixed

  • Fixes/improvements to SEO

v0.13.0 - 2026-05-29

Changed

  • Further visual refinement

Fixed

  • Fixed SSO login error due to recent libtwad security improvements

v0.12.0 - 2026-05-29

Added

  • Large continued developments in all areas

v0.11.0 - 2026-05-04

Changed

  • minor content/labelling tweaks

v0.10.0 - 2026-05-04

Added

  • Added admin area

v0.9.0 - 2026-05-04

Changed

  • More visual tweaks

v0.8.0 - 2026-05-03

Added

  • Many changes

Changed

  • Various UI fixes/tweaks, incl. to settings and page header

v0.7.0 - 2026-04-26

Added

  • lots

v0.6.0 - 2026-04-20

Added

  • Customisable behaviour for actions added on adding URLs

v0.5.1 - 2026-04-20

Fixed

  • Various UI and URL-handling fixes

v0.5.0 - 2026-04-19

Changed

  • Tweaked mobile padding/spacing

v0.4.0 - 2026-04-19

Added

  • Added AI inference of Todo actions

Changed

  • Various UX improvements

Fixed

  • Various dark mode fixes

v0.3.0 - 2026-04-19

Added

  • Background jobs for pulling URL title/summary

v0.2.0 - 2026-04-19

Added

  • Google/MS/Apple signin support, and make Github optional

v0.1.0 - 2026-04-18

Added

  • Initial build
  • Posthog