#+TITLE: Sprites #+AUTHOR: melgray@gmail.com * ...of the text variety This site is hosted on [[https://fly.io][fly.io]] It's pretty ok. I have some gripes around the ux for it, but the [[https://fly.io/docs/flyctl/][cli tooling]] tends to work and the product overall requires less insanity to get simple things up and running. The people there have somewhat recently launched a project called [[https://sprites.dev/][sprites.dev]] It's sold as stateful sandboxes to safely execute code. Code submitted by users or ai or any other type of miscreant that you wouldn't trust to execute code on a machine you paid money for or invested time into setting up. Behind the scenes it appears to be [[https://github.com/firecracker-microvm/firecracker][firecracker vms]] with a simple http api on top for interacting with the vm's internals. ** org-mode source blocks [[https://orgmode.org][org-mode]] allows [[https://orgmode.org/manual/Working-with-Source-Code.html][working with source code inside special tags]]. When running in emacs you can create a source block, write some code in it, and then execute it in the document. The code in the block runs on your machine and any output it generated can be rendered inside the document based you are editing. If you are familiar with [[https://developer.apple.com/swift-playground/][swift playgrounds]] or [[https://jupyter.org/][jupyter notebooks]] this won't seem foreign to you. Since [[https://orgmode.dev][orgmode.dev]] is a web app and not actually running in emacs this presents a challenge that I hope [[https://sprites.dev][sprites.dev]] can neatly solve. The backend of this site will create a [[https://docs.sprites.dev/working-with-sprites/][sprite]] per user that you can use to execute code for any documents you create on the platform. ** Examples Below are some example snippets showing some simple things that can be done. If you're logged into [[https://orgmode.dev][orgmode.dev]], you'll see a =Run= button that will execute the code in the block It looks like this: #+ATTR_HTML: :width 700px [[/api/media/88d359d9-104c-42d9-a6ad-a99d0cbf6500]] If you want to see the source of this document, just add ~.org~ onto the end of the url. Or [[https://orgmode.dev/d/ee34fc11-f1aa-4cff-85b3-23cd5817baec.org][just click this]] if you don't wanna do that. *** Python #+begin_src python print("hello sprites") #+end_src #+RESULTS: : hello sprites *** Ruby #+begin_src ruby print "hello orgmode.dev" #+end_src #+RESULTS: : hello orgmode.dev *** Bash #+begin_src bash ls -lah #+end_src #+RESULTS: : total 48K : drwxr-xr-x 1 sprite sprite 4.0K Feb 19 18:12 . : drwxr-xr-x 1 sprite sprite 4.0K Feb 19 18:12 .. : -rw-r--r-- 1 sprite sprite 750 Feb 19 17:57 .bashrc : drwxr-xr-x 3 sprite sprite 4.0K Feb 19 17:57 .claude : drwxr-xr-x 3 sprite sprite 4.0K Feb 19 17:57 .codex : drwxr-xr-x 4 sprite sprite 4.0K Feb 19 17:57 .config : drwxr-xr-x 4 sprite sprite 4.0K Feb 19 17:57 .cursor : drwxr-xr-x 3 sprite sprite 4.0K Feb 19 17:57 .gemini : -rw-r--r-- 1 sprite sprite 89 Feb 19 17:57 .gitconfig : drwxr-xr-x 6 sprite sprite 4.0K Feb 19 18:11 .local : -rw-r--r-- 1 sprite sprite 0 Feb 19 17:58 .sudo_as_admin_successful : -rw-r--r-- 1 sprite sprite 383 Feb 19 17:57 .tcshrc : -rw-r--r-- 1 sprite sprite 1.1K Feb 19 17:57 .zshrc * Beyond "Hello World" The above are pretty simple examples of what this site can do. To summarize we can: - Create source blocks using snippets by typing ~ 2: break row += " .:-=+*#%@"[min(i, 9)] print(row) #+END_SRC #+RESULTS: : ...::::::::::::-----==*@@@----:::............ : ...::::::::::::-----==+#@@*=----:::........... : ...::::::::::::-----==+%@@@%+==--::::.......... : ..:::::::::::------=++*@@@@@*===--::::......... : .:::::::::::-----=++**#@@@@@#*++=--::::........ : .:::::::::::----==+@@%@@@@@@@@@#*#+-:::::....... : .::::::::::---===+*@@@@@@@@@@@@@@@@=-::::....... : :::::::::--=====++#@@@@@@@@@@@@@@@#=-:::::...... : .:::::::--======++#@@@@@@@@@@@@@@@@*+--::::...... : .:::::--=+@*******%@@@@@@@@@@@@@@@@%#--::::...... : :::----==+@@@@@%#%@@@@@@@@@@@@@@@@@@#=-:::::..... : :-----===*%@@@@@@@@@@@@@@@@@@@@@@@@@*=-:::::..... : :----===+*@@@@@@@@@@@@@@@@@@@@@@@@@@+=--::::..... : ----=++*@%@@@@@@@@@@@@@@@@@@@@@@@@@@+=--::::..... : ===*++*%@@@@@@@@@@@@@@@@@@@@@@@@@@@*==--::::..... : @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%*==--:::::.... : ===*++*%@@@@@@@@@@@@@@@@@@@@@@@@@@@*==--::::..... : ----=++*@%@@@@@@@@@@@@@@@@@@@@@@@@@@+=--::::..... : :----===+*@@@@@@@@@@@@@@@@@@@@@@@@@@+=--::::..... : :-----===*%@@@@@@@@@@@@@@@@@@@@@@@@@*=-:::::..... : :::----==+@@@@@%#%@@@@@@@@@@@@@@@@@@#=-:::::..... : .:::::--=+@*******%@@@@@@@@@@@@@@@@%#--::::...... : .:::::::--======++#@@@@@@@@@@@@@@@@*+--::::...... : :::::::::--=====++#@@@@@@@@@@@@@@@#=-:::::...... : .::::::::::---===+*@@@@@@@@@@@@@@@@=-::::....... : .:::::::::::----==+@@%@@@@@@@@@#*#+-:::::....... : .:::::::::::-----=++**#@@@@@#*++=--::::........ : ..:::::::::::------=++*@@@@@*===--::::......... : ...::::::::::::-----==+%@@@%+==--::::.......... : ...::::::::::::-----==+#@@*=----:::........... ** ASCII Bar Chart (Python) #+BEGIN_SRC python :results output data = {"Python": 85, "Rust": 72, "JS": 68, "Ruby": 45, "Bash": 30} max_val = max(data.values()) for lang, val in sorted(data.items(), key=lambda x: -x[1]): bar = "█" * int(val / max_val * 4) print(f"{lang:>8} │{bar} {val}") #+END_SRC #+RESULTS: : Python │████ 85 : Rust │███ 72 : JS │███ 68 : Ruby │██ 45 : Bash │█ 30 ** System Introspection (Bash) #+BEGIN_SRC bash :results output echo "=== Sprite Environment ===" uname -a echo "---" cat /etc/os-release 2>/dev/null | head -3 echo "---" echo "CPU: $(nproc) cores" echo "Memory: $(free -h 2>/dev/null | awk '/Mem/{print $2}' || echo 'N/A')" echo "Disk: $(df -h / | awk 'NR==2{print $4}') free" #+END_SRC #+RESULTS: : === Sprite Environment === : Linux org-editor-7aea4c5f-d3cf-4ebe-be5b-0559bedf38c3 6.12.47-fly #1 SMP PREEMPT_DYNAMIC Fri Feb 13 00:38:38 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux : --- : PRETTY_NAME="Ubuntu 25.04" : NAME="Ubuntu" : VERSION_ID="25.04" : --- : CPU: 8 cores : Memory: 15Gi : Disk: 99G free * Better source block parsing ** :exports code (should show code only, no results div) #+BEGIN_SRC python :exports code print("you should see this code but no results area") #+END_SRC #+RESULTS: : you should see this code but no results area ** :exports results (should hide code, show only results after Run) #+BEGIN_SRC python :exports results print("the code is hidden, but you can still run me") #+END_SRC #+RESULTS: : ** :exports none (should be completely invisible) #+BEGIN_SRC python :exports none print("you should not see this at all") #+END_SRC ** :exports both (default, same as no arg) #+BEGIN_SRC python :exports both print("code AND results visible") #+END_SRC #+RESULTS: : code AND results visible ** :results output (default — escaped, pre-wrapped) #+BEGIN_SRC python :results output print("this should be escaped") #+END_SRC #+RESULTS: : this should be escaped ** :results output html (raw HTML rendering) #+BEGIN_SRC python :results output html print("

Hello from Python!

") print("") #+END_SRC #+RESULTS: :

Hello from Python!

: ** :results output html (SVG) #+BEGIN_SRC python :results output html print('') print(' ') print(' SVG from Python') print('') #+END_SRC #+RESULTS: : : : SVG from Python : ** :results output table (TSV → table rendering) #+BEGIN_SRC python :results output table print("Name\tAge\tCity") print("Alice\t30\tSeattle") print("Bob\t25\tPortland") print("Carol\t35\tDenver") #+END_SRC #+RESULTS: : Name Age City : Alice 30 Seattle : Bob 25 Portland : Carol 35 Denver ** Python value (should print 3, no print() needed) #+BEGIN_SRC python :results value 1 + 2 #+END_SRC #+RESULTS: : 3 ** Python value with statements #+BEGIN_SRC python :results value xs = [1, 2, 3, 4, 5] sum(x**2 for x in xs) #+END_SRC #+RESULTS: : 55 ** JavaScript value #+BEGIN_SRC js :results value [1, 2, 3].map(x => x * 10) #+END_SRC #+RESULTS: : [ : 10, : 20, : 30 : ] ** Ruby value #+BEGIN_SRC ruby :results value (1..5).map { |n| n ** 2 } #+END_SRC #+RESULTS: : 1 : 4 : 9 : 16 : 25 ** Named data source #+NAME: greeting #+BEGIN_SRC python print("Hello, World!") #+END_SRC #+RESULTS: : Hello, World! ** Block that references the named block #+BEGIN_SRC python :var msg=greeting print(f"Received: {msg}") print(f"Length: {len(msg.strip())}") #+END_SRC #+RESULTS: : Received: Hello, World! : Length: 13 ** Chained computation #+NAME: numbers #+BEGIN_SRC python print("1,2,3,4,5") #+END_SRC #+RESULTS: : 1,2,3,4,5 #+BEGIN_SRC python :var data=numbers nums = [int(x) for x in data.strip().split(",")] print(f"Sum: {sum(nums)}") print(f"Mean: {sum(nums)/len(nums)}") #+END_SRC #+RESULTS: : Sum: 15 : Mean: 3.0 ** Value + HTML (return an SVG as value) #+BEGIN_SRC js :results value html ` ` #+END_SRC #+RESULTS: : : : : : ** Static results with :results html #+BEGIN_SRC python :results output html print("rendered as HTML") #+END_SRC #+RESULTS: : rendered as HTML