Data Sources
The data field on pages, layouts, and components accepts named source definitions. At request time all sources are collected, deduplicated, and resolved in parallel into a single data object.
static
Inline data passed directly to the template:
{
"site_config": {
"type": "static",
"data": { "name": "My Site", "description": "A cool website" }
}
}
{{ data.site_config.name }}
db
SQL against the D1 database (or Turso). query returns an array of rows; queryOne returns a single object or null:
{
"posts": {
"type": "db",
"query": "SELECT * FROM posts WHERE category = ? ORDER BY created_at DESC LIMIT 5",
"params": ["query.category"]
},
"featured": {
"type": "db",
"queryOne": "SELECT * FROM posts WHERE featured = 1 LIMIT 1"
}
}
{{#each data.posts}}{{this.title}}{{/each}}
SQL Guard: only data statements are allowed — SELECT, INSERT, UPDATE, DELETE, REPLACE, WITH, VALUES. Schema operations and stacked queries are rejected.
Param resolution
| Param value | Resolves to |
|---|---|
"params.id" | URL path parameter (/products/:id → id) |
"query.q" | URL query parameter (?q=shoes) |
| Any other string | Passed through as a literal |
url
Fetch and parse JSON from an external HTTP endpoint:
{
"weather": {
"type": "url",
"url": "https://api.weather.gov/points/40.7,-74.0",
"method": "GET",
"headers": { "Accept": "application/json" }
}
}
file
Metadata plus a time-limited signed URL for an R2 object. The file content stays out of the template — you get a URL usable in <img>, <a>, <video>:
{
"brochure": { "type": "file", "path": "marketing/brochure.pdf", "expires": 3600 }
}
<a href="{{ data.brochure.url }}">Download ({{ data.brochure.size }} bytes)</a>
| Field | Description |
|---|---|
key | R2 object key |
size | File size in bytes |
uploaded | ISO timestamp |
url | Signed URL at /__r2/{key}?exp=...&sig=... (HMAC-SHA256) |
How resolution works
- Collect data configs from page + layout + referenced components.
- Deduplicate by content — identical SQL/params, URLs, or file paths resolve once and are shared.
- Resolve in parallel: unique DB queries in a single
db.batch()round-trip, URL fetches concurrently, file ops via parallelR2.head()+ signing. - Merge results — page > layout > component on key collisions.