pastmonday.com is live. It has auth, a weekly calendar, tiered billing with Stripe, referral credits, file uploads, and an AI chat that knows your calendar. A small but complete SaaS, the kind of thing that used to be a three-month project.

Two things about it are unusual, and they're the reason for this post.

First: I didn't hand-write it. A software factory did.. four reusable Claude Code skills that turn a one-page brief into a shipped product, stage by stage. I talked about this on YouTube recently, and the skills themselves are public on GitHub.

Second: look at the vendor list. Postgres is Neon. Auth is Neon. The data API is Neon. Object storage is Neon. The LLM calls go through Neon. Stripe handles money and my own cluster serves the containers, and that's the entire list. The backend is one vendor, and until a few weeks ago that sentence was impossible to say, because half of these services didn't exist.

Neon announced they're building the full backend: Postgres, Auth, and the Data API are GA, and Object Storage, Functions, and an AI Gateway just entered private preview. I got early access, pointed the factory at all of it, and this post is the build report.

Note: this post is a transcription of my video on software factories, passed through AI and edited for reading. If you'd rather watch than read, here it is:

TL;DR

  • A software factory, four reusable Claude Code skills reading one PROJECT.md brief, shipped pastmonday.com from empty repo to production in about 40 minutes.
  • The entire backend is Neon: Postgres, Auth, and Data API (GA), plus Object Storage and AI Gateway (private preview, early access).
  • Money and limits are server-authoritative: atomic single-statement quota consumes, idempotent Stripe webhooks, AI budgets checked before every call.
  • The AI Gateway's official SDK provider wasn't installable yet, so the agent verified the OpenAI-compatible endpoint live and shipped anyway.. the API-first thesis from my last Neon post, proven again.
  • Neon now ships agent skills for their new services. The factory and the platform are converging.

Resources


The software factory


The core idea is one separation: the skill is the HOW, the brief is the WHAT.

Everything project-specific lives in a single PROJECT.md in the repo: name, one-liner, the plans table, the palette and fonts, the entities, which services are enabled. Everything reusable lives in the skills. When I want a different product, I write a different brief. The factory doesn't change.

There are four stages, each a separate skill, each reading that same brief:

  1. Foundation (set-project-structure) builds the skeleton: Next.js with the directory contracts, the Drizzle schema, env keys with comments on where to get each value, design tokens, and placeholder clients for every enabled service. It deliberately builds less: seams, not features.
  2. Landing (set-landing-page) is the taste stage. It studies the brief's reference sites, writes real copy before layout, and works against an explicit banned-patterns list: no gradient hero, no "Supercharge your workflow", no fake testimonials.
  3. Backend (set-app-backend) is the correctness stage. Money and limits. Every quota, credit, token budget, and dollar is enforced on the server, atomically, idempotently. More on this below, because this is where Neon's new services plug in.
  4. Dashboard (set-dashboard) builds the app people live in: the calendar, the modals, the streaming AI chat, consuming only the contracts stage 3 exposed.

Each stage stops at an approval gate before building, verifies current package versions instead of trusting its training data, and must leave the repo shippable when it ends. No half-built sections, no "we'll polish later".

Click through the stages here.. this is the actual pipeline that built pastmonday:

I've written the first three stages up in detail before, if you want the deep dives: the concept, the brief, and the landing page.

What matters for this post: a factory like this is only as good as the surfaces it builds on. Stage 3 is where the factory has to wire auth, storage, data access, and LLM calls, and that's usually where you accumulate vendors. One for identity, one for buckets, one for model routing, plus the database. Four dashboards, four bills, four sets of credentials to leak.

This time, all four seams landed on the same platform.


One backend


Here's what pastmonday actually runs on, and the state of each piece:

Service Role in pastmonday Status
Postgres entries, profiles, billing, referrals, asset metadata GA
Neon Auth signup, login, sessions, the identity table GA
Data API PostgREST-style HTTP reads GA
Object Storage user file uploads, S3-compatible private preview
AI Gateway all LLM calls, metered per request private preview

A few receipts from the codebase, because "it works" is cheap to say.

Auth ships its own schema. Identity lives in neon_auth.user, and the factory's rule is: never mirror it. App tables hold foreign keys straight into it, so there's no sync job, no webhook that copies users around, no second source of truth:

// Neon Auth's identity schema, referenced, never mirrored
export const neonAuth = pgSchema("neon_auth");
export const authUser = neonAuth.table("user", { id: text("id").primaryKey() });

// profiles FK straight into it
userId: text("user_id").notNull()
  .references(() => authUser.id, { onDelete: "cascade" }),

Storage speaks S3, so there's no proprietary SDK to learn. The client is the plain AWS SDK, and it auto-reads the endpoint from AWS_ENDPOINT_URL_S3. Uploads are presigned PUTs with keys scoped per user, and since a presigned PUT can't enforce a size limit, the confirm route does a HeadObject and deletes anything oversized. The interesting part: Neon's storage branches with your database. Every branch gets its own isolated storage state. Your files and your rows stop drifting apart across environments.

AI Gateway is one API for models from Anthropic, OpenAI, Google and others, with per-request logging and rate limits, running on the same gateway infrastructure Databricks says handles 125 trillion tokens a month. For the app it means one token in the environment instead of a drawer full of provider keys, and the model is a config value:

const provider = createOpenAICompatible({
  name: "neon-ai-gateway",
  baseURL: `${NEON_AI_GATEWAY_BASE_URL}/ai-gateway/mlflow/v1`,
  apiKey: process.env.NEON_AI_GATEWAY_TOKEN,
});
export const chatModel = provider(process.env.NEON_AI_GATEWAY_MODEL);

Poke around the real architecture here, every box is clickable:


Building on features that shipped last week


In the last Neon post I made one argument: Neon is API-first, so an agent can reach a primitive the moment it exists, before anyone builds it a button. I proved it by building a feature Neon hadn't shipped yet.

This build pushed that idea further than I expected, twice.

First, the AI Gateway is so new that its official AI SDK provider package wasn't even installable yet when the factory ran stage 3. A human would have stopped there. The agent didn't: it probed the gateway, found the OpenAI-compatible endpoint at /ai-gateway/mlflow/v1, verified it live with a real request, and wired the app through the AI SDK's generic OpenAI-compatible provider instead. The code carries a comment saying "swap to the official provider once it installs". That's what API-first buys you: the endpoint existed, so the missing package didn't matter.

Second, the convergence I didn't see coming: a week after I published my factory skills, Neon shipped agent skills of their own.. instruction files that teach coding agents how to integrate Functions, Storage, and the AI Gateway, installable with one command:

npx skills add neondatabase/agent-skills

Read that again from where I'm standing. I write skills that teach an agent how to build products. Neon now writes skills that teach the same agent how to consume their platform. The factory and the platform are meeting in the middle, and neither side needed the other's permission. This is what it looks like when a vendor treats agents as the primary developer.


The part that has to be exactly right


A factory that ships beautiful broken apps is a liability, so stage 3 is paranoid by design. pastmonday charges money and sells limits: Free gets 1 entry and a 5,000-token AI budget, Pro gets 10 entries and 20,000 tokens a cycle, Max is unlimited. Limits only mean something if they can't be raced.

One constraint made this sharper than usual: the factory wired Drizzle through Neon's HTTP driver, which doesn't do interactive transactions. No BEGIN, hold the lock, decide, COMMIT. So every money-critical operation had to become a single atomic statement. This is the actual entry creation, quota check and insert in one round trip:

WITH consumed AS (
  UPDATE billing
     SET used_this_cycle = CASE WHEN used_this_cycle < monthly_quota
                                THEN used_this_cycle + 1 ELSE used_this_cycle END,
         extra_credits   = CASE WHEN used_this_cycle >= monthly_quota AND extra_credits > 0
                                THEN extra_credits - 1 ELSE extra_credits END
   WHERE profile_id = ${profileId}
     AND (used_this_cycle < monthly_quota OR extra_credits > 0)
  RETURNING id
)
INSERT INTO calendar_entries (user_id, title, ...)
SELECT ${userId}, ${title}, ...
WHERE EXISTS (SELECT 1 FROM consumed)

Quota first, then credits, else nothing gets inserted and the caller gets a 402. Two concurrent requests can't both take the last unit, not because the code is careful, but because the statement can't be split.

The same paranoia runs through the rest: the AI budget is checked server-side before every gateway call and metered from real usage on finish, Stripe webhooks dedupe on event id in a processed_stripe_events ledger so a replayed event can't grant credits twice, and quota-exhausted returns a typed 402 the UI turns into an upgrade prompt instead of an error toast.

None of this is Neon-specific, but it's the standard the factory holds, and the new services slotted into it without a fight. That's the actual test of a backend platform: not the demo, the enforcement paths.


Where this goes: branches that fork the whole stack


My favorite Neon primitive has always been branching. I've built preview environments where every pull request gets its own database branch, created and destroyed by the agent through the API.

The new services extend that idea past the database. Storage state branches with your data today, and Neon manages Functions through the same CLI and API as everything else. The direction is obvious and they're saying it out loud: a branch should fork the backend, not just the schema.

For a software factory, that's the missing piece. Today my factory pipeline validates each stage against the production-shaped environment it builds. The version I want is: every factory run, every agent session, every experiment gets a full isolated copy of the backend.. rows, files, functions.. for the lifetime of a task, then vanishes. Database branching already proved this workflow for schema changes. Extending it to the whole backend turns "spin up a staging environment" from an afternoon of Terraform into a flag on a CLI call.

That's the same story as the spending-caps feature from my last post, which is still marked "coming soon" by the way, and I'm still holding them to it: the primitives ship first, through the API, and the people building on top get to run ahead of the roadmap.


Closing


The pitch for this stack isn't "Neon does everything". It's narrower and more honest: a full working SaaS.. identity, data, files, AI, money.. now fits in one brief, four skills, one backend vendor, and one Stripe account. pastmonday went from empty repo to production on my cluster in about 40 minutes, and most of that time I was making taste decisions at the approval gates, not doing integration work.

If you want to go deeper: the video covers the factory concept, the skills are on GitHub to steal, the series walks each stage, and pastmonday.com is the living proof.. go create an entry, that's a race-safe atomic quota consume you're clicking.

And if you're at Neon: ship the branch-forks-everything future. I have a factory waiting for it.