Backends
Primate supports multiple backend languages compiled to WebAssembly. Use one or mix them in the same app for different routes.
Overview
Backend | Routes | Body | Query | Sessions | Stores | WebSocket | Validation |
---|---|---|---|---|---|---|---|
Go | |||||||
Grain | |||||||
Python | |||||||
Ruby |
Features
- Routes — HTTP method handlers (GET, POST, PUT, DELETE, etc.)
- Body — handle JSON, form data, text, binary, and file uploads
- Query — access URL query parameters and path variables
- Sessions — server-side session management with cookies
- Stores — built-in database operations (CRUD, queries, validation)
- WebSocket — real-time bidirectional communication
- Validation — strongly-typed request/response validation schemas
WebAssembly
Backends run in the JS runtime via WebAssembly or a Wasm-based runtime (e.g. Pyodide for Python).
Language Categories
Systems Languages
Go, Grain
Compiled languages with strong type systems, memory safety, and excellent WebAssembly support. Well-suited for high-performance APIs and complex business logic.
Dynamic Languages
Python, Ruby
Interpreted languages with flexible syntax and extensive ecosystems. Good for rapid prototyping, data processing, and scripting tasks.
Quickstart
Install a backend module:
npm install @primate/go
Configure it:
// config/app.ts
import config from "primate/config";
import go from "@primate/go";
export default config({
modules: [go()],
});
Create a route handler:
// routes/hello.go
package main
import "github.com/primate-run/go/route"
var _ = route.Get(func(request route.Request) any {
return "Hello, World!"
})
Route Structure
Each backend follows a consistent pattern for route handlers:
HTTP Methods
All backends support standard HTTP methods through dedicated functions:
// Go
var _ = route.Get(func(request route.Request) any { ... })
var _ = route.Post(func(request route.Request) any { ... })
// Grain
provide let get = (request: Request) => { ... }
provide let post = (request: Request) => { ... }
# Python
@Route.get
def get(request): ...
@Route.post
def post(request): ...
# Ruby
Route.get do |request|
...
end
Route.post do |request|
...
end
Request Handling
Access request data through consistent APIs:
// Go - Query parameters
if request.Query.Has("name") {
name, _ := request.Query.Get("name")
return name
}
// Go - JSON body
json, err := request.Body.JSON()
// Grain - Query parameters
let query = Request.getQuery(request)
match (Map.get("name", query)) {
Some(value) => JsonString(value),
None => JsonString("name missing")
}
// Grain - JSON body
Body.json(request)
Response Types
Data Responses
Return structured data as JSON:
return map[string]any{"message": "Hello"}
JsonObject([("message", JsonString("Hello"))])
Views
Render frontend components:
return response.View("component.html", data)
Response.view("component.html", props = data)
Redirects
Redirect to other routes:
return response.Redirect("/other-route")
Response.redirect("/other-route")
Database Operations
Built-in store operations:
// Grain
let User = Store.store("User")
let user = Store.insert(User, userData)
Session Management
Server-side sessions with automatic cookie handling:
// Go
session.Create(map[string]any{"user": "john"})
data := session.Get()
// Grain
Session.create(JsonObject([("user", JsonString("john"))]))
let session = Session.get()
WebSocket Support
Real-time communication endpoints:
// Grain
Response.ws(
message = Some((socket, payload) => {
WebSocket.send(socket, payload) // Echo back
})
)
Mixing Backends
Multiple backends can coexist; each handles its own file extensions:
import config from "primate/config";
import go from "@primate/go";
import python from "@primate/python";
import grain from "@primate/grain";
export default config({
modules: [go(), python(), grain()],
});
Routes can be implemented in different languages:
routes/
├── auth.go # Go authentication
├── api.py # Python data processing
├── websocket.gr # Grain real-time features
└── admin.rb # Ruby admin interface
Ecosystem Integration
Package Management
Each backend uses its native package manager:
- Go —
go.mod
andgo get
- Grain — Built-in modules and includes
- Python —
requirements.txt
andpip
- Ruby —
Gemfile
andbundle
External Libraries
Import and use libraries native to each language, compiled to WebAssembly:
// Go
import "encoding/json"
import "crypto/sha256"
# Python
import numpy as np
import pandas as pd
# Ruby
require 'json'
require 'digest'