Akan.js 3.1.0
Release notes · Oct 25, 2026
Akan.js 3.1.0 release notes
Everything that changed in 3.1.0, in plain terms: what got safer, what is new, what got faster and what got fixed, followed by a short checklist for upgrading. Each package's CHANGELOG.md keeps the full technical entries.
Read the 3.1 announcementRequirements
Bun
1.4.4+
Akan stops on an older Bun.
React
19.3.1
Pin react, react-dom and react-server-dom-webpack to this version.
akanjs · @akanjs/cli
3.1.0
Install both at the same version; the new CLI will not build native apps against an older akanjs.
Upgrade Bun, update the workspace and the global CLI, then run these once on every app and library:
Security
None of these needs a code change, and several close a gap between visitors or between servers. Every 3.0 app should take 3.1.0.
- Visitors' sessions never mix. Under heavy traffic, part of a page streamed to one visitor could read another visitor's login cookie; each render now sees only its own request.
- Your users' login stays home. A server-side call to another company's API no longer forwards the visitor's login token, cookie or address; only calls to your own server carry them.
- No more redirect tricks. A crafted link such as ?redirect=evil.com can no longer use the app's navigation to send a visitor to another site.
- Requests can't grant themselves extra rights. Fields a form was never meant to send, such as a role or a deleted flag, are dropped before they reach your code.
- Switching accounts leaves nothing behind. Pages kept for the previous account are dropped at sign-in, and a redirect raised while a page renders is never cached by a CDN.
- Login headers are read one strict way everywhere: the API, the AI endpoint, device tokens, the ops channel and the log stream all accept only 'Bearer' followed by a single token.
- Fewer secrets in your logs: more kinds are masked, such as webhook URLs, database connection strings and signing keys.
- Updates nobody can tamper with. A CDN in between can no longer alter a signed app update, and a signed desktop app refuses an update signed by anyone else.
- A server running on an edge device starts with its AI endpoint turned off.
- The in-page agent acts only on what is on screen: if the screen changes while it is acting, its call is refused instead of running against the wrong thing.
- A security scan hardened text matching against input crafted to stall the server, keeps unsafe link types out of what the agent reads, and escapes values written into native app settings.
New features
Pages and navigation
- Access control before render: a guard on a layout or page decides who may open it before anything is drawn. A guest goes straight to sign-in, and a record they may not see answers as if it did not exist.
- Give each theme its own colour, and the browser bar and the iOS status bar follow it the moment the theme switches.
- A change of only the URL's query, such as a filter, can update the screen without reloading the page from the server.
- A back button always has somewhere to go: give it a fallback page for the first screen after a reload.
- Headers, tab bars and other frame parts arrive in the first HTML, so text typed before the page finishes loading keeps its place.
- Titles and meta tags from nested layouts merge predictably: the deepest one wins, and the rest are kept.
AI agents and MCP
- MCP Apps: show a page's component inside AI chats such as claude.ai. It is the same component your site shows, runs with the user's own permissions and can only read.
- Each of those views is built small, carrying only what it needs, and rebuilds as you save during development.
- Endpoints can return images that an AI model receives as pictures, such as a chart or a product photo.
- The in-page agent can look at images on the screen, and your own tools can attach files to what they return.
- Give each screen action a human-friendly name, and list the screen's one-click actions for a command palette.
- Run a single AI turn on a different model, such as the one the user picked, without extra setup.
Server and API
- Every request is checked against your models before your code runs, over HTTP, WebSocket and MCP alike. An error names the exact field, and fields the input does not declare are dropped.
- List the errors an endpoint returns on purpose. They appear in your API docs and in AI tool descriptions, and a caller can check for one by name.
- Calls to other servers retry by themselves through brief outages and busy responses, within the deadline you set. Send a payment or an order with a duplicate-protection key and it runs exactly once.
- Live connections reconnect gently, and right away when the device comes back online or the tab becomes visible. Missed updates are detected and filled in.
- Clear an endpoint's cached answers on every server the moment the data behind them changes.
- Background jobs can cap how long they wait between retries and run a hook when they finally fail, and a server can start without scheduled jobs for tests and scripts.
Data
- Data migrations that preview, apply, verify and roll back. A migration refuses to run if the data changed after you reviewed it, only one runs at a time, and it works the same in development and in deployed containers.
- Akan Cloud can start a migration on a server it has no shell access to.
- Delete data past its retention, such as old logs, for good and in safe batches. A delete with no conditions is refused.
- Import records under their original ids and timestamps, and let summary fields add values up.
UI and forms
- A modal can open as a full-screen sheet on phones that you swipe down to close, or slide in from the right as a side panel.
- Uploads belong to the form that started them, and the submit button waits until every upload is done.
- Mark every list of a model stale in one call, so each refreshes the next time it is shown.
- Layouts can follow the on-screen keyboard and the safe areas, with different spacing per screen size, and the bottom tab bar tells screen readers which tab is current.
- Tooltips flip to the side with room, bottom sheets lock the page behind them, and the agent's launcher button can move or hide on small screens.
- Generated API reference pages render on the server and can be grouped by library.
Native apps
- Phone app updates are signed so no CDN can tamper with them, with up to three signing keys to rotate between and revocations every device remembers for good.
- See how each release landed on devices (downloaded, applied, rolled back or failed) through a random install id and nothing about the user.
- Publish a phone update straight to Akan Cloud, which signs and ships it, and register store builds the same way. The same commit always packs to the same bytes, settings included.
- Kiosk mode for desktop apps: pages cannot open print or file dialogs, downloads, share sheets or other programs.
- A desktop app's built-in server restarts itself, is watched by a health check, and can be built without your secrets. Devices can prove who they are with signed device tokens, and a module can run only on edge devices.
- Show a third-party web page inside your desktop app as if it were your own, with its own browser profile, and place windows on a chosen display, frameless if you like.
- Windows paint their background before the page loads, so there is no white flash. Windows apps name your company as publisher, installers can bundle WebView2, installed apps can switch update channels, and internal builds can open developer tools.
- Publish desktop releases for both arm64 and x64, and upload them straight to S3.
CLI and deployment
- Declare your build pipeline in akan.config.ts, from build and test to Docker and deploy, with shell steps of your own, and preview locally what Akan Cloud will run.
- Pipeline secrets are write-only, kept per project and branch, and never accepted as a command-line argument.
- akan typecheck covers libraries and your tests, and a new lint rule catches hooks a render can skip, a classic cause of production-only crashes.
- akan code, the built-in coding agent, compacts its conversation at a point you choose and can search the web when the workspace has a DeepSeek key.
- The AGENTS.md the CLI writes is about 60% smaller, so coding agents spend less of their context on rules.
Performance
2.5×
faster list responses
16 µs → 6.5 µs
1.5×
faster simple API calls
3.0 µs → 2.0 µs
+15%
more pages served per second
26.7k → 30.8k req/s
−14%
shorter slowest responses
p99 3.7 ms → 3.2 ms
Each figure was measured on one machine just before and just after the change behind it: API calls in process, pages on a cached page of the sample app.
Where it comes from
- Each endpoint is prepared once and reused, and a call skips caching, duplicate protection and rate limiting when it does not use them.
- Responses follow a plan made once per model, in a single pass when no related data is involved.
- A signed-in live connection checks its login once per connection instead of on every message; a sign-out still takes effect at once.
- The API description is built once per process, and startup logs how long each step took.
Fixes
Grouped by area. Open one to see what was fixed.
Pages and navigation6
- Missing pages and redirects return real 404 and 3xx status codes, even while a layout is still loading, so search engines and link previews read them right. An invalid value in the URL answers 404 instead of a blank page.
- A page whose head fails still renders instead of failing the whole request, and loading indicators on group layouts show up.
- Back and forward return to where you left off, in Safari too, while images and streamed sections settle.
- In native app screens, not-found pages, redirects and stacked screens behave correctly.
- External links with unusual casing or no scheme (//host) open outside the app, unchanged.
- A base path matches only whole segments, so /officers is no longer mistaken for /office, and Chrome finds the install manifest.
Server and API6
- Bad or missing arguments answer 400 and missing records 404, instead of 500, and links to deleted records drop out of lists.
- A cached answer is identical to a fresh one, dates and binary data included.
- Live rooms no longer keep subscribers that already left, and server-to-server live connections recover within one heartbeat.
- Errors from a proxy in between show as readable messages, a 'retry after 0 seconds' means now, and a cloned client keeps its timeout.
- Turning a module off also turns off the modules that depend on it instead of erroring, memory limits inside containers are read correctly, and a crashed replica is restarted reliably.
- Type fixes: in-memory values keep their class, and an endpoint that returns anything is typed unknown on the client.
Data6
- Conditional updates are atomic on Postgres: two simultaneous withdrawals can no longer both pass the same balance check.
- Index names stay stable, so adding one no longer rebuilds the rest. Indexes Akan created and no longer needs are removed; ones you made by hand are left alone.
- Partial indexes are real on SQLite and Postgres, so a deleted record can give its unique value back, such as an email address.
- A queued job that crashed on its last attempt is marked failed instead of running again.
- Cascading deletes finish cleanly even when two owners share a target, with no files left behind.
- Filtering by a model's own kind field works, counts on searchable models are accurate, SQLite waits only for real writes, and live lists that send only ids update.
UI and forms7
- Modals stack above everything else, dropdowns inside them open on top, toasts sit above modals, and the agent's launcher sits under menus.
- Buttons inside built-in components, such as a password toggle or a copy button, no longer submit the surrounding form.
- An open edit form keeps what you typed when the page refreshes, and a searchable select searches once after you stop typing.
- Live lists keep all their rows and stay put through updates, and a list shown again after going back in a native app reloads its own data.
- Selects show options by their translated names, and edit modals show only the actions you are allowed to take.
- Installed web apps stop bouncing, small inputs no longer make iOS zoom in, and the back link is a real button a keyboard can reach.
- In the agent chat on phones, picking from the @ and / menus keeps the keyboard up, and mentions with brackets in their title work.
Native apps4
- A signed desktop app refuses updates signed by someone else, and stops offering them.
- A phone release that freezes rolls back while the app runs, background launches no longer cause false rollbacks, and apps built with the iOS 26 SDK run on iOS 18.5 again.
- Windows installs and uninstalls survive automatic restarts, a silent install shows no window over a kiosk, only one instance runs across sessions, and the app's own name appears on its executable.
- A window can no longer be placed off every display.
CLI and build6
- No command waits for keyboard input in CI: a missing argument fails right away and says what to pass.
- Builds are reproducible, and the default Docker image is pinned to Bun 1.4.4 instead of a moving tag.
- Script, console and database import and export commands run from the workspace root against the same database as akan start.
- Tailwind classes with nested brackets compile, and code highlighting inside a lazily loaded editor works in app bundles.
- Failed builds print their errors once, and a child server's errors show in the akan start terminal.
- Generated files pass lint, the CLI runs without a root .env, generated paths use / on Windows, installing a library is faster, and warnings no longer break JSON output.
Upgrade checklist
Most apps need only the first group. Skim the rest for the features you use; akan lint and akan typecheck point at most of it.
Every app
Check these whatever your app does.
- 01
Requests are checked strictly now. A client that sends a number as text, an { id } object where an id belongs, or leaves out a required field gets 400. If your service read a field its input does not declare, declare it.
Details - 02
Bad or missing arguments answer 400 instead of 500: update tests or clients that expected 500.
Details - 03
akan typecheck checks your tests too (--tests false restores the old scope), and lint flags hooks a render can skip.
Details - 04
Quote any .env value that contains #: an unquoted value now ends at the #, the way Bun reads it.
Details - 05
A CI step that answered a prompt through stdin now fails fast: pass the argument on the command line.
Details
If your server calls other servers
Pages and UI
- 01
router.push, replace and redirect to another site need { external: true }. A Link to another site is unchanged.
Details - 02
A page no longer inherits its layout's canonical link or og:url: declare them in each page's own head.
Details - 03
Modals now sit above other overlays. An element that used a z-index between 10 and 120 to sit above a modal now sits under it, and a custom agent launcher must apply its new style prop.
Details - 04
A Link's active state matches whole path segments, and / is active only on the home page.
Details - 05
Constant.Doc given an empty list now shows nothing; leave the prop out to show every model.
Details
MCP and agents
- 01
Pages with .prompt() also appear as tools. In an app that serves its CSR bundle, AI clients that support MCP Apps can call the read endpoints a screen needs, under their guards, and an app with an .app() page uses the older MCP protocol revisions unless you set option.setMcp({ modern: true }). option.setMcp({ apps: false }) turns all of this off.
Details - 02
The agent's image viewer is now one of its default tools; list the built-ins you want to leave it out.
Details - 03
A server running on an edge device serves /mcp only with AKAN_MCP=true or option.setMcp(true).
Details
Data and server
- 01
Cache lifetimes are capped at one day, and answers cached before the upgrade are fetched fresh once.
Details - 02
LibsqlDatabase is removed: use SqliteDatabase for a local file, or cluster mode for a shared server.
Details - 03
Indexes that declared a where are rebuilt once, as real partial indexes, on the next boot. A where no index can hold, or two different indexes with the same name, stops the boot.
Details - 04
In single database mode, a job whose process dies on its last attempt now fails instead of running again: use attempts: 2 to keep that retry.
Details - 05
A memory() value of a model class is now an instance: copy it with new cnst.X().set(value), never a spread.
Details - 06
Turning a module off also leaves out the modules that relate to it, and log searches for a newly masked key see [redacted].
Details
Native apps
- 01
Desktop signing is opt-in: add --sign true to akan build-desktop and akan publish-update, plus --notarize true on macOS. Sign each release the same way as the installed app, which refuses anything else.
Details - 02
Phone apps that receive updates need one new store binary before you publish an update in the new format, and a signing tool of your own must read the new layout.
Details - 03
In kiosk mode, pages cannot print, pick files, download or open the system browser: open those through the opener or file-picker plugin.
Details - 04
A desktop app that carries its server is refused a release build while that server holds a secret from your server env files: build it with native.desktop.server.profile.
Details - 05
akan pack-update --against exits 2 when a new store build is needed, and 1 for any other failure.
Details
Workspace and tooling
- 01
A workspace with the shared or util library adds their type packages: bun add -d @types/react @types/react-dom, plus @types/nodemailer with util.
Details - 02
akan.subspace.ts is no longer read: move it under subspace in the workspace-root akan.config.ts and delete it. A subspace no longer receives the workspace's Jenkinsfile.
Details - 03
Script, console and database import and export commands resolve relative paths from the workspace root: build a script's paths from import.meta.dir.
Details - 04
Run akan login again if your saved host ended in a slash, used capitals or :443, and set docker.image to run a Bun other than 1.4.4 in your image.
Details - 05
Optional peers move up: happy-dom 21, which loads no CSS files or iframes by default, and firebase 13.
Details
Rarely used internals that were removed or renamed are left out here; akan typecheck points at them.