YouBothAgent▾
You — Business rules and flows you own. Read these yourself.
Both — Know the idea; your agent follows the details.
Agent — Conventions and references your agent follows. Look up as needed.
General▾
Interface▾
Observability▾
Performance▾
Native▾
Development▾

PWA

A PWA (Progressive Web App) runs in the browser but can be installed and launched like an app. The browser adds the icon, the app window without a toolbar, and the install prompt.
  • When it helps. Users open the same web app again and again, and a home-screen or desktop launcher saves them time.
  • Typical apps. Admin tools, field-work apps, internal dashboards, lightweight commerce apps and content apps.
  • Where it starts. A web app manifest that tells the browser the app's name, icon, start URL, display mode and colors.
Add It In Three Steps
  1. Put the icons in apps/<app>/public/. That folder is served from the site root, so public/icon-192x192.png loads as /icon-192x192.png.
  2. Declare the manifest in one of two ways: a static manifest.json linked from .head(), or rootLayout().manifest({...}).
  3. Deploy, check that every URL in the manifest loads, then test installation.
Two Ways To Declare It
Static JSON File
apps/<app>/public/manifest.json
  • Keys. Standard snake_case, exactly what the browser reads.
  • Linked by. A <link rel="manifest"> you write in .head().
  • Pick it when. Designers or operators need to review the JSON directly.
.manifest() Object
apps/<app>/page/_layout.tsx
  • Keys. camelCase, converted to snake_case for you.
  • Linked by. A data: URL link Akan adds to the head, so no file is served.
  • Pick it when. You want TypeScript help and app metadata in one place.

When To Use PWA

A PWA makes a web app easier to come back to. It does not replace every native app, but it is a strong first choice when shipping on the web fast matters and the app needs no deep device APIs.
Situation
PWA alone
Native too
Good fit
Daily workflow
✓
Users return to the same flow every day: office tasks, approvals, reports or checklists.
No app store first
✓
One deployed web app covers desktop and mobile before any app-store release.
Be careful
Deep native features
✓
The core of the product needs device features the browser does not expose.
Heavy background work
✓
The app has to do heavy work while it is not on screen.
App-store presence
✓
Being listed in the app stores is a hard requirement.
✓AppliesDoes not apply
In the three careful cases, plan a native wrapper or a native app next to the PWA.

Static Manifest File

Use this when you already have a manifest.json or want to edit the exact JSON the browser reads. First, put the file in public/:
apps/myapp/public/manifest.json
Then link it from .head() of the root _layout.tsx:
apps/myapp/page/_layout.tsx
  • Standard keys. The file is served as is, so write the browser's own snake_case keys such as short_name and start_url.
  • A real URL. public/manifest.json is served at /manifest.json, so you can open it in the browser to check it.

Layout Manifest Object

rootLayout().manifest({...}) keeps the manifest in app code instead of a separate JSON file. Write the keys in camelCase:
apps/myapp/page/_layout.tsx
  • camelCase in, snake_case out. shortName, startUrl and themeColor reach the browser as the standard short_name, start_url and theme_color, at every depth.
  • No file to serve. The object becomes a <link rel="manifest"> in the head whose href is a data: URL, so there is no /manifest.json to open.
  • Root layout only. .manifest() is a rootLayout() stage, so it goes in the app's (or a base path's) root _layout.tsx.
Keys You Can Write
The argument is typed as WebAppManifest from akanjs/client. Every key is optional.
namestring
Full app name shown in the install dialog and the app list.
shortNamestring
Short name shown under the home-screen icon.
descriptionstring
One-line description of the app.
startUrlstring
The page the installed app opens first.
scopestring
The URLs that stay inside the installed app window.
display"fullscreen" | "standalone" | "minimal-ui" | "browser"
How the window opens; standalone hides the browser toolbar.
displayOverridestring[]
Display modes to try in order before display.
orientationstring
Default screen orientation, such as portrait.
themeColorstring
Color of the title bar and system UI around the app.
backgroundColorstring
Background of the splash screen shown while the app loads.
langstring
Language of text values such as name and description, for example ko.
dir"ltr" | "rtl" | "auto"
Text direction of those same text values.
iconsWebAppManifestIcon[]
App icons; each entry takes src, plus optional sizes, type and purpose.
categoriesstring[]
Categories that describe the app, such as business.
screenshotsWebAppManifestIcon[]
Images for richer install dialogs, in the same shape as icons.
[key: string]unknown
Any other member, such as shortcuts or id, passes through with its keys converted.

Required Assets

Before testing installation, make sure every URL in the manifest loads on the deployed app. These are the ones to check first:
/icon-192x192.png/icon-512x512.png
Good first sizes for install prompts; Chrome needs at least one icon of 144px or larger.
startUrl
The page the installed app opens at launch, so it must load on the deployed app.
scope
Limits which URLs belong to the installed app window.
display: "standalone"
Opens the app without the normal browser toolbar.

Tips

  • Start simple. Ship one minimal manifest first. Add screenshots, categories or shortcuts once installation works.
  • Under a base path. Set startUrl and scope to that path instead of /. A base path's root _layout.tsx with no .manifest() of its own uses the app root's.
  • Pick one method. With both, the page carries two <link rel="manifest"> tags and the browser reads only the first.
  • Test over HTTPS. Browsers offer installation only on HTTPS or localhost. Chrome DevTools → Application → Manifest shows what the browser parsed and why it will not install.
Read next

Released under the MIT License

Connect your AI to these docs

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js All rights reserved.System managed bybassman