Add a Feature in 10 Minutes
January 25, 2025 · Magnus Rodseth
Add a Feature in 10 Minutes
Eden Stack's architecture makes adding features predictable. Every feature follows the same pattern across four layers. Once you understand the pattern, you can ship complete functionality in minutes.
The Four-Layer Pattern
Every feature in Eden Stack touches these layers:
┌─────────────────────────────────────────────────┐
│ 1. SCHEMA → Define the data structure │
│ 2. API → Expose CRUD operations │
│ 3. HOOKS → Connect React to API │
│ 4. UI → Render and handle interactions │
└─────────────────────────────────────────────────┘Let's see this in action with a bookmarks feature.
Layer 1: Schema (Drizzle)
Define what a bookmark looks like:
// src/lib/db/schema.ts
export const bookmarks = pgTable("bookmarks", {
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
userId: text("user_id").notNull().references(() => users.id),
conversationId: text("conversation_id").notNull(),
createdAt: timestamp("created_at").defaultNow(),
});Run bun run db:push. Schema done.
Layer 2: API (Elysia)
Expose the operations:
// src/server/routes/bookmarks.ts
export const bookmarksRoutes = new Elysia({ prefix: "/bookmarks" })
.get("/", /* list bookmarks */)
.post("/", /* add bookmark */)
.delete("/:id", /* remove bookmark */);Each endpoint: authenticate → query/mutate → return. Eden Treaty auto-generates the typed client.
Layer 3: Hooks (TanStack Query)
Connect React to your API:
// src/hooks/use-bookmarks.ts
export const useBookmarks = () => useQuery({ queryKey: ["bookmarks"], queryFn: /* ... */ });
export const useAddBookmark = () => useMutation({ mutationFn: /* ... */ });
export const useRemoveBookmark = () => useMutation({ mutationFn: /* ... */ });Queries cache automatically. Mutations invalidate related queries.
Layer 4: UI (React)
Use the hooks in components:
function BookmarkButton({ id }: { id: string }) {
const { data } = useIsBookmarked(id);
const add = useAddBookmark();
const remove = useRemoveBookmark();
return (
<Button onClick={() => data?.isBookmarked ? remove.mutate(id) : add.mutate(id)}>
{data?.isBookmarked ? <BookmarkCheck /> : <Bookmark />}
</Button>
);
}That's it. Four layers, one feature.
The Files You Touch
| Layer | Location | What You Add |
|---|---|---|
| Schema | src/lib/db/schema.ts | Table definition |
| API | src/server/routes/ | New route file |
| Hooks | src/hooks/ | Query/mutation hooks |
| UI | src/components/ | React components |
Or Just Ask Claude
Instead of writing this yourself:
Add a bookmarks feature. Users should be able to bookmark
conversations and see them in a sidebar. Include database
schema, API endpoints, and React components.Claude knows the patterns. It'll generate all four layers, following the conventions already in your codebase.
The architecture is the documentation. Consistent patterns mean AI assistants (and new team members) can contribute immediately.
Ready to build? Check out the Getting Started guide or see 10 SaaS ideas you can build with this pattern.
Related Articles
Deploy to Production in 5 Minutes
Go from local development to a live production app with Vercel, Railway, and Neon
Stripe vs Lemon Squeezy for SaaS
Why Eden Stack chose Stripe and when Lemon Squeezy might be the better choice for your project
Why Bun Over Node.js
The case for using Bun as your JavaScript runtime and package manager in production