* fix: show the new folder's row in the dashboard before mkdir answers Both New Folder paths in the dashboard Files tab awaited mkdir before drawing anything, so on a slow connection the button appeared to do nothing for seconds. The toolbar path then did a full renderDirectory on top of that -- a second round-trip, and with the default eventual consistency the new folder could miss the listing entirely, leaving the rename editor unopened. Both now go through one createFolderInstant(), which renders the row first: a locally predicted name (mirroring the backend's " (N)" dedupe convention), a temporary uid, and the name editor already open. mkdir is still asked for the plain "New Folder" path with rename: true, so the server keeps owning deduplication; the prediction is only what we draw in the meantime, and the row corrects itself if the two disagree. On failure the row is withdrawn and the error is shown rather than swallowed. Renaming is the next thing the user does and it needs the real uid, so rename() awaits the create promise parked on the row. Everything else that acts on the item -- open, menus, drag -- sits out while the row is pending. mkdir's item.added comes back to the originating client (the event carries no original_client_socket_id) and cannot match a temporary uid, so _creatingItem still suppresses it, now as a counter: as a flag, one create finishing uncovered another still in flight. Two things found on the way: - directory_depth_limit_exceeded had no translation key, so that alert (including the pre-existing desktop create_folder path) rendered the raw slug. - The empty-directory notice is now restorable without refetching, since a withdrawn create has to put it back. It carries its own class because the loading overlay shares the same container. Verified end to end against a dev backend with mkdir slowed to 3s: toolbar and context-menu paths, rename and Escape before the response, two overlapping creates, and a rejected mkdir. * fix: don't draw the instant new-folder row while a listing is rebuilding renderDirectory() clears .files before its readdir resolves, so a row drawn during a load survives the clear and is left behind in whatever directory the load lands on. Clicking the new-folder button while a folder is still opening produced a row for `<old dir>/New Folder` sitting in the new directory's listing, with the rename editor open on it — clicking it navigated elsewhere and renaming it renamed a folder the user wasn't looking at. Drop the click while a rebuild is in flight, the same way renderDirectory already drops navigation clicks that arrive while it renders. * fix: stop drops onto a not-yet-created folder row from mangling files A row drawn ahead of its mkdir carries a predicted path, but it was still registered as a live drop target. Dropping a file on it called move_items() with a destination that does not exist yet, and move treats a non-existent destination as a rename target — so the dragged file was silently renamed to "New Folder" instead of moving into the folder. Reproduced against a slow mkdir: victim.txt became a 5-byte file named "New Folder". Sit the row out of the jQuery UI droppable (drop and the spring-load hover) until the real fsentry lands, matching the guards already on opening it, its menus and dragging it. The native-file dragster drop gets the same guard: it uploads into the same predicted path.
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

