Log in to share a post with the community.
Home
Log in as alice@example.com and edit this post. Log in as bob and PATCH the same id — Bunderstack returns 403. That is row-level security.
drizzle-kit push runs on boot in development so the example works after git clone. Production: run db:push explicitly.
Level 0: createBunderstack({ schema }). Level 2: reach for app.db, app.router, app.auth when auto-CRUD is not enough.
Follows, likes, retweets, and threaded replies — all plain Drizzle tables with ownerColumn access. Compose Twitter-style UX on top.
Opt-in searchableColumns in access rules. GET /api/posts?q=drizzle runs parameterized LIKE across title and body — try the search box!
Storage access mirrors table access: authenticated upload, public read, owner delete. Metadata tracked in SQLite.
POST /api/files uploads with mime/size rules. GET serves originals; ?w=&h=&format=webp returns on-the-fly thumbnails via sharp.
Prefetch with queryClient.ensureQueryData in route loaders, fall back to Route.useLoaderData() so SSR and client markup match.
createBunderstackQueryClient exposes listQuery, createMutation, etc. Wire useQuery/useMutation directly — no custom hooks layer.
Email/password sessions live at /api/auth/*. Same app.handler(Request) serves CRUD, auth, and files — mount in TanStack Start or Next.js.
Use defineAccess() when conventions are not enough: follows use followerId, auth tables stay sealed unless exposeAuthTable.
Add a userId column and owner-scoped update/delete kick in automatically. Public list/get, authenticated create, owner mutations.
Define tables in Drizzle — Bunderstack mounts GET/POST/PATCH/DELETE at /api/:table. No hand-written route boilerplate.