• Embeddable code playgrounds

    for fun and profit

    Peter Zaitsev

    Anton Zhiyanov

  • Explain

    the topic

    Engage

    the reader

  • → Use cases

    Approach

    Implementation

  • Tutorials and how-tos

    explain by example

  • Cloud Storage API Tutorial

    PUT https://database.deta.sh/v1/c0p1npjnpwx/messages/items
    content-type: application/json
    x-api-key: c0p1npjnpwx_uL7C9wfpyoaNVh5Sr3s2FiubG2jrjMyt
    
    {
        "items": [{
            "key": "m-001",
            "user": "Alice",
            "message": "Hi Bob!"
        }]
    }
    HTTP/1.1 207 Multi-Status
    content-length: 77
    content-type: application/json; charset=UTF-8
    
    {"processed":{"items":[{"key":"m-001","message":"Hi Bob!","user":"Alice"}]}}
  • Cloud Storage API Tutorial

    GET https://database.deta.sh/v1/c0p1npjnpwx/messages/items/m-001
    content-type: application/json
    x-api-key: c0p1npjnpwx_uL7C9wfpyoaNVh5Sr3s2FiubG2jrjMyt
    HTTP/1.1 200 OK
    content-length: 51
    content-type: application/json; charset=UTF-8
    
    {"key":"m-001","message":"Hi Bob!","user":"Alice"}
  • Release notes

    show what's changed

  • Go loop variables

    // go 1.21
    
    values := []int{1, 2, 3, 4, 5}
    for _, val := range values {
        go func() {
            fmt.Print(val, " ")
        }()
    }
    5 5 5 5 5
    // go 1.22
    
    values := []int{1, 2, 3, 4, 5}
    for _, val := range values {
        go func() {
            fmt.Print(val, " ")
        }()
    }
    5 1 2 3 4
  • Reference documentation

    try options in real time

  • curl --json option

    --json <data>
    
    Sends the specified JSON data in a POST request to the HTTP server.
    
    There is no verification that the passed in data is actual JSON or that the syntax is correct.
    
    If you start the data with the letter @, the rest should be a file name to read the data from, or a single dash (-) if you want curl to read the data from stdin. Posting data from a file named 'foobar' would thus be done with --json @foobar and to instead read the data from stdin, use --json @-.
    
    If this option is used more than once on the same command line, the additional data pieces are concatenated to the previous before sending.
  • curl --json: post

    curl --json '{ "drink": "coffee" }' http://httpbingo.org/anything
    {
      "args": {},
      "headers": {},
      "method": "POST",
      "origin": "172.19.0.9:39794",
      "url": "http://httpbingo.org/anything",
      "data": "{ \"drink\": \"coffee\" }",
      "files": {},
      "form": {},
      "json": {
        "drink": "coffee"
      }
    }
  • curl --json: from file

    curl --json @coffee.json http://httpbingo.org/anything
    {
      "args": {},
      "headers": {},
      "method": "POST",
      "origin": "172.19.0.9:35124",
      "url": "http://httpbingo.org/anything",
      "data": "{ \"drink\": \"coffee\" }\n",
      "files": {},
      "form": {},
      "json": {
        "drink": "coffee"
      }
    }
  • Deep dives

    show how things work

  • Upsert in SQL

    ┌────┬───────┬────────┬────────────┬────────┐
    │ id │ name  │  city  │ department │ salary │
    ├────┼───────┼────────┼────────────┼────────┤
    │ 11 │ Diane │ London │ hr         │ 70     │
    │ 12 │ Bob   │ London │ hr         │ 78     │
     21  Emma   London  it          84     
    │ 22 │ Grace │ Berlin │ it         │ 90     │
    │ 23 │ Henry │ London │ it         │ 104    │
    │ 24 │ Irene │ Berlin │ it         │ 104    │
    │ 31 │ Cindy │ Berlin │ sales      │ 96     │
    │ 32 │ Dave  │ London │ sales      │ 96     │
    └────┴───────┴────────┴────────────┴────────┘
    
    + 33 | Alice | Berlin | sales      | 100
  • Upsert in SQL: insert or replace

    insert or replace into employees
    (id, name, city, department, salary)
    
    values
    (21, 'Emma', 'London', 'it', 95),
    (33, 'Alice', 'Berlin', 'sales', 100);
    
    select * from employees where id in (21, 33);
    ┌────┬───────┬────────┬────────────┬────────┐
    │ id │ name  │  city  │ department │ salary │
    ├────┼───────┼────────┼────────────┼────────┤
    │ 21 │ Emma  │ London │ it         │ 95     │
    │ 33 │ Alice │ Berlin │ sales      │ 100    │
    └────┴───────┴────────┴────────────┴────────┘
  • Upsert in SQL: on conflict

    insert into employees
    (id, name, city, department, salary)
    
    values
      (21, 'Emma', 'London', 'it', 95),
      (33, 'Alice', 'Berlin', 'sales', 100)
    
    on conflict do update set
      salary = excluded.salary;
    
    select * from employees where id in (21, 33);
    ┌────┬───────┬────────┬────────────┬────────┐
    │ id │ name  │  city  │ department │ salary │
    ├────┼───────┼────────┼────────────┼────────┤
    │ 21 │ Emma  │ London │ it         │ 95     │
    │ 33 │ Alice │ Berlin │ sales      │ 100    │
    └────┴───────┴────────┴────────────┴────────┘
  • ✓ Use cases

    → Approach

    Implementation

  • Writer and reader experience

  • Same documentation

    but interactive

  • Hassle-free integration

    focus on writing

  • Write as you are used to

    ```python
    def greet(name):
        print(f"Hello, {name}!")
    
    greet("World")
    ```
  • Add interactivity as needed

    ```python
    def greet(name):
        print(f"Hello, {name}!")
    
    greet("World")
    ```
    <codapi-snippet sandbox="python" editor="basic">
    </codapi-snippet>
  • See results immediately

    def greet(name):
        print(f"Hello, {name}!")
    
    greet("World")
    Hello, World!
  • Real-world scenarios

    go beyond the "hello world"

  • Templates

    select
      dense_rank() over w as "rank",
      name, department, salary
    from employees
    window w as (
      partition by department
      order by salary desc
    );
    ┌──────┬───────┬────────────┬────────┐
    │ rank │ name  │ department │ salary │
    ├──────┼───────┼────────────┼────────┤
    │ 1    │ Bob   │ hr         │ 78     │
    │ 2    │ Diane │ hr         │ 70     │
    │ 1    │ Henry │ it         │ 104    │
    │ 1    │ Irene │ it         │ 104    │
    │ 2    │ Grace │ it         │ 90     │
    │ 3    │ Emma  │ it         │ 84     │
    │ 1    │ Cindy │ sales      │ 98     │
    │ 1    │ Dave  │ sales      │ 96     │
    └──────┴───────┴────────────┴────────┘
  • Templates

    <codapi-snippet sandbox="sqlite" template="employees.sql">
    </codapi-snippet>
    create table employees (
        ...
    );
    
    insert into employees
    (id, name, city, department, salary)
    values ...;
    
    ##CODE##
    
  • Code cells

    model dependencies

  • Code cells

    import textwrap
    
    def wrap(text, width=20):
        return textwrap.fill(text, width)
    text = (
        "Python is a programming language that lets you work quickly "
        "and integrate systems more effectively."
    )
    print(wrap(text))
  • Code cells

    ```python
    # first snippet
    ```
    
    <codapi-snippet id="cell-1" sandbox="python">
    </codapi-snippet>
    
    ```python
    # second snippet
    ```
    
    <codapi-snippet sandbox="python" depends-on="cell-1">
    </codapi-snippet>
    
  • ✓ Use cases

    ✓ Approach

    → Implementation

  • Implementation

  • Browser APIs

    JavaScript • Fetch API

  • WebAssembly

    Python • PHP • Ruby
    Lua • SQLite

  • Docker

    virtually anything

  • Showcase


    chDB documentation

    FerretDB tutorial

    Go release notes (unofficial)

    SQL join flavors

    codapi.org/showcase

  • Interactive code snippets


    github.com/nalgeon/codapi

    github.com/nalgeon/codapi-js

    codapi.org/fosdem-2024


    Peter Zaitsev • peterzaitsev.com
    Anton Zhiyanov • antonz.org