QIAOPANG.COM · SELECTED ESSAYS (2013–2026) · 260 ESSAYSBrowse Chronologically (2013 → 2026) ↗
QiaoPang · Programmers LifeSelected Essays · Systems, Craft & Agentic Era
Timeline ↗

The One-Person Company: How to Build Fast Once the Foundation Is Laid?

The One-Person Company: How to Build Fast Once the Foundation Is Laid?

A nine-story tower rises from a heap of earth; a journey of a thousand miles begins with a single step. — Tao Te Ching

Preface: This is the fifth installment in the “One-Person Tech Company” series. The concept of OPC (One Person Company) is all the rage these days, so I thought I’d give it a try—to see what can really be accomplished if I seriously commit my weekends to doing the kind of work that would normally take an entire tech company. This doesn’t mean I’m going full-time startup. I consider myself a perpetual entrepreneur on the road; a nine-to-five was never a cage for me. Through this process, I want to learn the boundaries of AI—and my own.

The whole series documents the complete process of building a full technology stack from zero—from infrastructure, to networking and runtime, from the core framework to application services. It’s not a tutorial, but a field journal that captures the thinking along the way.

Over the first four installments, we’ve ground our way through it all: building the network and security boundary, standing up the cloud infrastructure, forging the serverless application framework, and rounding out the internal toolchain. Each layer paved the way for the one above it.

If the first four installments were about laying the foundation, raising the steel frame, and running the pipes, then today’s piece finally begins to “build the building.”

The core question of this article is: when you’re a solo operator holding a carefully designed set of infrastructure, how fast can you go from a product idea to a live deployment? The answer may be beyond your imagination.

One weekend. Truly, just one weekend.

I. From Idea to Product: The Speed of One

What I wanted to build was a slide deck application for the AI era.

This app started as a project in a Geek Time AI bootcamp. One late night, while slacking off and trying every AI PPT-generation tool I could get my hands on, a thought suddenly popped into my head: what if I could have AI generate a distinct image for each individual slide, with a unified visual style, then pair it with the text content to produce a fully AI-driven illustrated presentation—what would that look like? NotebookLM’s slide generation partially satisfies this need, but it offers no fine-grained control.

From that idea to a first working prototype, I spent an hour or two using Python + FastAPI + React. Fast enough, but the code quality… let’s just say “it’s not like it doesn’t work.” Classic prototype code: hot data crammed into memory, cold data dumped into files, no auth, no persistence, no deployment. Later I used it frequently to generate all kinds of presentations, and at some point I started to want it online so I could access it anywhere, anytime. And once it’s going online, it can’t remain a “just get it running” prototype—it has to be a proper production-grade application.

Think about it: to turn such a prototype into a production product, you’d have to handle authentication and authorization, persistent storage, CDN caching, secret management, multi-environment deployment, domain certificates, logging and monitoring… In a traditional team, these “non-functional requirements” alone would devour weeks or even a month. But when you’re holding a well-suited set of infrastructure, a serverless framework that already does most of the work, plus a powerful AI coding tool like Claude Code, the picture looks entirely different.

In actual practice, going from prototype to production-grade application—complete with authentication, data persistence, AI integration, CDN configuration, and multi-environment deployment—took less than a day from start to finish. Throughout that day, Claude Code carried a huge amount of the heavy lifting: generating backend modules from design docs, writing frontend components, troubleshooting deployment issues, refining the data model. And the reason it all flowed as smoothly as an assembly line is fundamental: the infrastructure was clear enough, grounded in the operon serverless framework I’d written myself, so Claude Code had rules to follow and a framework to lean on.

This leads to a core insight: there is a multiplier effect between infrastructure investment and AI coding tools. Infrastructure makes the project structure crystal clear, letting AI coding tools produce efficiently; and AI’s efficient output in turn gives you the headroom to polish your infrastructure even further. The two form a flywheel that spins ever faster. With good infrastructure but no AI, you’re still coding line by line; with AI but no good infrastructure, AI can only produce scattered, hard-to-integrate code snippets. It’s the combination of the two that is the real silver bullet of the one-person company.

II. The Workspace Architecture: Letting Applications Divide Like Cells

Back to the most fundamental question: with the infrastructure framework in place, how should application code be organized?

Why a Workspace?

If you open a separate repository for every application, you’ll soon be crushed by code duplication. The AI image-generation logic is needed by the slides app, and will be needed by a future docs app; the edge authentication logic is unavoidable for every user-facing application; and common types like pagination and user identity are flying around everywhere.

The answer is Rust’s workspace mechanism. Put multiple applications into a single workspace and eliminate duplication through shared crates:

workspace/
├── crates/                   # Shared libraries
│   ├── golgi-core/           # Common types: pagination, user identity, subscription tier
│   ├── golgi-ai/             # AI capabilities: image-generation trait + multiple providers
│   └── golgi-auth-edge/      # Edge auth: CloudFront Function generation
│
├── apps/                     # Applications
│   ├── slides/               # Slides API (Lambda Function URL)
│   └── slides-worker/        # Async image generation (SQS Worker Lambda)
│
└── Cargo.toml                # Workspace root config

The beauty of this structure is: the cost of adding each new application approaches zero. Shared crates provide common capabilities, the application framework (operon) provides the runtime and deployment pipeline, and you just focus on the application’s own business logic. Even better, this tidy directory structure is like water to a fish for Claude Code—at a glance it can tell which parts are shared capabilities, which are application code, and where a new app should go. When I ask Claude Code to create a new application, it automatically scaffolds it by following the structure of existing apps.

The Craft of Workspace Dependency Management

Centralizing all dependency versions in the workspace’s root Cargo.toml looks simple but is in fact crucial:

[workspace.dependencies]
# Internal crates
golgi-core = { path = "crates/golgi-core" }
golgi-ai = { path = "crates/golgi-ai" }

# Application framework (referencing a private registry)
operon = { version = "0.3.1", registry = "chromatin", features = ["dynamodb", "s3", "sqs", "oidc"] }

# Unified versions for external dependencies
axum = "0.8"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.49", features = ["rt", "rt-multi-thread", "macros"] }

What’s the point of this?

First, version consistency. Every crate uses the same version of axum, tokio, and serde. Dependency conflicts? They don’t exist.

Second, atomic upgrades. Bump a dependency in one place, and every crate follows in lockstep—no need to flip through files one by one.

Third—and most easily overlooked—it lays out the runway for AI. When I say in Claude Code, “help me create a new application,” it simply consults the workspace root config and knows exactly which dependencies to use, which versions, what project structure—it even knows precisely how to enable operon’s feature flags. I don’t need to repeat the context; Claude Code can infer everything from the project structure itself.

This leads to a deeper realization: good architecture isn’t just designed for people—it’s designed for AI.

Think it over: AI coding tools understand your code in a way that’s actually quite similar to how humans do—they look at the directory structure first, then the config files, and only then dig into the specific code. The difference is that humans can fill in the missing context from experience, whereas AI relies more on explicit, structured information. So: the tidier the project structure, the clearer the conventions, the more centralized the configuration, the higher the quality of AI’s output.

In other words, the good architecture you design for AI happens to be the most human-friendly architecture too. This is no coincidence—clarity and consistency are themselves core traits of good architecture. AI simply shortens the feedback loop on “is the architecture clear?” down to real time: if the structure isn’t clear, AI immediately hands you a pile of code that doesn’t fit; if the structure is clear, AI’s output is directly usable.

III. Shared Crates: Turning Capabilities into Building Blocks

Let’s look at how those shared crates are designed, and why this design is a necessity for a one-person company.

The Common Types Layer

The lowest layer of shared crates provides common types used across applications. These types look unassuming, but they define the “common language” of all applications:

/// Pagination parameters — used by every list endpoint
pub struct PaginationParams {
    pub limit: Option<u32>,
    pub cursor: Option<String>,  // Cursor-based pagination, ideal for DynamoDB
}

pub struct PaginatedResponse<T> {
    pub items: Vec<T>,
    pub next_cursor: Option<String>,
}

/// User identity — extracted from JWT, shared across all apps
pub struct UserIdentity {
    pub user_id: String,
    pub email: String,
    pub name: String,
    pub picture: Option<String>,
    pub subscription_tier: SubscriptionTier,
}

/// Subscription tier — reserved for a future billing system
#[derive(Default)]
pub enum SubscriptionTier {
    #[default]
    Free,
    Pro,
    Team,
}

Notice the SubscriptionTier enum? In v1, every user is a Free tier, and the paid features haven’t been built at all. But this type is already baked into the data model and the JWT claims.

MORE IN AI & Autonomous Agents

Further Reading in This Column

View all essays in “AI & Autonomous Agents” →