Skip to content

smart-developer1791/preact-wasm-notebook-runtime

Repository files navigation

✦ Preact WASM Notebook Runtime

A private browser Python notebook with self-hosted Pyodide, persistent execution state, structured outputs, and portable export.

Preact TypeScript Tailwind CSS Pyodide Vite

Deploy with Vercel


✨ Highlights

  • Real CPython WASM Runtime: Executes Python through Pyodide rather than translating or simulating Python in JavaScript.
  • Dedicated Web Worker: Keeps runtime compilation and cell execution away from the main UI thread.
  • Self-Hosted Runtime: Serves the Pyodide loader, lock file, WebAssembly binary, and Python standard library from public/pyodide without a runtime CDN dependency.
  • Persistent Python Namespace: Preserves imports, functions, and variables between cell executions until the runtime is explicitly reset.
  • Ordered Run All: Queues notebook cells and executes them sequentially against the shared Python namespace.
  • Cell Operations: Adds, edits, duplicates, reorders, runs, and deletes cells with stable execution metadata.
  • Structured Output: Renders standard output, standard error, scalar values, dictionaries, record tables, and lightweight bar or line charts.
  • Runtime Variable Inspector: Displays user-created namespace values with Python types and compact previews.
  • Python Import: Converts an imported .py file into a new executable notebook cell.
  • Portable Notebook Export: Downloads the current workspace as a valid .ipynb document.
  • Local Notebook Persistence: Stores notebook cells in IndexedDB through idb-keyval without a backend.
  • Runtime Lifecycle Controls: Shows warmup and CPython status, reports execution timing, and supports a complete worker reset.
  • Responsive Editing Surface: Keeps cell actions, code editors, outputs, and runtime panels usable on mobile while favoring wide screens for longer code.

🧱 Project Structure

public/
|-- favicon.svg
|-- sample-analysis.py
`-- pyodide/
    |-- pyodide-lock.json
    |-- pyodide.asm.mjs
    |-- pyodide.asm.wasm
    `-- python_stdlib.zip
src/
|-- app.tsx                       # notebook state, execution queue, import, export, and persistence
|-- main.tsx
|-- index.css
|-- components/
|   |-- cell-card.tsx             # code cell controls, execution state, and output shell
|   `-- output-view.tsx           # text, error, table, scalar, and chart renderers
|-- domain/
|   `-- types.ts                  # notebook, output, variable, and worker message contracts
`-- workers/
    `-- python.worker.ts          # Pyodide initialization and browser-local Python execution

🛠️ Tech Stack

  • Preact 10 with Vite 8
  • TypeScript 6
  • Tailwind CSS 4
  • pyodide
  • Web Workers
  • idb-keyval
  • lucide-preact

📦 Included Sample Data

  • The starter notebook contains three cells covering descriptive statistics, a list-of-records table, and a chart result contract.
  • public/sample-analysis.py provides a standalone Python file for testing the import workflow.
  • public/pyodide contains the matching loader, lock manifest, WASM runtime, and standard library used by the worker.
  • The examples require no third-party Python package installation and work with the bundled standard library.

📊 Structured Output Contract

The final Python expression becomes the cell result. A list of dictionaries renders as a table. A dictionary in this form renders as a chart:

{
    "type": "bar",
    "title": "Requests by service",
    "x": ["API", "Worker", "Search"],
    "y": [120, 88, 64],
}

Set type to "line" to render a line chart with the same x and y arrays.

🚀 Local Development

npm install
npm run dev

Open http://localhost:5173.

🔌 Extension Notes & Nuances

  • Python code, outputs, variables, and imported files remain inside the browser and are never submitted to an application server.
  • Pyodide performs a real CPython WASM startup, so the first cold load can take longer than later cached sessions.
  • The worker keeps one shared namespace, which gives notebook cells familiar stateful behavior and also means execution order matters.
  • Reset Python runtime terminates the current worker and removes all in-memory Python variables before starting a fresh runtime.
  • stdout and stderr are captured per execution and transferred to the UI through typed worker messages.
  • PyProxy values are converted to serializable JavaScript structures before leaving the worker and are destroyed after conversion.
  • The included runtime provides Python's standard library; packages such as pandas, NumPy, or Matplotlib are not preinstalled by this project.
  • Chart rendering intentionally uses a compact local SVG renderer instead of requiring a heavy plotting framework.
  • IndexedDB persistence stores the notebook document, not the active Python heap or imported module state.
  • The UI is responsive, but editing long Python cells and comparing multiple outputs is naturally more comfortable on desktop.

🧪 Build & Checks

npm run build
npm run preview

The production build validates TypeScript before emitting the Preact application and dedicated Python worker. Keep the files in public/pyodide version-aligned when upgrading the pyodide package.

🌐 Vercel Deployment

The repository includes a Vite-ready vercel.json with SPA rewrites.

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "framework": "vite",
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}

📄 License

MIT License. See LICENSE. Bundled Pyodide notices are documented in THIRD_PARTY_LICENSES.md.

Releases

No releases published

Packages

 
 
 

Contributors