How I Built an AI SaaS Platform as a Solo Developer
Building a production SaaS platform by yourself sounds like a lot. And it is. But with the right stack choices it becomes way more manageable than you'd think.
Over the past year I built an AI-powered creative workflow tool for Shopify merchants. It went from the first commit to a live product with paying users. I want to share what actually worked and what I got wrong.
Why the Stack Matters More When You're Solo
When you're the only developer every technology choice is a bet on your own speed. I didn't have a team to split responsibilities so I needed tools that would handle entire categories of problems for me.
Here's what I went with:
- Next.js + TypeScript for the full stack. Server components and API routes meant I could keep everything in one project. TypeScript saved me from myself more times than I can count.
- Supabase for the backend. Postgres with auth, real-time subscriptions, row-level security and storage built in. This alone replaced what would have been three or four separate services.
- Vercel for deployments. Zero config, preview URLs on every PR. I never had to think about CI/CD.
- Trigger.dev for background jobs. This was the biggest unlock. AI tasks like image generation and video processing can take minutes. Trigger.dev gave me durable workflows that retry from the exact step that failed instead of starting over.
Orchestrating AI Workflows
The core challenge was reliability. A single user request could trigger a multi-step pipeline: pull product data from Shopify, generate images, create videos, process the results then push everything back to the store.
Each step can fail independently and takes a different amount of time. I needed the whole thing to be retryable without re-running steps that already succeeded.
Trigger.dev solved this perfectly. Instead of building a custom queue I defined workflows as code:
export const generateCreativeAssets = task({
id: "generate-creative-assets",
run: async (payload: GeneratePayload) => {
const product = await io.runTask("fetch-product", async () => {
return shopifyClient.getProduct(payload.productId);
});
const images = await io.runTask("generate-images", async () => {
return aiClient.generateImages({
prompt: buildPrompt(product),
count: payload.imageCount,
});
});
const video = await io.runTask("generate-video", async () => {
return aiClient.generateVideo({
sourceImage: images[0].url,
duration: 5,
});
});
await io.runTask("update-shopify", async () => {
return shopifyClient.updateProductMedia(
payload.productId,
[...images, video]
);
});
},
});
If step 3 fails it retries from step 3. Not from the beginning. That single feature saved me weeks of building custom retry logic.
Row-Level Security Changed How I Think About Multi-Tenancy
I resisted Supabase's row-level security at first because it felt like extra setup. But for a multi-tenant SaaS it turned out to be incredibly powerful.
CREATE POLICY "Users can only see their own assets"
ON assets FOR SELECT
USING (auth.uid() = user_id);
With this in place I didn't need to add WHERE user_id = ? to every query. The database enforced data isolation at the lowest level. One less thing to get wrong.
Real-time subscriptions also let me build a live progress UI. Users could watch their AI generations happen step by step without any polling.
The Shopify Integration
Shopify's developer experience has improved a lot but it still has quirks. The OAuth flow and session management took more time than I expected. I built it as an embedded app so it runs directly inside the Shopify admin.
The custom extensions were my favorite part. Shopify UI Extensions let you inject custom interfaces right into the admin. Merchants could kick off AI generation directly from their product pages without switching contexts.
What I Got Wrong
I added billing too late. I built the whole platform before integrating Stripe. Payment flows touch almost everything though. Rate limits, feature gates, usage tracking. Retrofitting all of that was painful.
Not enough integration tests. Unit tests are fine for utility functions but the real bugs in a system like this happen at the boundaries between services. I should have written end-to-end tests for the full pipeline from day one.
Too much abstraction too early. I spent time building a provider-agnostic AI interface before I even needed it. YAGNI is real. Build for what you need right now.
Why Solo Can Be an Advantage
Working alone isn't just a constraint. It's a superpower in some ways.
I could ship features in hours instead of days. No waiting on PR reviews or scheduling meetings. When something wasn't working I could change the architecture immediately. I talked to users directly and pushed fixes the same day.
The trick is picking tools that eliminate whole categories of work. Supabase handled auth, database and real-time. Vercel handled deployments. Trigger.dev handled job queues. That freed me up to focus on the product itself.
The Numbers
Six months after launch the platform was processing thousands of AI-generated assets for merchants. Infrastructure costs stayed under $200/month thanks to serverless and Supabase's free tier.
If you're thinking about building a SaaS by yourself my advice is simple. Pick a boring stack. Solve a real problem. Ship faster than you're comfortable with. The market will tell you what to build next.
Have questions about building a SaaS solo? Reach out on LinkedIn or Twitter.