Writing

Vellum Case Study: Building an Open-Source Team Workspace with Next.js and PostgreSQL

Vellum is my open-source workspace for teams, projects, Kanban boards, and tasks. This case study covers the relational model, role-based access, TypeScript across Next.js and Drizzle, and what publishing the source changes about design.

Why build another team workspace?

Vellum started from a deliberately modest ambition: bring team and project workflows into one straightforward workspace. It has Kanban boards, task tracking, team organization, assignees, priorities, and role-based access. None of those words is exotic. The engineering problem is keeping them connected without making the product feel like an administration system that occasionally lets people do work.

That makes Vellum a useful case study because its difficulty is the ordinary difficulty of business software. A board is not just columns on a screen; it is a shared claim about what state work is in. A task is not just a title; it belongs somewhere, means something to somebody, and changes hands. Get those relationships wrong and every later feature becomes a workaround dressed as a screen.

The domain is mostly relationships

Teams contain people, projects contain work, and tasks sit inside both an organizational and a workflow context. That is why PostgreSQL is the natural centre of Vellum rather than a document-shaped shortcut. The product continually asks relational questions: which work belongs to this team, who is responsible for it, what state is it in, and who is allowed to change it? If those questions are awkward in the data model, they will be awkward everywhere.

Drizzle keeps that model close to SQL while letting the schema participate in the TypeScript codebase. It is the same preference I described in the SvelteKit platform article: queries should look like what they do, and the database should not disappear behind magic. Vellum uses a different frontend stack, but the database philosophy is deliberately familiar. Boring under the data is a compliment.

Hosted Neon PostgreSQL completes that choice operationally: the application gets a real relational database without making database babysitting the project’s main hobby. That does not remove the need for database-performance discipline. Board views, project lists, and responsibility filters are exactly the kinds of everyday queries that should be shaped around how people scan their work. If the model needs contortions to answer “what is on this board, who owns it, and what changed?”, the interface will eventually pay for those contortions in latency or special cases. A calm schema makes ordinary product questions cheap to ask again and again.

Role-based access is a product boundary

Role-based access sounds like a settings table until a real team uses the product. Roles decide whose work is visible, who can reorganize a project, and which actions are even meaningful for a given person. In that sense authorization is not a security garnish added after the interface; it is part of the product’s shape. It has to agree across screens, actions, and data access or the UI starts promising things the system should never allow.

That is where my security-first habit matters in an open-source tool. I do not need to invent a dramatic threat story to justify clear boundaries. Ordinary correctness is enough: a person should only reach the work their role gives them a reason to reach, and the rule should be understandable to the next maintainer. Access logic that nobody can explain is already half broken, even before an attacker finds it.

Next.js, React, and one TypeScript conversation

I built the application with Next.js and React, with TypeScript and Tailwind CSS throughout. The practical value is not that one framework magically removes the frontend/backend divide. It is that product concepts — a task, a project, an assignee, a priority — can keep recognizable shapes as they move from database to server logic to interface, reducing the translation errors that breed in handoffs.

This is also why Vellum sits naturally beside my other web application work even though much of my client platform work uses SvelteKit. Framework choice changes syntax and deployment shape; it does not change the underlying duties. Model the domain cleanly, keep authorization coherent, make the interface direct, and let types catch the boring mismatches before users do. Those habits travel.

Open source changes the reader

Vellum’s source is public under the MIT license, and that changes who the code is written for. A private internal tool can survive on tribal knowledge for a while. A public repository has to make sense to somebody who was not in the room, which pushes names, boundaries, and setup paths toward honesty. You can inspect the result in the public repository instead of taking a portfolio paragraph at face value.

That pressure is one reason I value open-source work in my independent developer practice. It exposes design decisions that client work often cannot publish. The same is true of PromptForge, although the products solve very different problems. Together they show the developer tooling side of my work: software whose structure is meant to be read, reused, and argued with.

What Vellum keeps teaching me

The main lesson is that “simple workspace” is an outcome, not a starting condition. It takes a relational model that respects ownership, types that survive the journey through the stack, and access rules that remain legible. Most product complexity does not arrive as one huge feature. It leaks in through small exceptions until nobody can say why a task behaves differently in one place than another. The defence is boring consistency. It also creates roadmap discipline: a new view should reuse the same task truth, a new role should extend the same access model, and a new project workflow should not quietly invent a second meaning for status, ownership, or priority.

If you are building an internal workspace, project tool, or multi-user business application, I would start with those boundaries before debating boards and dashboards. The Vellum project page has the concrete stack and source link, the Laravel article covers the database-performance side of my backend history, and my résumé is the shortest route to the rest of the work.

All writing