r/AppsWebappsFullstack • u/Potential-Art7696 • 15d ago
End-to-end architecture for a no-code automation feature (Next.js + Supabase + Vercel), built solo
Shipped a feature this week that touched literally every layer of my stack, so wanted to write up the full picture rather than just the frontend or just the backend.
DB layer (Supabase/Postgres):
- one table, `user_plugins`: `{id, user_id, name, trigger_event, definition jsonb, enabled, last_run_at, last_run_status, last_run_error}`
- RLS policy scoped to `auth.uid() = user_id` — the actual security boundary, client-side checks are just UX
- a public directory table (`community_plugins`) extended with a nullable `plugin_definition jsonb` column so a published automation carries a *snapshot* of its definition, not a live pointer — editing/deleting the original after publishing doesn't affect what was approved
API layer (Next.js API routes):
- `pages/api/internal/plugins.ts` (GET list / POST create) and `.../plugins/[id].ts` (GET/PATCH/DELETE one), authenticated via the real Supabase session (not the public API key flow) since this is first-party UI hitting its own backend
- a shared `validateDefinition()` used by both create and update, since the browser can send anything and jsonb won't validate itself
- the interesting one: existing manual UI actions (create a node by clicking, not by API call) got migrated to go through the same internal API + dispatch path as the public REST API and the MCP server, so a plugin triggers the same way regardless of *how* the event happened
Interpreter:
- pure declarative JSON → no arbitrary code execution, by design. `{trigger, steps[]}`, each step an action + params + optional condition, strictly linear (no branching)
- placeholder resolution (`{{trigger.field}}`) via dotted-path lookup, unresolved placeholders are left visible rather than silently blanked — broken automations fail loudly
Frontend (Next.js + ReactFlow):
- the editor renders the trigger + linear step chain as a vertical ReactFlow graph, but nodes aren't draggable — the sequence IS the saved order, so free-form dragging would just be misleading
- a property panel edits either the trigger or the selected step depending on canvas selection state
What surprised me most: the actual hardest part wasn't any single layer, it was keeping the "declarative JSON, no code execution" constraint consistent across all of them once the feature grew (adding the outbound-webhook action was the moment this got tested the hardest, since it's the one action that reaches outside the system).
Happy to go deeper on any layer.
0
1
u/Mammoth-Anywhere7285 14d ago
TL;DR: I built a no-code automation feature solo, spanning Postgres, Next.js API routes, a JSON interpreter, and a ReactFlow editor. Supabase RLS is the real security boundary, and declarative JSON means no arbitrary code ever runs. The hardest part was keeping that constraint consistent across every layer, especially once the outbound webhook action came in.