{
"$type": "site.standard.document",
"content": "---\ntitle: \"The road to COMP4020: safety, YOLO and the open web\"\ndescription: \"Fly Sprites as lightweight, snapshotable VMs for student coding---safe enough\n for YOLO mode, live on the open web by default.\"\ntags: [comp4020]\n---\n\n:::tip\n\nThis post is part of a series I'm writing as I develop\n[COMP4020: Agentic Coding Studio](/blog/2025/12/19/comp4020-rapid-prototyping-for-the-web/).\nSee [all posts in the series](/blog/tag/comp4020/).\n\n:::\n\nRunning terminal agents in \"YOLO mode\", where they can run arbitrary commands\n(and delete all your data, or worse) is the sort of thing which you _know_ you\nshouldn't do. However, manually approving all the \"can I use this tool\" or \"can\nI edit this file\" requests becomes such a PITA that many developers (myself\nincluded, alongside\n[many others I respect](https://lucumr.pocoo.org/2025/6/12/agentic-coding/)) are\ndoing it anyway. Honestly, I have all my files backed up in a couple of\ndifferent places, and while I have semi-important files on my machine I don't\nhave the nuclear codes or anything. Most of all, Claude hasn't let me down yet\n(famous last words, I guess).\n\nHowever, that's me---thinking about teaching my students to use these tools\neffectively is another matter. If I say \"use YOLO mode\" then I feel some\nresponsibility if it goes pear-shaped for them. So I'd rather they be safer, but\nmy career in human factors research also tells me that you've gotta be pragmatic\nabout what people are actually going to do.\n\nThere are a few emerging tools for squaring the \"run wild, but don't break my\nthings\" circle. [Devcontainers](https://containers.dev/) is one of the big ones.\nHowever, [Fly.io](https://fly.io) recently released\n[Sprites](https://sprites.dev/), which are lightweight (i.e. fast startup) VMs\nwith first class snapshot-and-restore functionality, and which automatically\nspring to life on the open web with a URL and everything. There's lots you\n_could_ do with this sort of setup, but I'm particularly interested in them for\nsupporting collaborative student work in COMP4020.\n\n<svg width=\"100%\" viewBox=\"0 0 500 210\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Left: local machine (dashed = porous/risky) -->\n <rect x=\"20\" y=\"15\" width=\"200\" height=\"140\" rx=\"10\" fill=\"none\" stroke=\"#f87171\" stroke-width=\"2\" stroke-dasharray=\"6 3\"/>\n <text x=\"120\" y=\"42\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"#f87171\">your machine</text>\n <line x1=\"45\" y1=\"50\" x2=\"195\" y2=\"50\" stroke=\"#f87171\" stroke-width=\"0.5\" stroke-opacity=\"0.4\"/>\n <text x=\"120\" y=\"72\" text-anchor=\"middle\" font-size=\"12\" fill=\"#e2e8f0\">Claude Code</text>\n <text x=\"120\" y=\"93\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">personal files & SSH keys</text>\n <text x=\"120\" y=\"110\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">system packages</text>\n <text x=\"120\" y=\"127\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">everything you care about</text>\n <text x=\"120\" y=\"185\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"#f87171\">YOLO = risky</text>\n <!-- Divider -->\n <text x=\"250\" y=\"92\" text-anchor=\"middle\" font-size=\"15\" font-weight=\"700\" fill=\"#64748b\">vs</text>\n <!-- Right: sprite (solid = contained/safe) -->\n <rect x=\"280\" y=\"15\" width=\"200\" height=\"140\" rx=\"10\" fill=\"none\" stroke=\"#86efac\" stroke-width=\"2\"/>\n <text x=\"380\" y=\"42\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"#86efac\">sprite</text>\n <line x1=\"305\" y1=\"50\" x2=\"455\" y2=\"50\" stroke=\"#86efac\" stroke-width=\"0.5\" stroke-opacity=\"0.4\"/>\n <text x=\"380\" y=\"72\" text-anchor=\"middle\" font-size=\"12\" fill=\"#e2e8f0\">Claude Code</text>\n <text x=\"380\" y=\"93\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">this week's prototype</text>\n <text x=\"380\" y=\"110\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">nothing else</text>\n <text x=\"380\" y=\"127\" text-anchor=\"middle\" font-size=\"11\" fill=\"#94a3b8\">snapshotable & disposable</text>\n <text x=\"380\" y=\"185\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"#86efac\">YOLO = go for it</text>\n</svg>\n\nThe basic idea would be that for each week's\n[prototype and studio session](/blog/2026/02/20/comp4020-the-core-mechanic/) the\nstudents would do their work in a (fresh) sprite. They could ssh in and do the\ndev work, and \"serving\" it on the web is as simple as running the dev server,\nfinding out what the sprite's URL is and then sharing that with their\nclassmates. More than that, for collaborative work, students could give each\nother access to their sprite. That's safe, because it's got no data/files on it\nexcept for that week's prototype. And because it's checkpointable even if one\nstudent did bork another student's prototype, they could just roll back to a\nprevious snapshot and keep going[^git-rollback].\n\n<svg width=\"100%\" viewBox=\"0 0 500 280\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <marker id=\"arr2\" markerWidth=\"8\" markerHeight=\"6\" refX=\"6\" refY=\"3\" orient=\"auto\">\n <path d=\"M 0 0 L 8 3 L 0 6 Z\" fill=\"#94a3b8\"/>\n </marker>\n <marker id=\"arr2-teal\" markerWidth=\"8\" markerHeight=\"6\" refX=\"6\" refY=\"3\" orient=\"auto\">\n <path d=\"M 0 0 L 8 3 L 0 6 Z\" fill=\"#80cbc4\"/>\n </marker>\n </defs>\n <!-- Student dot -->\n <circle cx=\"35\" cy=\"80\" r=\"8\" fill=\"#ffab91\"/>\n <text x=\"35\" y=\"104\" text-anchor=\"middle\" font-size=\"10\" fill=\"#ffab91\">you</text>\n <!-- Arrow to sprite -->\n <line x1=\"55\" y1=\"80\" x2=\"85\" y2=\"80\" stroke=\"#94a3b8\" stroke-width=\"1.5\" marker-end=\"url(#arr2)\"/>\n <!-- Sprite box -->\n <rect x=\"93\" y=\"20\" width=\"215\" height=\"150\" rx=\"10\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"2\"/>\n <text x=\"200\" y=\"46\" text-anchor=\"middle\" font-size=\"13\" font-weight=\"600\" fill=\"#a5b4fc\">fresh sprite</text>\n <line x1=\"113\" y1=\"55\" x2=\"288\" y2=\"55\" stroke=\"#a5b4fc\" stroke-width=\"0.5\" stroke-opacity=\"0.4\"/>\n <text x=\"200\" y=\"78\" text-anchor=\"middle\" font-size=\"12\" fill=\"#e2e8f0\">Claude Code (YOLO mode)</text>\n <text x=\"200\" y=\"100\" text-anchor=\"middle\" font-size=\"14\" fill=\"#64748b\">↕</text>\n <text x=\"200\" y=\"120\" text-anchor=\"middle\" font-size=\"12\" fill=\"#e2e8f0\">dev server</text>\n <text x=\"200\" y=\"142\" text-anchor=\"middle\" font-size=\"11\" fill=\"#80cbc4\">abc123.fly.dev</text>\n <!-- Arrow to studio session -->\n <line x1=\"313\" y1=\"95\" x2=\"345\" y2=\"95\" stroke=\"#94a3b8\" stroke-width=\"1.5\" marker-end=\"url(#arr2)\"/>\n <!-- Studio session box -->\n <rect x=\"353\" y=\"20\" width=\"132\" height=\"150\" rx=\"10\" fill=\"none\" stroke=\"#ffab91\" stroke-width=\"2\"/>\n <text x=\"419\" y=\"46\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"600\" fill=\"#ffab91\">studio session</text>\n <line x1=\"368\" y1=\"55\" x2=\"470\" y2=\"55\" stroke=\"#ffab91\" stroke-width=\"0.5\" stroke-opacity=\"0.4\"/>\n <!-- People dots -->\n <circle cx=\"378\" cy=\"78\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"393\" cy=\"73\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"408\" cy=\"78\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"423\" cy=\"73\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"438\" cy=\"78\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"453\" cy=\"73\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"385\" cy=\"96\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"400\" cy=\"91\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"415\" cy=\"96\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"430\" cy=\"91\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"445\" cy=\"96\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"460\" cy=\"91\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"392\" cy=\"112\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"407\" cy=\"117\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"422\" cy=\"112\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"437\" cy=\"117\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"452\" cy=\"112\" r=\"4\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <!-- Tutor (slightly larger, different opacity) -->\n <circle cx=\"419\" cy=\"138\" r=\"5\" fill=\"#ffab91\" fill-opacity=\"0.9\"/>\n <text x=\"419\" y=\"155\" text-anchor=\"middle\" font-size=\"9\" fill=\"#ffab91\">~20 + tutor</text>\n <!-- GitLab box at bottom -->\n <rect x=\"130\" y=\"220\" width=\"200\" height=\"42\" rx=\"8\" fill=\"none\" stroke=\"#80cbc4\" stroke-width=\"2\"/>\n <text x=\"230\" y=\"246\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"600\" fill=\"#80cbc4\">class GitLab server</text>\n <!-- Arrow from sprite down to GitLab (dashed = continuous flow) -->\n <path d=\"M 200 175 L 200 215\" fill=\"none\" stroke=\"#80cbc4\" stroke-width=\"1.5\" stroke-dasharray=\"4 2\" marker-end=\"url(#arr2-teal)\"/>\n <text x=\"228\" y=\"200\" font-size=\"10\" fill=\"#80cbc4\">git push</text>\n</svg>\n\n[^git-rollback]:\n I know that good git hygiene makes for easy rollbacks as well, and students\n _will_ be committing and pushing their work to git as well. But this is\n still easier than setting up full push-to-deploy pipelines for arbitrary\n tech stacks, not to mention if the \"broken things\" are outside of the\n git-controlled source, e.g. installation/removal of OS packages.\n\nMarking, too, would be as simple as snapshotting at the right time (or perhaps\nseveral snapshots---I think that marking the progression of these prototypes is\ngoing to be more important than marking the finished prototype). And I really\nlike Fly's commitment to fast-starting, on the web by default infra. I've been a\nhappy user of their platform for a few years now and these sprites seem like a\nreally interesting idea for teaching programming.\n\n<svg width=\"100%\" viewBox=\"0 0 500 240\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <marker id=\"arr3\" markerWidth=\"8\" markerHeight=\"6\" refX=\"6\" refY=\"3\" orient=\"auto\">\n <path d=\"M 0 0 L 8 3 L 0 6 Z\" fill=\"#94a3b8\"/>\n </marker>\n </defs>\n <!-- GitLab -->\n <rect x=\"15\" y=\"50\" width=\"120\" height=\"120\" rx=\"10\" fill=\"none\" stroke=\"#80cbc4\" stroke-width=\"2\"/>\n <text x=\"75\" y=\"78\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"600\" fill=\"#80cbc4\">GitLab</text>\n <line x1=\"30\" y1=\"86\" x2=\"120\" y2=\"86\" stroke=\"#80cbc4\" stroke-width=\"0.5\" stroke-opacity=\"0.4\"/>\n <text x=\"75\" y=\"108\" text-anchor=\"middle\" font-size=\"10\" fill=\"#94a3b8\">all students'</text>\n <text x=\"75\" y=\"122\" text-anchor=\"middle\" font-size=\"10\" fill=\"#94a3b8\">source code</text>\n <text x=\"75\" y=\"136\" text-anchor=\"middle\" font-size=\"10\" fill=\"#94a3b8\">& history</text>\n <!-- Arrow GitLab → Sprites -->\n <line x1=\"140\" y1=\"110\" x2=\"172\" y2=\"110\" stroke=\"#94a3b8\" stroke-width=\"1.5\" marker-end=\"url(#arr3)\"/>\n <!-- Sprite grid -->\n <rect x=\"180\" y=\"30\" width=\"150\" height=\"180\" rx=\"10\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1.5\" stroke-dasharray=\"4 2\"/>\n <text x=\"255\" y=\"52\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"600\" fill=\"#a5b4fc\">persisted sprites</text>\n <!-- Mini sprites (2x3 grid) -->\n <rect x=\"195\" y=\"64\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"233\" cy=\"75\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"216\" y=\"86\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <rect x=\"260\" y=\"64\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"298\" cy=\"75\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"281\" y=\"86\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <rect x=\"195\" y=\"102\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"233\" cy=\"113\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"216\" y=\"124\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <rect x=\"260\" y=\"102\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"298\" cy=\"113\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"281\" y=\"124\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <rect x=\"195\" y=\"140\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"233\" cy=\"151\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"216\" y=\"162\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <rect x=\"260\" y=\"140\" width=\"55\" height=\"30\" rx=\"5\" fill=\"none\" stroke=\"#a5b4fc\" stroke-width=\"1\"/>\n <circle cx=\"298\" cy=\"151\" r=\"3\" fill=\"#86efac\"/>\n <text x=\"281\" y=\"162\" text-anchor=\"middle\" font-size=\"7\" fill=\"#94a3b8\">.fly.dev</text>\n <!-- Arrow Sprites → Students -->\n <line x1=\"335\" y1=\"110\" x2=\"367\" y2=\"110\" stroke=\"#94a3b8\" stroke-width=\"1.5\" marker-end=\"url(#arr3)\"/>\n <!-- Student cluster -->\n <text x=\"430\" y=\"40\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"600\" fill=\"#ffab91\">the whole class</text>\n <!-- Dot cluster (~30 dots in a rough oval suggesting ~200 students) -->\n <circle cx=\"400\" cy=\"62\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"415\" cy=\"58\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"430\" cy=\"62\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"445\" cy=\"58\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"460\" cy=\"62\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"393\" cy=\"78\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"408\" cy=\"74\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"423\" cy=\"78\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"438\" cy=\"74\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"453\" cy=\"78\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"468\" cy=\"74\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"390\" cy=\"94\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"405\" cy=\"90\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"420\" cy=\"94\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"435\" cy=\"90\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"450\" cy=\"94\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"465\" cy=\"90\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"388\" cy=\"110\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"403\" cy=\"106\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"418\" cy=\"110\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"433\" cy=\"106\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"448\" cy=\"110\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"463\" cy=\"106\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.8\"/>\n <circle cx=\"393\" cy=\"126\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"408\" cy=\"122\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"423\" cy=\"126\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"438\" cy=\"122\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"453\" cy=\"126\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"468\" cy=\"122\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.7\"/>\n <circle cx=\"400\" cy=\"142\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"415\" cy=\"138\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"430\" cy=\"142\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"445\" cy=\"138\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"460\" cy=\"142\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.6\"/>\n <circle cx=\"405\" cy=\"156\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.5\"/>\n <circle cx=\"420\" cy=\"158\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.5\"/>\n <circle cx=\"435\" cy=\"156\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.5\"/>\n <circle cx=\"450\" cy=\"158\" r=\"3\" fill=\"#ffab91\" fill-opacity=\"0.5\"/>\n <text x=\"255\" y=\"228\" text-anchor=\"middle\" font-size=\"10\" fill=\"#ffab91\">~200 students browse any prototype</text>\n</svg>\n\nNone of this works without some unglamorous plumbing underneath. Each week's\nprovocation---the starting point for that week's prototype---is a template git\nrepo. Every student forks it and pushes their work, with the last push before\nthe deadline counting as their submission. This keeps things simple and\nauditable, and it means CI can check some of the invariants automatically: does\nthe build step exit cleanly, does the served site return `200 OK` on the\nrequired routes, are the process reflection `.md` files present in the repo,\nthat sort of thing.\n\nI've already got tooling that can batch clone and run tests across all student\nrepos for a given class---plus a \"badger\" script that I run a few days before\nthe deadline to send a courtesy email to anyone who hasn't forked the template\nyet, gently suggesting they get started. Extending all of this to also provision\nand snapshot sprites per student is the next step, but the bones are there.\n",
"createdAt": "2026-05-13T23:14:39.385Z",
"description": "Fly Sprites as lightweight, snapshotable VMs for student coding---safe enough for YOLO mode, live on the open web by default.",
"path": "/blog/2026/03/05/comp4020-safety-yolo-and-the-open-web",
"publishedAt": "2026-03-05T00:00:00.000Z",
"site": "at://did:plc:tevykrhi4kibtsipzci76d76/site.standard.publication/self",
"tags": [
"comp4020"
],
"textContent": "Fly Sprites as lightweight, snapshotable VMs for student coding---safe enough for YOLO mode, live on the open web by default.",
"title": "The road to COMP4020: safety, YOLO and the open web"
}