The SaaS Pivot: From Broad Visions to Utilitarian Reality

Why I changed my mind on building a complex Learning Management System and instead pursued a specialized freelancer utility.

January 12, 20264 min read
The SaaS Pivot: From Broad Visions to Utilitarian Reality

I recently spent some time planning out a new Learning Management System (LMS) project. It was an ambitious technical challenge, but as I got deeper into the details, I decided to pivot. It wasn't just about the code; it was about the fundamental friction of the business model.

An LMS is a "content first" platform. It requires creators to spend weeks building courses before they see a single cent. For a solo developer without an existing pipeline of leads or a library of content, this creates a massive cold-start problem. I realized I was drifting toward the IKEA Effect—valuing the project more because of the technical complexity I was trying to master. As the Cognitive Load of the project grew, it became clear that the path to success was too narrow.

So, I shifted gears toward a utility with zero adoption friction.

Introducing WebsiteSellerHelper—a specialized tool designed to handle the friction-heavy parts of the freelancer-client relationship: contracts, revisions, and secure asset delivery.


1. The Anatomy of a Pivot

The transition was about moving from a project that required "mass adoption" and "content creation" to one that provides immediate, individual value. My goal shifted from user engagement to Workflow Integrity.

The core features are built to solve the "trust" and "numbness" (as discussed in The Numb UI) often found in freelance management:

  1. Binding Contracts: Instead of back-and-forth emails, the app generates and records eIDAS-compliant signatures directly in the workflow.
  2. The Revision Counter: A transparent, database-enforced limit on project revisions. This prevents scope creep before it starts.
  3. Milestone Protection: Project assets are only unlocked for the client once milestones are approved and the project state is updated correctly.

2. Technical Implementation: Type-Safe Workflows

By narrowing the scope, the project became technically simpler but far more resilient. I used Drizzle ORM and PostgreSQL to enforce business logic at the storage layer.

Take, for example, the milestones and projects relationship. We model the project lifecycle directly into the schema to ensure that state transitions are deterministic:

export const projects = pgTable("project", {
    id: uuid("id").defaultRandom().primaryKey(),
    creatorId: text("creator_id").references(() => users.id).notNull(),
    clientId: text("client_id").references(() => users.id).notNull(),
    status: varchar("status", { length: 50 }).notNull().default("draft"), 
    totalRevisions: integer("total_revisions").notNull().default(0),
    usedRevisions: integer("used_revisions").notNull().default(0),
});

export const milestones = pgTable("milestone", {
    id: uuid("id").defaultRandom().primaryKey(),
    projectId: uuid("project_id").references(() => projects.id).notNull(),
    status: varchar("status", { length: 50 }).notNull().default("pending"), 
    price: decimal("price", { precision: 10, scale: 2 }).notNull(),
});

By applying the principles of Reliable Failure, every state transition is handled carefully to ensure the database remains the ultimate source of truth for both the creator and the client.

3. Real-time Communication: Beyond the Request-Response

One of the most satisfying technical additions was the real-time project chat. While many developers reach for heavy external services, I opted for a high-performance WebSocket-based interaction (using Server-Sent Events) backed by PostgreSQL's LISTEN/NOTIFY protocol.

This allows for instantaneous communication between freelancers and clients with minimal overhead. When a message is saved to the database, Postgres triggers a notification that is immediately picked up by the listener and pushed to the connected client.

// The Postgres Listener logic for real-time updates
listener.listen("new_message", (payload) => {
    const data = JSON.parse(payload);
    const targetProjectId = data.projectId;

    subscribers.forEach(({ projectId, controller }) => {
        if (projectId === targetProjectId) {
            const eventData = `data: ${JSON.stringify({ type: "new_message", ...data })}\n\n`;
            controller.enqueue(new TextEncoder().encode(eventData));
        }
    });
});

The result is a snappy, reliable chat interface that feels as responsive as a desktop application, ensuring that discussions about revisions and milestones happen in real-time.

Project Chat Interface


4. Monetization: The Subscription Model

Initially, I considered a transaction-fee model. However, fees create a perverse incentive: if the platform takes a cut of every payment, users will inevitably try to move the transaction off-platform to save money.

Instead, WebsiteSellerHelper follows a Subscription-Based Model.

By charging a monthly fee for access to the specialized tooling—the contract generator, the revision tracker, and the secure asset vault—the platform becomes a professional tool rather than a tax on earnings. This aligns with the Software Minimalism philosophy: users pay for a clear, focused tool that provides immediate value without requiring them to build a complex ecosystem first.


5. Why Utilitarian Software Wins

When you build a utility, you aren't fighting for "mass adoption" or "content." You are fighting for efficiency.

The shift from a broad LMS to a focused utility has reinforced the importance of eliminating the "cold start." I no longer have to worry about how to get creators to build content on my platform; instead, I've built a tool that makes their existing life as a freelancer easier from day one.

The lesson is simple: Technical feats are fun, but solving practical friction for a single user is what builds a sustainable business.


To explore the philosophy behind this approach, read more on Software Minimalism and Architect's Ego.

Federico Cervelli

Federico Cervelli

Computer Science graduate and Software Developer at CAEN S.p.A. This blog is my digital lab for architectural deep-dives, technical experiments, and personal reflections.