"Journey: One-File Full-Stack Data"

Journey: One-File Full-Stack Data

The Duplicate Tax of Modern Web Dev

To build a simple "Todo list" or display a database record in most modern apps, you must duplicate the data structure across three distinct layers:

  1. The Database: A SQL migration or Prisma schema (table tasks...).
  2. The Backend ORM: The structure logic bridging the DB to logic (e.g., a Rust struct).
  3. The API Layer: An Express/Axum HTTP endpoint to serialize the struct into JSON.
  4. The Frontend: A TypeScript interface Task { id: string, title: string } mirroring the query output.

This causes extreme friction when a single field changes, breaking APIs and forcing developers to jump through five files for the smallest data adjustment.

The Vox Paradigm: No API Layer

Vox enables you to declare this from one single source of truth. One @table definition compiles into the correct Rust struct and the SQLite bindings. One @server function creates an Axum handler and the matching TypeScript serialization client. The @island component then directly calls the server function as if it was native to the React client.

You avoid writing boilerplate. State synchronization and type-checking happen safely across the entire vertical stack at compilation time.

Core Snippet: The Vertical Slice

Below is a complete, working React frontend and Rust backend in a single .vox file.

// vox:skip
import react.use_state

// 1. DDL & Struct defined once entirely.
@table type Task {
    title:    str
    done:     bool
    owner:    str
}

// 2. Server mutation automatically generated. Typed args enforce contract.
@server fn complete_task(id: Id[Task]) -> Result[Unit] {
    db.Task.update(id, { done: true })
    return Ok(())
}

// 3. UI logic generated as React component.
@island
fn TaskList(tasks: list[Task]) -> Element {
    let (items, _set_items) = use_state(tasks)

    <div class="task-list">
        {items.map(fn(task) {
            <label>
                <input 
                    type="checkbox" 
                    checked={task.done}
                    onChange={fn(_e) complete_task(task.id)}
                />
                {task.title}
            </label>
        })}
    </div>
}

// Server Side Routing mapped directly to the UI elements.
routes {
    "/" -> TaskList
}

Running the Process

  1. Put the code in src/main.vox.

  2. Initialize and run:

    vox build src/main.vox -o dist
    vox run src/main.vox
    
  3. Vox will instantly compile the Task type into a Rust struct, create the SQLite table automatically via Codex, launch the Axum server, and compile the React bundle.

Maturity and limitations

  • Maturity: beta — web stack and Codex bindings are active development surfaces; verify against golden examples for your compiler version.
  • Limitation ids: L-021 (workspace-local vs canonical Codex stores can diverge if env paths are mis-set).

Deep Dives

To examine how the compiler handles this transparently: