What I Learned Building A Code Playground

Hatem Hosny

Agenda

  • Project
  • Challenges
    • Design decisions and work-arounds
    • Web Standards and APIs
  • Conclusions

Disclosures

I'm a doctor!

... and the author of LiveCodes

LiveCodes

A Code Playground That Just Works!

https://livecodes.io

Language Support

Features

Embedded Playgrounds

  • Can be embedded in any web page
  • Powerful SDK
    • JavaScript/TypeScript
    • React
    • Vue
    • Svelte
  • Communicate with embedded playgrounds

Demo

Client-Side!

  • Yes, all compilers run in the browser!
  • No server rounds
  • No servers to configure (or pay for!)
  • All projects are private by default
  • Free with unlimited usage
  • Can be self-hosted on any static file server

Free and Open-Source

  • MIT License
  • No limits for use
  • No ads
  • No accounts required

 

https://github.com/live-codes/livecodes

Challenges

Running 80+ Languages

Definitions

  • Language
  • Compiler
  • Runtime

Running 80+ Languages

  • Options:
    • Servers
    • WebContainers/Nodebox
    • Use the platform!
      • JavaScript
      • WebAssembly (Wasm)
node_modules

Languages

          graph LR
              A[/Language A\n`compiles to JS`/]
              B{{Language B\n`JS runtime`}}
              C>Language C\n`Wasm runtime`]
        

Create Compilers

          graph LR
              comp[Create Compiler] -- Config --> A[/Language A\n`compiles to JS`/]
              comp -- Config --> B{{Language B\n`JS runtime`}}
              comp -- Config --> C>Language C\n`Wasm runtime`]
              A -- "⌛" --> fnA(fn A)
              fnA -- code --> Script
              B -- "⌛" --> fnB(fn B)
              fnB -- code --> Script
              C -- "⌛" --> fnC(fn C)
              fnC -- code --> Script
        

Demo: Ruby

Demo: PHP

Importing npm Modules

Importing npm Modules

Importing npm Modules

import {v4} from "uuid"

Uncaught TypeError: Failed to resolve module specifier "uuid". Relative references must start with either "/", "./", or "../".

Importing npm Modules

import {v4} from "https://jspm.dev/uuid"

Getting Imports

Getting Imports

Getting Imports

https://regexr.com/

Unit tests

No Backend!

No Backend!

  • Save
  • Deploy
  • Local assets
  • Sync
  • Share
  • Broadcast

Browser Storage

  • Cookies
  • sessionStorage
  • localStorage
  • IndexedDB
  • Web SQL
  • Cache API
  • Origin private file system (OPFS)

Services

  • CDNs
    • npm packages
    • ES modules for npm packages
    • GitHub files
    • Deno modules
  • GitHub Pages
    • Push to gh-pages branch
  • Share service: dpaste
  • Custom services

Query Strings

https://livecodes.io/?x=code/N4IgLglmA2CmIC...
  • Client-side sharing
  • Size limit
  • Needs encoding and may be compression
  • Not user-friendly

QR Code

LiveCodes QR code

Data URLs

URLs prefixed with the data: scheme

Example:

data:,Hello%2C%20World%21

Hello, World!

Avoid Breaking Changes

SDK

  • for embedding playgrounds
  • light-weight npm package (SDK)
  • creates an Iframe
  • loads LiveCodes with embed options (App)
  • allows communication with the app

Automated Releases

          graph LR
              release[Release] --> SDK
              SDK -- GH Actions --> npm
              npm --> sdkV["livecodes@0.2.0"]
              sdkV --> CDNs
              release --> App
              App -- GH Actions --> PR[PR -> main]
              PR -- CF Pages --> Preview
              Preview -- DNS API --> Subdomain[v15.livecodes.io]
              PR -- merge --> Deploy
              Deploy --> Domain[livecodes.io]
        

Technology Stack

(a.k.a. Personal Preferences!)

  • "Vanilla" TypeScript
  • I NEVER use classes or this!
  • Build system: Esbuild
  • Testing: Playwright & Jest
  • Docs: Docusaurus
  • CI/CD: GitHub Actions
  • Hosting: Cloudflare Pages
  • Backend: None :)

Future

  • Offline!
    • Service workers
  • Source control
    • Client-side Git!
  • Collaboration
    • WebRTC

Summary

  • WebAssembly
  • Higher-Order Functions
  • Import Maps
  • Browser Storage
  • Data URLs
  • Automated Releases - Versions

Conclusions

Open-Source = ❤️

Keep learning and building

References

  • https://webassembly.org/
  • https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
  • https://github.com/WICG/import-maps
  • https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage
  • https://web.dev/persistent-storage/
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs

 

Presentation

https://hatemhosny.github.io/egyptjs/

Edit in LiveCodes

https://livecodes.io/?x=id/9y7um6qucs8

Made in LiveCodes!

Thank You

Thank You