Timberdocs

Developers

Data & storage

Storage API#

db_read('posts', [])                     // data/posts.json → array
db_write('posts', $rows)                 // atomic: temp file + rename
db_locked(fn() => …)                     // exclusive lock around read-modify-write
collection('posts')                      // list of records, each with an 'id'
find_by('pages', 'slug', 'about')
save_record('posts', $record)            // insert or merge by id; sets id, created_at, updated_at
delete_record('posts', $id)
settings('seo.site_url', $default)       // dot path into settings.json

Files are pretty-printed UTF-8 JSON, so they diff and back up well.

Collections#

FileHolds
pages.json, posts.jsonContent (status, slug, title, body, SEO, dates, images…)
versions.jsonThe Playground's versions (theme, status, content overrides, order, hidden sections, share key)
forms.json, messages.jsonForm definitions and submissions (personal data)
menus.json, menu_names.jsonMenus and custom menu names
redirects.jsonRedirects with hit counts
snippets.jsonBlocks
media_meta.jsonAlt text keyed by media path (the library itself is a file scan)
page_folders.jsonVirtual folders for organising pages
email_log.json, consents.json, form_stats.jsonLogs and counters
users.json, secrets.json, login_throttle.jsonAccounts (with password hashes), API keys and mail passwords, login attempts. Never exported or shown

Settings groups (settings.json)#

site · seo · analytics · email · maintenance · notice · theme · styles · privacy · adminbar · code_editor · integrations · dashboard · migrations. Read them with settings('group.key'); write them with save_settings('group', [...]).

Why JSON?#

  • Zero setup and zero services — nothing to install, nothing to credential.
  • Transparent. Open a file and see your content.
  • Portable. Back up and move by copying.
  • Safe enough. Writes are atomic and read-modify-write cycles hold a lock, so concurrent requests can't corrupt a file.

Limits#

JSON is comfortable up to a few thousand records and modest write traffic. Each request reads the collections it needs in full. If you outgrow it, the plan is an optional SQLite driver behind the same collection() / save_record() API (see the roadmap).

Timber is open source. Built by indies, for indies. © 2026