TellWang
Dashboard

Storage

Your Wok includes file storage for images, uploads, and documents — the S3-compatible Supabase Storage API. There's no separate file server to run or scale.

Bucket creation + policy management live in your Wok's Postgres (storage.buckets + storage.objects + RLS). Click SQL on any Wok card in the dashboard for an in-browser console — see the recipe below.

Buckets (shipped)

Files live in buckets. A bucket can be public (anyone with the link can view) or private (only the signed-in users you allow, using the same rules as your data). Create one and grant access via SQL on the Wok:

bucket.sql
-- Create a public bucket (links work without auth)
insert into storage.buckets (id, name, public)
values ('avatars', 'avatars', true);

-- Create a private bucket + a policy: authenticated users can upload
-- their OWN avatar into avatars/.png
insert into storage.buckets (id, name, public)
values ('docs', 'docs', false);

create policy "own-folder-write" on storage.objects
  for insert to authenticated
  with check (
    bucket_id = 'docs'
    and (storage.foldername(name))[1] = auth.uid()::text
  );

Upload & serve (shipped)

upload.ts
await tw.storage.from("avatars").upload("alex.png", file);
const { url } = tw.storage.from("avatars").publicUrl("alex.png");

Private files are served through short-lived signed links, so they can't be shared or guessed:

signed.ts
const { data } = await tw.storage.from("docs")
  .createSignedUrl("contract.pdf", 60); // 60s

Backend (shipped)

Today every Wok's Storage runs on a local-filesystem backend (STORAGE_BACKEND=file, FILE_STORAGE_BACKEND_PATH=/var/lib/storage), persisted alongside its Postgres on the host. The API contract is the same as S3 mode, so apps don't change when the backend swaps under them. Daily logical backups cover the Postgres-side metadata; file bytes ride on the host's bare-metal storage.

Roadmap