- Technical Deep Dive
- Project Architecture
Technical Deep Dive
Project Architecture
Deep dive into the folder layout, build pipeline, and runtime design of Mako Code.
Project Architecture
Mako Code intentionally segments front-end and back-end into two self-contained workspaces. This allows each side to use best-of-breed tooling—FastAPI for the API tier, SvelteKit for the UI—while preserving a thin, predictable contract between them.
Repository Layout
├── backend/ # FastAPI + Polars execution engine
│ ├── main.py # Entry point (uvicorn main:app)
│ └── functions/ # Domain modules
│ ├── ingestion.py # Dataset import helpers
│ ├── mako.py # Save helpers for DataFrame → Parquet
│ ├── sql_parser.py # Basic SELECT ... FROM parser
│ └── utils.py # Exec helpers, user functions
├── frontend/ # SvelteKit SPA
│ ├── src/lib/ # Reusable components & stores
│ │ ├── components/ # Modal dialogs, editor, sidebar
│ │ └── utils/ # api.ts (REST wrapper)
│ ├── src/routes/ # +page.svelte (main workspace)
│ └── vite.config.ts # Vite aliasing & env
├── data/ # Automatically created at runtime
│ ├── datasets/ # *.parquet user datasets
│ ├── versions/ # Code snapshots per tab
│ └── functions/ # Saved user functions
└── docker-compose.yml # Two-service orchestration
Why Separate functions/ inside backend/?
The backend frequently evaluates user code snippets. To keep the global namespace tidy, helper utilities are namespaced under functions.*. When a user saves a custom helper through Save Function Modal, the backend writes it into data/functions/ and imports it dynamically via importlib. See backend/functions/utils.py#delete_function for safe deletion.
Runtime Sequence Diagram
sequenceDiagram
participant UI as /src/routes/+page.svelte
participant API as FastAPI
participant Polars as Polars Engine
participant FS as Local File System
UI->>API: POST /api/execute (code)
activate API
API->>API: validate_code_safety(code)
API-->>UI: 400 Bad Request (if unsafe)
API->>Polars: pl.scan_parquet(), transformations
Polars->>FS: read dataset parquet
API-->>UI: JSON(stdout, stderr, success, artifacts)
deactivate API
A single /api/execute call may spawn three sub-tasks:
- AST Safety Check (
main.py#is_safe_code) – Disallowsimport os,eval(), orsubprocessinside user snippets. - Code Execution – Run inside a
contextlib.redirect_stdoutcontext, capturing textual output. - Artifact Extraction – If the snippet produces a Bokeh
Figure, the backend serializes it to JSON and streams it back.
Front-End Architectural Highlights
- MonacoEditor.svelte – Thin wrapper around
monaco-editor, registers Python completions viapythonLanguageFeatures.ts. - RightSidebar.svelte – Hosts dataset overview, plus VersionHistory.svelte via slot composition.
- Global Store –
lib/stores/navigation.tspersistshasUnsavedChangesacross route transitions. Used to trigger ConfirmNavigationModal. - Tab Model – The main workspace maintains
tabs[]in local component state. Closed tabs are pushed toeditorStore.tsfor undo close.
Backend Module Deep Dive
1. functions/ingestion.py
DATASET_DIR = Path(os.getenv("DATASETS_DIR", "data/datasets"))
def ensure_dataset_dir() -> Path:
DATASET_DIR.mkdir(parents=True, exist_ok=True)
return DATASET_DIR
Every upload path eventually calls ensure_dataset_dir(). Because it is idempotent, parallel uploads are safe.
2. functions/sql_parser.py
A very lightweight SELECT col1, col2 FROM dataset parser used to transform SQL tabs into Polars pipelines:
SELECT_RE = re.compile(r"select\s+(?P<cols>.+?)\s+from\s+(?P<table>\S+)", re.I)
def parse_sql_code(code: str) -> tuple[str, Optional[str], list[str]]:
m = SELECT_RE.search(code)
if not m:
return "", None, []
cols = [c.strip() for c in m.group("cols").split(",")]
table = m.group("table")
return table, None, cols
While simplistic, this is sufficient for 80 % of exploratory SQL use-cases. Complex predicates can be rewritten directly in Polars.
3. main.py::execute_code
@app.post("/api/execute")
async def execute_code(request: CodeRequest):
safe, reason = is_safe_code(request.code)
if not safe:
return JSONResponse(status_code=400, content={"error": reason})
stdout_buffer = io.StringIO()
with contextlib.redirect_stdout(stdout_buffer):
try:
exec(request.code, exec_env)
success = True
except Exception as e:
success = False
traceback.print_exc()
return {
"stdout": stdout_buffer.getvalue(),
"success": success,
}
exec_env includes polars as pl, the functions package, and any user-saved helpers imported at runtime.
Data Directory Contract
| Path | Description |
|---|---|
data/datasets/ | Parquet or Arrow files. Created by uploader or by mako.save() helper. |
data/versions/<tab_name>/ | Timestamped snapshots of every save event. |
data/functions/ | User helpers, one file per function, plus __init__.py autoload. |
All directories are created at startup via init_data_directories().
Build & Release Flow
- Backend –
Dockerfile.backendinstalls Python 3.11 slim, copiesbackend/, runsuv pip install -r. - Frontend –
Dockerfile.frontendperforms SvelteKit static build (npm run build) and serves viavite preview. - Compose – Tags are pushed to GHCR (
ghcr.io/slashml/mako-code-frontend:sha), versioned via GitHub Actions.
Extending the Architecture
- Add BigQuery or Snowflake connectors inside
functions/ingestion.py. - Swap Bokeh for Plotly by updating the
POST /api/executeserializer. - Implement Auth by mounting another FastAPI router (e.g.,
fastapi-users).
Continue to API Reference for a list of all endpoints.