Skip to content
NewClientOS is live — the self-hosted client portal for agencies.
work/clientos

Product · Agency operations

ClientOS

Service checkout, a branded client portal, delivery tracking, helpdesk and billing for agencies selling productized services, on the agency’s own server.

  • Self-hosted platform · Client portal
  • 2026
ClientOS — Product · Agency operations

Customer story · Dot Mirror

A link building agency left Wayfront and owns its portal now.

Our partners trust us with their clients’ names, and for years that list sat on someone else’s servers. ClientOS put the whole operation on our own server, under our own name, and the monthly bill simply went away.

Shimanto NeerFounder, Dot MirrorRead the full story

What changed

monthly portal bill, one license paid once
$0
kept over three years against Wayfront Pro
$6,274
of client history moved: orders, messages, invoices, files
100%
from install to live on clients.dotmirror.com
7 days

A white-label link building and digital PR agency, moved with its partners, orders and years of history onto its own server in one week.

About ClientOS

Introduction

Agencies that sell productized services — link building, SEO, content, editing — tend to run on a patchwork: a form here, an invoice there, status updates by email, and a spreadsheet holding it together. ClientOS replaces the patchwork with one platform the agency runs on its own server. Clients order from service pages that are also the checkout, track delivery and approve work in a branded portal, and pay through subscriptions with automatic dunning; the agency runs orders, helpdesk and reporting from a role-gated admin, with margin visible to the agency and never to the client.

Details

Project
ClientOS
Timeframe
2026
Type
Self-hosted platform · Client portal
Stack
  • Next.js
  • NestJS
  • PostgreSQL
  • Redis
  • Drizzle
  • Stripe
  • Playwright
  • Docker
  • Caddy
Problem
Selling and delivering productized services across forms, email, invoices and spreadsheets means slow updates, lost context and no clear view of margin per order.
What we built
A platform with service pages that take the order (packages, add-ons, coupons), a branded client portal, delivery with client approval, a helpdesk with response targets, recurring billing with automatic retries and margin reporting per service — installed on the agency’s own server, one install per agency.
Outcome
Shipped as ClientOS, a licensed product agencies install on their own server with one command. Client data stays on that server; only the license check-in reaches us.
staff permissions, across built-in and custom roles
122
payment gateways: Stripe, PayPal and three for crypto
5
default order statuses, each one the agency can edit
6
command to install it on the agency’s own server
1

Inside the admin.

The console an agency runs its orders, clients and money from, rebuilt here in code from its own screens. Pick a page, or click the sidebar.

ClientOS — Dashboard

Money, throughput, and what is about to slip

The ops dashboard is put together panel by panel from the viewer’s role: the month’s revenue and margin, whose move each open order is waiting on, what is past its promise, and how loaded each person on the team is.

  • Revenue, collected and gross margin
  • Waiting on us, or on clients
  • Past the promise, on our time
  • Team capacity per person

Recreated from the admin’s interface. Labels, columns and statuses are ClientOS’s own; the agency, clients, people, orders and figures are samples.

The parts, up close.

The workings behind the admin and the portal, at full size.

What went into it.

  1. 01

    Sell

    Service pages with packages, add-ons, volume pricing and coupons, priced on the server, with the brief collected in the portal once the order is paid.

  2. 02

    Deliver

    Six default order statuses the agency can rename, client approval or a revision request on each hand-over, and a helpdesk whose response clock pauses while waiting on the client.

  3. 03

    Get paid

    Recurring invoices charged to a saved card with automatic retries, invoices in the portal, and margin reporting that never exposes cost to clients.

How it is built.

The running parts

Portal and admin
Two Next.js apps, one for clients and one for the agency, sharing a design system. Every write goes through a server action.
API
NestJS on Fastify, and the only process with a database connection.
Domain package
Pricing, statuses, response targets and permissions as plain functions with no framework in them, which is where most of the tests live.
Data
PostgreSQL through Drizzle, which is also the job queue. Redis is optional, for presence only; files go to S3-compatible storage.
Deployment
Ready-built Docker images behind Caddy, which handles HTTPS and is the only container with open ports, with a migration step that runs before the API starts.

The hard parts

  1. 01

    One install, one agency

    Each agency runs its own copy, so its clients’ data never shares a database with anyone else’s. Inside it, each client company sees only its own orders, and the API connects as a least-privilege role, refusing to start in production as a superuser.

  2. 02

    Cost never reaches a client

    Responses are built against a whitelist of fields, and the version with cost in it is chosen only for staff allowed to see finance. Portal queries never select cost, and a test walks every response looking for anything named cost or margin.

  3. 03

    A license that survives a bad connection

    The license is signed and bound to the agency’s domain, and the install checks in twice a day. If it cannot, a seven-day grace period runs before the admin turns read-only; the client portal and the data are never touched.

  4. 04

    A response clock that pauses fairly

    When a ticket is waiting on the client, the clock stops. When it resumes, the due time moves by exactly the length of the pause — or by the open time left, when business hours are on.

  5. 05

    Recurring billing without charging twice

    The platform keeps its own renewal clock and raises one invoice per cycle, which the database enforces. The saved card is charged with a key unique to that invoice and attempt; a failed charge is retried on days one, three and five before the plan is paused.

  6. 06

    One price, settled once

    A single function applies base price, add-ons, volume discount, promo and credit in that order, for the checkout and the server alike. Payment can be confirmed by the return page, a webhook or a reconcile job, and a row lock makes sure it counts once.

Start here

Have a problem worth solving?

Tell us what is slow, manual or missing. You will hear back within one working day — then get a written scope and a fixed quote, or an honest no.

brief.md
  1. # New project brief
  2. ## What is slow, manual or missing?
  3. - [x] Written scope
  4. - [x] Fixed quote
  5. - [x] Or an honest no
Reply within one working daySend brief
Message Us