The popup loads the GUI with embedded_in_popup=true, so it ran the sign-in token exchange and posted puter.token to the opener before the user answered the prompt. A site that called requestPermission() walked away holding a user-app token for the account even when the user pressed "Don't Allow" — and because the SDK's global puter.token handler feeds event.data.token into setAuthToken() without looking at `success`, a failed exchange posted token: null and wiped a token the site already had. Keep running the exchange (it bootstraps the app row the grant needs and caches host_app_uid) but leave the token in the popup. A site that wants credentials still has to call signIn(). Escape on the SDK's consent dialog left the caller pending forever. PuterDialog wired its Cancel and close buttons but not the <dialog>'s native cancel event, so the browser dismissed the dialog and nothing reported it: no dialog, no popup, no answer. Route cancel to the same handler. Programmatic close() fires only `close`, so launching the popup — which closes this dialog — is unaffected, and the implicit-auth flow stops hanging on Escape too. Serialize the permission dialogs. showModal() makes the whole document inert rather than just the requesting app's window (which is what the UIWindow it replaced did), and the dedup map only coalesced identical requests, so an app asking for permissions in a loop stacked one modal per request and walled the user off from the desktop — including from the app doing it. Prompts now queue and open one at a time, and each caller still gets its own decision. Identify apps by more than their title. `title` is free-form text the author picks and is not unique, so it was the whole identity of a prompt an app titled "Puter Settings" could raise; the registered `name` is unique and format-restricted, so show it underneath. Give the name line the unicode-bidi isolation the origin line already had, since escaping leaves bidi overrides intact. Stop the dialog from answering over its own in-flight grant: a dismissal while the POST was outstanding resolved false for a permission the server was committing. Ignore dismissals while granting, and time-box the request with AbortController (AbortSignal.timeout isn't everywhere) so a hung network can't leave a modal no one can close. Fail closed on the remaining paths that could reject or prompt uselessly — showModal() throwing under <iframe sandbox>, and a requester known only by app_name, whose Allow the server would always reject. Pass the error string to .text() unencoded so translations containing an apostrophe don't render '. The e2e suite covers all of it; each new test fails without its fix.
The Open-Source Internet Computer!
« LIVE DEMO »
Puter.com
·
App Store
·
Developers
·
Discord
·
Reddit
·
X
Puter
Puter is an advanced, open-source, self-hostable internet computer designed to be feature-rich, fast, and highly extensible.
For Users
Puter's goal is to provide you with every app and feature you need to work, create, and play under one roof. From a simple Notepad and Voice Recorder to Spreadsheet and Camera, Puter wants to be the all-in-one solution for your digital life.
For Developers
Puter provides everything you need to build and publish web apps and games. From AI to Cloud Storage and Database to Serverless Workers, Puter has you covered. Puter also helps you get users! Once you build your app, you can publish it on our App Store to reach and monetize users.
Getting Started
💻 Local Development
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
→ This should launch Puter at http://puter.localhost:4100
🚀 Self-Hosting
Linux/macOS
curl -fsSL https://puter.com/selfhost | sh
Windows
irm https://puter.com/selfhost?os=windows | iex
→ For more details, see Self-Hosting Puter.
☁️ Puter.com
Puter is available as a hosted service at puter.com.
Support
Connect with the maintainers and community through these channels:
- Bug report or feature request? Please open an issue.
- Discord: discord.com/invite/PQcx7Teh8u
- X (Twitter): x.com/HeyPuter
- Reddit: reddit.com/r/puter/
- Mastodon: mastodon.social/@puter
- Security issues or abuse reports? security@puter.com
- Email maintainers at hi@puter.com
We are always happy to help you with any questions you may have. Don't hesitate to ask!
License
This repository, including all its contents, sub-projects, modules, and components, is licensed under AGPL-3.0 unless explicitly stated otherwise. Third-party libraries included in this repository may be subject to their own licenses.
Translations
- Arabic / العربية
- Armenian / Հայերեն
- Bengali / বাংলা
- Chinese / 中文
- Danish / Dansk
- English
- Farsi / فارسی
- Finnish / Suomi
- French / Français
- German / Deutsch
- Hebrew/ עברית
- Hindi / हिंदी
- Hungarian / Magyar
- Indonesian / Bahasa Indonesia
- Italian / Italiano
- Japanese / 日本語
- Korean / 한국어
- Malay / Bahasa Malaysia
- Malayalam / മലയാളം
- Polish / Polski
- Portuguese / Português
- Punjabi / ਪੰਜਾਬੀ
- Romanian / Română
- Russian / Русский
- Spanish / Español
- Swedish / Svenska
- Tamil / தமிழ்
- Telugu / తెలుగు
- Thai / ไทย
- Turkish / Türkçe
- Ukrainian / Українська
- Urdu / اردو
- Vietnamese / Tiếng Việt

