You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enables people who cannot create user accounts to share their work.
Feature request details
I’m attempting to teach a p5.js unit to my high school students so I asked my district’s IT department to allow for students to sign in on the editor and they wrote back:
“Their privacy policy says that they will provide PII data to 3rd parties, as well as web beaconing, collecting location and account information including domain, name, and credentials. We cannot allow the creation of accounts for students for these reasons.”
The main problem that creates is that they can't share a link to their work without logging in, which means they can't share the cool stuff they make with people (including me, for faster grading). It makes the experience a lot less relevant for them.
With something like strudel.cc the code in the workspace gets encoded into the URL and students can put that into a URL shortener to share with people. I wonder if p5.js could borrow that idea.
Thanks for raising this @MrClark313, and for the strudel.cc pointer.
I think URL embedding with localStorage is doable here, though there are a couple of things that matter for students which this might miss. Please correct me if any of my assumptions don't match reality.
As far as I understand, assets can't go in a URL. Images, sounds and fonts uploaded temporarily would be missing for whoever opens the link, so the share action should warn about that.
Long sketches (which might come up in assessments) will also make long URLs. Browsers handle them fine, but some URL shorteners and chat apps truncate them. One option could be standardizing on a URL shortener for the class that keeps the full link intact.
Another thing which can be done (though @ksen0 will need to confirm this given the ongoing backend work) is opening the share option to logged-out users as well, as a temporary anonymous share. This would also cover the assets, which can't go in the URL.
Clicking Share uploads the sketch with its assets and returns a short link, no account needed
The link expires after a set time, to keep spam and storage in check
Rate limiting and a size cap per share, since a link can still be misused until it expires
This is a bigger scoped change, so it could come as a follow-up. For this case specefically maybe we can go ahead with URL embedding.
@Vaivaswat2244 We have defined a format for URI-based sketch encoding in Processing 4 (See: SCHEMA.md). I think it would be a an exciting idea to adapt it for the p5.js editor.
A naive approach (NOT recommended) would be to use query parameters, for example:
This would work, but it has an important limitation: query parameters are included in the HTTP request, even when only the frontend interprets them. The maximum supported length therefore depends not only on the browser, but also on the server and any intermediaries such as a CDN or proxy. In practice, sufficiently long query strings may be rejected before the frontend ever sees them, for example with 414 URI Too Long or 431 Request Header Fields Too Large.
The alternative is to follow the strudel.cc approach and use # Fragment:
The fragment is not sent to the server when the page is requested. The web app can read it locally, avoiding server-side and intermediary URL-length limits.
I tested this with editor.p5js.org: a URL of about 30 KB using a query parameter returned 431, while an equivalent URL using a # fragment worked.
You can still keep named parameters and parse them with location.hash.slice(1). See MDN Web Docs for hash.
Arbitrary data such as images can also be encoded in the URI (for example using Base64url encoding) provided the resulting URI fits within the applicable length limits.
References
Documentation for the pde:// protocol in SCHEMA.md
I have used ChatGPT to help research and draft this message. I have independently verified the accuracy of the information and take responsibility for any errors or omissions.
I conjured a small proof of concept that reads a p5.js sketch from the URL fragment and runs it directly in the browser.
This is an intentionally very limited proof of concept for demonstration purpose only. Single file only, p5.js v1.111, no assets, extra files, or version picker. This is exclicitely NOT a full implementation of the pde:// protocol.
Do not use it for work or teaching.
The sketch is Base64url-encoded after #sketch=. When you open the link, the page decodes it client-side into a minimal editor.
changed the title [-]My students cannot create user accounts and cannot share links to their work.[/-][+]Sketches Should Shareable by URL[/+]on Oct 2, 2026
thanks for raising this. the student use-case really highlights how important frictionless sharing is.
encoding the sketch directly in the url is a really interesting direction.
in the meantime, one practical step that feels both high-impact and straightforward would be enabling download without requiring a login. rn the download path forces a save first, which in turn requires authentication. that gate doesn’t feel necessary for an open-source tool, students (and anyone else) should be able to take their current work with them without creating an account.
a related small improvement that would pair well with this: once people can download a zip, the editor currently has no clear way to re-open that zip via simple drag-and-drop. supporting “download → drag the zip back into the editor” would create a clean local workflow that works without accounts.
both of these feel like relatively simple changes that would meaningfully improve accessibility for classrooms and privacy-sensitive users.
After a discussion with @ksen0, I conjured a more minimal PoC (123 lines), still using Claude, but I read the code and made some manual tweaks (including adding comments).
The only somewhat "exotic" part is a small hand-rolled function to encode to Base64url (only because Uint8Array.toBase64/fromBase64landed in all major browsers in 2025).
This is so helpful thank you @SableRaf ! Compression was a great add. Some thoughts below. tl;dr I think this would be ready for someone to volunteer to draft a PR, using @SableRaf 's implementation as a starting point?
I played a bit with the limits of using images with this, because if we do ship this that will be the first question (or one of the first questions: if/when we'd support image uploads). For example here's one with a blurry image from data uri at 1.8kb total -github markdown correctly blocks larger thigns, so I was able to do a 80kb+ URL and store/use it but sharing it became a problem
2. I was experimenting to see if theoretically small images could potentially be used (carried in the URL but hidden from within the sketch - sketch authors should see a "filename" not the data string). Also client-side could be possible to downscale an image to make it usable, so have a very hard cap on any images (maximum 100x100), and no other assets (or this could ostensibly used for other assets but those are even larger to be useful.) Not to suggest that on Day 1 of a shareable url feature this should happen (certainly not), but pointing out that the length of a possible sketch is considerable; even if assets are very limited to start with, we could have a roadmap to enabling extremely limited image uploads, which would allow educators to teach asset management in the sketch without logging in. Teachers can also potentially prepare additional asset URLs to be able to teach image loading without having to do any of that.
Playing around with this, the main downside overall is that the URLs are long and brittle; they require careful and thoughtful use of markdown to not paste a wall of text, and messing up 1 character messes the sketch up. Sending in an email that introduce weird line-breaks without formatting a link will also ruin it. Though there's different content types that could be added to clipboard on copy:
// Copy button helper: puts markdown, HTML, and plain-text flavors on the
// clipboard at once, so pasting into editors/apps that support rich formats
// renders a proper link instead of a wall of base64url.
//
// NOTE: 'text/markdown' is NOT a commonly supported clipboard type.
// Browsers commonly support writing only text/plain, text/html, and image/png
// (https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/write), and
// passing an unsupported type can make the entire write() reject on some
// browsers. So we feature-detect with ClipboardItem.supports()
// (https://web.dev/blog/baseline-clipboard-item-supports) and fall back to
// plain text/HTML if it isn't available.
async function copyMarkdownLink(title, url) {
// Sanitize: title gets interpolated into both the markdown string and the
// HTML blob. Escape [ ] and ( ) in the title so they can't break the
// markdown link syntax, and HTML-escape it for the HTML flavor.
const safeTitle = String(title)
.replaceAll('\\', '\\\\')
.replace(/([[\\\]])/g, '\\$1');
const htmlTitle = safeTitle
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"');
const markdown = `[${safeTitle}](${url})`;
const html = `<a href="${url}">${htmlTitle}</a>`;
const types = {
'text/html': new Blob([html], { type: 'text/html' }),
'text/plain': new Blob([url], { type: 'text/plain' })
};
// Only add the markdown flavor if this browser actually accepts it,
// otherwise the whole clipboard write could throw NotAllowedError.
if (typeof ClipboardItem !== 'undefined'
&& ClipboardItem.supports?.('text/markdown')) {
types['text/markdown'] =
new Blob([markdown], { type: 'text/markdown' });
}
try {
await navigator.clipboard.write([new ClipboardItem(types)]);
} catch {
// Last-resort fallback: plain URL only. This one is supported everywhere
// (including Firefox, which has stricter MIME support for write()).
await navigator.clipboard.writeText(url);
}
}
@SableRaf the copy button in your original demo could maybe intervene to make sure the link looks good in most plausible cases and reduces likelihood of getting malformed through formatting?
Other thoughts I had:
In any case, shareable URL should be possible for sketches up for X size. IMO if we get this working it should be enabled by default on all sketches up to a certain hard-capped size, and beyond that the shareable URL should somehow go away? What's the least confusing way to explain this in the UI?
Prioritize and recommend a single-file standalone html download*. Right now we do a zip, which is less portable.
@SableRaf and I have discussed before EXIF/tEXt/iTXt encoding sketch data in an image "export" to be able to "import" it (like a pico 8 cartridge; or comfyui provenance), but thats also brittle if people screenshot to share or save it in some degraded way - no reason a user needs to know exactly how the picture is encoding the sketch. I find myself trying to think if there's some way of embedding information that's more robust. A QR code is also pretty fragile for such a dense example, and doesnt work on mobile (at least not for me):
So that's definitely not the answer, but although mobile doesn't read it, it would still be pretty machine legible even with some noticeable degradation (definitely more robust to being reuploaded than something with image file data) so one potential future extension (also absolutely not day 1) is some kind of robust cartridge format which could have a little sketch snapshot and be human-readable too. Again, I'm more thinking of obvious future extensions to help us shape the direction of this feature today, not any immediate feature. The URL sharing is a strong and useful stand-alone task.
*Note: +1 on enabling a download without requiring login but I believe that might already be the case in https://github.com/processing/p5.js-editor-op ? (Check op backend refactor branch) I'm not 100%.
I poked at this a bit on the current develop branch and found a few things that might be useful.
One thing that surprised me was that small assets don't seem too far off from working already. addCacheBustingToAssets() adds ?v=... to every file.url, including data: URLs, which breaks them. Skipping that just for data: URLs was enough to get image, font and audio assets loading locally in both Chromium and Firefox.
blob: URLs seem less useful here because the preview is on a separate origin and just gets a JSON copy of the files through the dispatcher.
I also tried the existing DirectoryContents shape for a multi-file project and it seems like a pretty natural fit. One small gotcha is the entry page: the preview uses the first .html file, so if the file order changes while rebuilding the project it can open the wrong page. I hit that with an assets/credits.html file taking precedence over index.html.
For a rough sense of X, I ran the p5.js-website examples through the same encoding. The full projects came out around 700 to 3,500 characters. GitHub's GFM Markdown API also stopped preserving the link once the URL went past 32,768 characters, so that might be a useful reference point when deciding where to draw the line.
The other thing I'd be a little careful with is only limiting the URL itself. In one test a fairly small Deflate fragment expanded to tens of MB once decoded, so it probably makes sense to cap the decoded size as well.
Thanks for all the feedback! We will open this up for work, based on the second sketch example that @SableRaf provided. For the first phase of this feature, we will only encode sketches without images.
Since this is a bit of a complex issue, anyone who would like to volunteer please briefly recap your understanding of the task when asking for assignment (and please dont make a PR before being assigned.) Thanks so much for understanding!
My understanding is that the approved first phase is client-only sharing for asset-free sketches: serialize the editor’s text-file project state, UTF-8 encode and DEFLATE-compress it using the browser APIs from SableRaf’s second proof of concept, Base64url-encode it in a versioned #sketch= fragment, and restore it entirely in the browser. This would require no server storage or API change, and images, audio, fonts, data URLs, and other assets would remain out of scope.
I would also validate a small explicit payload schema, reject assets and malformed file trees, cap the complete URL at 32,768 characters, and enforce a streamed decompressed-size limit—provisionally 1 MiB—to avoid compression bombs. I’d add focused tests for Unicode round trips, multiple text files, malformed/truncated input, unsupported versions, asset rejection, and both encoded and decoded size limits.
If this matches the intended scope, could you assign the issue to @Xenon010101? I will not open a PR before assignment.
Activity
Vaivaswat2244 commentedon Oct 1, 2026
Thanks for raising this @MrClark313, and for the strudel.cc pointer.
I think URL embedding with localStorage is doable here, though there are a couple of things that matter for students which this might miss. Please correct me if any of my assumptions don't match reality.
As far as I understand, assets can't go in a URL. Images, sounds and fonts uploaded temporarily would be missing for whoever opens the link, so the share action should warn about that.
Long sketches (which might come up in assessments) will also make long URLs. Browsers handle them fine, but some URL shorteners and chat apps truncate them. One option could be standardizing on a URL shortener for the class that keeps the full link intact.
Vaivaswat2244 commentedon Oct 1, 2026
Another thing which can be done (though @ksen0 will need to confirm this given the ongoing backend work) is opening the share option to logged-out users as well, as a temporary anonymous share. This would also cover the assets, which can't go in the URL.
This is a bigger scoped change, so it could come as a follow-up. For this case specefically maybe we can go ahead with URL embedding.
SableRaf commentedon Oct 2, 2026
@Vaivaswat2244 We have defined a format for URI-based sketch encoding in Processing 4 (See: SCHEMA.md). I think it would be a an exciting idea to adapt it for the p5.js editor.
A naive approach (NOT recommended) would be to use query parameters, for example:
This would work, but it has an important limitation: query parameters are included in the HTTP request, even when only the frontend interprets them. The maximum supported length therefore depends not only on the browser, but also on the server and any intermediaries such as a CDN or proxy. In practice, sufficiently long query strings may be rejected before the frontend ever sees them, for example with
414 URI Too Longor431 Request Header Fields Too Large.The alternative is to follow the strudel.cc approach and use
#Fragment:The fragment is not sent to the server when the page is requested. The web app can read it locally, avoiding server-side and intermediary URL-length limits.
I tested this with editor.p5js.org: a URL of about 30 KB using a query parameter returned 431, while an equivalent URL using a # fragment worked.
You can still keep named parameters and parse them with
location.hash.slice(1). See MDN Web Docs for hash.Arbitrary data such as images can also be encoded in the URI (for example using Base64url encoding) provided the resulting URI fits within the applicable length limits.
References
pde://protocol in SCHEMA.mdAI Disclosure
I have used ChatGPT to help research and draft this message. I have independently verified the accuracy of the information and take responsibility for any errors or omissions.
SableRaf commentedon Oct 2, 2026
I conjured a small proof of concept that reads a p5.js sketch from the URL fragment and runs it directly in the browser.
This is an intentionally very limited proof of concept for demonstration purpose only. Single file only, p5.js v1.111, no assets, extra files, or version picker. This is exclicitely NOT a full implementation of the
pde://protocol.Do not use it for work or teaching.
The sketch is Base64url-encoded after
#sketch=. When you open the link, the page decodes it client-side into a minimal editor.https://sableraf.github.io/p5-sketch-in-URL/#sketch=ZnVuY3Rpb24gc2V0dXAoKSB7CiAgY3JlYXRlQ2FudmFzKDQwMCwgNDAwKTsKfQoKZnVuY3Rpb24gZHJhdygpIHsKICBiYWNrZ3JvdW5kKDIyMCk7CiAgY2lyY2xlKHdpZHRoIC8gMiwgaGVpZ2h0IC8gMiwgMTAwKTsKICB0ZXh0KCJIZWxsbyBNckNsYXJrMzEzISIsIDEwLCAyMCk7CiAgdGV4dCgiSGVsbG8gVmFpdmFzd2F0ISIsIDEyMCwgNDApOwp9
AI Disclosure: This demo was generated using Opus 5.5. I made all the design decisions, and verified that everything works as described.
ksen0 commentedon Oct 2, 2026
Thanks for the research @SableRaf @Vaivaswat2244 ! @doradocodes @clairep94 and I will open this one for discussing approaches or draft PRs.
[-]My students cannot create user accounts and cannot share links to their work.[/-][+]Sketches Should Shareable by URL[/+]skyyash commentedon Oct 4, 2026
thanks for raising this. the student use-case really highlights how important frictionless sharing is.
encoding the sketch directly in the url is a really interesting direction.
in the meantime, one practical step that feels both high-impact and straightforward would be enabling download without requiring a login. rn the download path forces a save first, which in turn requires authentication. that gate doesn’t feel necessary for an open-source tool, students (and anyone else) should be able to take their current work with them without creating an account.
a related small improvement that would pair well with this: once people can download a zip, the editor currently has no clear way to re-open that zip via simple drag-and-drop. supporting “download → drag the zip back into the editor” would create a clean local workflow that works without accounts.
both of these feel like relatively simple changes that would meaningfully improve accessibility for classrooms and privacy-sensitive users.
SableRaf commentedon Oct 13, 2026
After a discussion with @ksen0, I conjured a more minimal PoC (123 lines), still using Claude, but I read the code and made some manual tweaks (including adding comments).
The only somewhat "exotic" part is a small hand-rolled function to encode to Base64url (only because
Uint8Array.toBase64/fromBase64landed in all major browsers in 2025).The URL updates continuously as you edit the sketch and it seems resistant to strange characters.
I also added compression using
CompressionStream/DecompressionStreamandDEFLATE. This is browser-native and widely available.This comment was written by hand 🤚😅
ksen0 commentedon Oct 13, 2026
This is so helpful thank you @SableRaf ! Compression was a great add. Some thoughts below. tl;dr I think this would be ready for someone to volunteer to draft a PR, using @SableRaf 's implementation as a starting point?
I played a bit with the limits of using images with this, because if we do ship this that will be the first question (or one of the first questions: if/when we'd support image uploads). For example here's one with a blurry image from data uri at 1.8kb total -github markdown correctly blocks larger thigns, so I was able to do a 80kb+ URL and store/use it but sharing it became a problem
2. I was experimenting to see if theoretically small images could potentially be used (carried in the URL but hidden from within the sketch - sketch authors should see a "filename" not the data string). Also client-side could be possible to downscale an image to make it usable, so have a very hard cap on any images (maximum 100x100), and no other assets (or this could ostensibly used for other assets but those are even larger to be useful.) Not to suggest that on Day 1 of a shareable url feature this should happen (certainly not), but pointing out that the length of a possible sketch is considerable; even if assets are very limited to start with, we could have a roadmap to enabling extremely limited image uploads, which would allow educators to teach asset management in the sketch without logging in. Teachers can also potentially prepare additional asset URLs to be able to teach image loading without having to do any of that.
Playing around with this, the main downside overall is that the URLs are long and brittle; they require careful and thoughtful use of markdown to not paste a wall of text, and messing up 1 character messes the sketch up. Sending in an email that introduce weird line-breaks without formatting a link will also ruin it. Though there's different content types that could be added to clipboard on copy:
https://web.dev/blog/baseline-clipboard-item-supports
(above was made with proton lumo i asked it to highlight browser support limitations. See also https://web.dev/blog/baseline-clipboard-item-supports)
@SableRaf the copy button in your original demo could maybe intervene to make sure the link looks good in most plausible cases and reduces likelihood of getting malformed through formatting?
Other thoughts I had:
So that's definitely not the answer, but although mobile doesn't read it, it would still be pretty machine legible even with some noticeable degradation (definitely more robust to being reuploaded than something with image file data) so one potential future extension (also absolutely not day 1) is some kind of robust cartridge format which could have a little sketch snapshot and be human-readable too. Again, I'm more thinking of obvious future extensions to help us shape the direction of this feature today, not any immediate feature. The URL sharing is a strong and useful stand-alone task.
*Note: +1 on enabling a download without requiring login but I believe that might already be the case in https://github.com/processing/p5.js-editor-op ? (Check
op backend refactorbranch) I'm not 100%.bhabishnu commentedon Oct 15, 2026
I poked at this a bit on the current
developbranch and found a few things that might be useful.One thing that surprised me was that small assets don't seem too far off from working already.
addCacheBustingToAssets()adds?v=...to everyfile.url, includingdata:URLs, which breaks them. Skipping that just fordata:URLs was enough to get image, font and audio assets loading locally in both Chromium and Firefox.blob:URLs seem less useful here because the preview is on a separate origin and just gets a JSON copy of the files through the dispatcher.I also tried the existing
DirectoryContentsshape for a multi-file project and it seems like a pretty natural fit. One small gotcha is the entry page: the preview uses the first.htmlfile, so if the file order changes while rebuilding the project it can open the wrong page. I hit that with anassets/credits.htmlfile taking precedence overindex.html.For a rough sense of X, I ran the p5.js-website examples through the same encoding. The full projects came out around 700 to 3,500 characters. GitHub's GFM Markdown API also stopped preserving the link once the URL went past 32,768 characters, so that might be a useful reference point when deciding where to draw the line.
The other thing I'd be a little careful with is only limiting the URL itself. In one test a fairly small Deflate fragment expanded to tens of MB once decoded, so it probably makes sense to cap the decoded size as well.
doradocodes commentedon Oct 16, 2026
Thanks for all the feedback! We will open this up for work, based on the second sketch example that @SableRaf provided. For the first phase of this feature, we will only encode sketches without images.
ksen0 commentedon Oct 16, 2026
Since this is a bit of a complex issue, anyone who would like to volunteer please briefly recap your understanding of the task when asking for assignment (and please dont make a PR before being assigned.) Thanks so much for understanding!
Xenon010101 commentedon Oct 18, 2026
Hi! I’d like to volunteer for #4331.
My understanding is that the approved first phase is client-only sharing for asset-free sketches: serialize the editor’s text-file project state, UTF-8 encode and DEFLATE-compress it using the browser APIs from SableRaf’s second proof of concept, Base64url-encode it in a versioned
#sketch=fragment, and restore it entirely in the browser. This would require no server storage or API change, and images, audio, fonts, data URLs, and other assets would remain out of scope.I would also validate a small explicit payload schema, reject assets and malformed file trees, cap the complete URL at 32,768 characters, and enforce a streamed decompressed-size limit—provisionally 1 MiB—to avoid compression bombs. I’d add focused tests for Unicode round trips, multiple text files, malformed/truncated input, unsupported versions, asset rejection, and both encoded and decoded size limits.
If this matches the intended scope, could you assign the issue to @Xenon010101? I will not open a PR before assignment.