{"slug": "i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack", "title": "I Built an AI-Powered Education Platform as a Solo Founder - Here's My Full Stack", "summary": "A solo developer built TopoForest, an AI-driven business education platform for indie builders, using Next.js, Koa, PostgreSQL, and Prisma. The platform integrates WeChat OAuth and Aliyun services to operate within China's internet ecosystem. The developer chose Koa over Next.js API routes for handling WeChat's complex authentication flows.", "body_md": "After 6 months of nights and weekends, I shipped [TopoForest](https://topforest.cn) - an AI-driven business education platform for indie builders going global. No co-founders, no VC funding, no team. Just me, a keyboard, and an unhealthy amount of coffee.\n\nIf you're a solo dev wondering whether you can actually pull off a SaaS by yourself, the answer is yes - but you'll need to be surgical about your tech choices. Here's the full stack I used, the trade-offs I made, and what I'd do differently.\n\nTopoForest is a learning platform that teaches OPC builders (solo entrepreneurs running a one-person business) how to leverage AI in their daily operations. It has video courses, user accounts, phone verification, and WeChat integration. All of it needs to work in China, which means dealing with the Chinese internet ecosystem - a whole different beast.\n\nHere's the architecture at a glance:\n\n```\n????????????????????     ????????????????\n?  Next.js + Koa   ? ??? ?  PostgreSQL  ?\n?  (Vercel)        ?     ?  (Prisma)    ?\n????????????????????     ????????????????\n         ?\n         ?\n????????????????????????????????\n?  Aliyun OSS (Video/Image)   ?\n?  WeChat OAuth + Aliyun SMS  ?\n????????????????????????????????\n```\n\nSimple enough, right? Let me walk through each piece.\n\nI picked Next.js for two reasons: **it's boring technology** (in the best way), and the App Router handles both frontend and API routes in one codebase.\n\nI started with Pages Router, but App Router won me over with:\n\n`route.ts`\n\nfiles for lightweight API endpoints that don't need the full backend treatment.App Router is not all sunshine. The caching behavior is confusing at first - I spent a full evening debugging why a page kept showing stale data. Turns out I needed to call `revalidatePath()`\n\nin the right place. Once you internalize the mental model, it's fine, but the learning curve is real.\n\n``` js\n// Example: revalidating after a course progress update\nimport { revalidatePath } from 'next/cache';\n\nexport async function updateProgress(courseId: string, data: ProgressData) {\n  await prisma.courseProgress.upsert({\n    where: { userId_courseId: { userId: data.userId, courseId } },\n    update: data,\n    create: { ...data, courseId },\n  });\n  revalidatePath(`/courses/${courseId}`);\n}\n```\n\n**Verdict**: Worth it. The DX is great once you're past the initial hump.\n\n\"Why a separate backend?\" - this is the question I get asked most.\n\nThe answer: **WeChat OAuth and ecosystem integration**.\n\nNext.js API routes are fantastic for simple CRUD, but when you're dealing with WeChat's callback mechanism, token exchange flows, and the need to track redirect statistics (click-through rates, visit sources, user agents), a dedicated backend framework keeps your codebase organized. I chose Koa for the API layer while keeping the frontend on Next.js - both running on Vercel.\n\nHonest answer: I just like Koa better. The middleware is cleaner - no callback hell, proper async/await from the ground up. Express middleware often feels like you're fighting the framework. Koa gets out of your way.\n\n```\n// Koa middleware for tracking redirect visits\nasync function trackRedirect(ctx: Context, next: Next) {\n  const { source, menuKey, openid } = ctx.query;\n\n  await prisma.trackVisit.create({\n    data: {\n      source: source as string,\n      menuKey: menuKey as string,\n      openid: openid as string,\n      ip: ctx.ip,\n      userAgent: ctx.headers['user-agent'],\n      referer: ctx.headers.referer,\n    },\n  });\n\n  await next();\n}\n```\n\nI initially tried using `koa-connect`\n\nto wrap Express middleware in Koa. Don't do this. It caused mysterious context leaks that took me a full weekend to track down. Write native Koa middleware. Yes, it's more work upfront, but you'll thank yourself later.\n\n**Verdict**: If you don't need WeChat-level ecosystem integration, Next.js API routes alone would be fine. But for my use case, Koa was the right call.\n\nI've used raw SQL, Sequelize, TypeORM, and Drizzle. Prisma is the first ORM I actively enjoy using.\n\n`prisma db push`\n\n, and instantly get fully typed queries. My IDE autocompletes every field. I haven't written a misspelled column name in months.`schema.prisma`\n\nfile is a single source of truth. When I onboard a contributor (someday), they can read one file and understand the entire data model.One rule I set early: **never physically delete data**. Every table has an `enabled`\n\nboolean field. Deletion is just setting `enabled = false`\n\n.\n\n```\nmodel Course {\n  id        Int      @id @default(autoincrement())\n  title     String\n  enabled   Boolean  @default(true)\n  createdAt DateTime @default(now())\n  updatedAt DateTime @updatedAt\n}\n```\n\nThis means every query needs a `where: { enabled: true }`\n\nfilter. It's a minor annoyance, but it's saved me multiple times when a user accidentally deleted something and I could just flip a flag back.\n\n`db push`\n\ninstead of `migrate`\n\n?\nI use `prisma db push`\n\nto sync the schema. No migration files, no versioning headaches. For a solo developer shipping fast, migration files are overhead I don't need. If I ever bring on a team, I'll switch to proper migrations, but for now, `db push`\n\nkeeps me fast.\n\n```\nprisma db push  # sync schema, no migration files\n```\n\n**Verdict**: Prisma is a joy. The autocomplete alone is worth the price of admission (which is free, so that's a pretty good deal).\n\nWeChat is the gateway to the Chinese internet. If your product targets Chinese users, you can't skip WeChat integration. But it's also the most painful part of the stack.\n\nUsers click a WeChat menu link ? they hit my backend ? I redirect to WeChat's OAuth page ? WeChat sends back a code ? I exchange it for an `openid`\n\n? I redirect the user to the actual content page.\n\nAll of this happens silently (`snsapi_base`\n\nscope), so the user doesn't see an authorization popup. It's fast, it's seamless, and it took me a week to get right.\n\n`topforest.cn`\n\n.`state=home`\n\n, `state=courses`\n\n, or `state=account`\n\nto track which menu item the user clicked. This feeds into my analytics.Every WeChat menu click goes through a tracking endpoint. I log the source, menu key, and openid, then issue a 302 redirect:\n\n```\n// Simplified redirect handler\nrouter.get('/api/v1/track/redirect', trackRedirect, async (ctx) => {\n  const { state } = ctx.query;\n  const targetUrl = getTargetUrl(state as string);\n  ctx.status = 302;\n  ctx.redirect(targetUrl);\n});\n```\n\n**Verdict**: The hardest part of the stack, but also the most valuable. WeChat integration is a moat - competitors can't just copy it.\n\nI host video courses on Aliyun OSS (Object Storage Service). It's cheap, fast, and integrates well with the rest of the Alibaba Cloud ecosystem.\n\nVideos are private by default. When a user requests a course video, my backend generates a signed URL with a time-limited expiration. This prevents hotlinking and keeps my bandwidth costs under control.\n\n``` python\nimport OSS from 'ali-oss';\n\nconst client = new OSS({\n  region: 'oss-cn-hangzhou',\n  accessKeyId: process.env.OSS_ACCESS_KEY_ID!,\n  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,\n  bucket: process.env.OSS_BUCKET!,\n});\n\nasync function getSignedUrl(objectKey: string): Promise<string> {\n  return client.signatureUrl(objectKey, { expires: 3600 }); // 1 hour\n}\n```\n\nWhen I first deployed, videos were returning 404 errors. I was confused for hours. Turns out I had forgotten to set the `OSS_ACCESS_KEY_ID`\n\n, `OSS_ACCESS_KEY_SECRET`\n\n, and `OSS_BUCKET`\n\nenvironment variables. Without them, OSS was returning unsigned URLs - which means public access is denied. Now I have a startup check that validates all three exist before the server starts.\n\n**Verdict**: Great value, but triple-check your env vars. The error messages are not helpful.\n\nPhone verification is standard in China, not email. I use Aliyun SMS for sending verification codes.\n\nYou need to configure a template in the Aliyun SMS console, then reference it in your code:\n\n``` python\nimport Dysmsapi from '@alicloud/dysmsapi20170525';\n\nconst client = new Dysmsapi({\n  accessKeyId: process.env.ALIYUN_SMS_ACCESS_KEY_ID!,\n  accessKeySecret: process.env.ALIYUN_SMS_ACCESS_KEY_SECRET!,\n});\n\nasync function sendVerificationCode(phone: string, code: string) {\n  await client.sendSms({\n    phoneNumbers: phone,\n    signName: process.env.ALIYUN_SMS_SIGN_NAME!,\n    templateCode: process.env.ALIYUN_SMS_TEMPLATE_CODE!,\n    templateParam: JSON.stringify({ code }),\n  });\n}\n```\n\nThe template code and sign name must match exactly what you configured in the Aliyun console. If either is wrong, the API returns a cryptic \"template not found\" error. I wasted half a day on this.\n\n**Verdict**: Works well once configured, but the setup is finicky. Double-check every string.\n\nI deploy both the frontend and the Koa backend on Vercel. The frontend uses Vercel's native Next.js hosting, and the Koa API runs as a serverless function on the same Vercel project - no separate server, no dual-infrastructure headache.\n\n`topforest.cn`\n\n)`/api/v1`\n\n`NEXT_PUBLIC_BACKEND_URL=https://topforest.cn`\n\nin Vercel's environment variablesI don't want to think about infrastructure. Vercel handles SSL, CDN, and the deployment pipeline. I push to `main`\n\n, and it's live in 2 minutes. For a solo developer, that's priceless.\n\nKeeping everything under one roof means:\n\n**Verdict**: If you're a solo dev, put everything on Vercel. You have better things to do than configure nginx.\n\nNo project is perfect. Here's what I'd change if I were starting over:\n\nI shipped this as a solo founder. Here's what that looks like in practice:\n\nIs it profitable yet? Not yet. But it's shipping, it's getting users, and I'm learning more than any tutorial could teach me.\n\nIf you're on the fence about building your own SaaS as a solo developer, here's my honest take:\n\n**The tech stack is not the hard part.** Next.js, Prisma, PostgreSQL - these are all well-documented, battle-tested tools. The hard part is everything else: figuring out what to build, staying motivated when nobody's using it, and shipping through the discomfort of \"this isn't ready yet.\"\n\nBut if you can push through that, the tech side is genuinely fun. There's nothing quite like watching a user sign up for something you built entirely by yourself.\n\nI'm currently working on:\n\nIf any of this resonates, I'd love to hear your story. What's your tech stack? What did you build? Drop a comment - I read every single one.\n\n*You can check out TopoForest at topforest.cn. I'm also on X (Twitter) sharing my build-in-public journey - come say hi!*", "url": "https://wpnews.pro/news/i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack", "canonical_source": "https://dev.to/jackhan312/i-built-an-ai-powered-education-platform-as-a-solo-founder-heres-my-full-stack-3557", "published_at": "2026-07-08 08:50:42+00:00", "updated_at": "2026-07-08 08:58:37.701334+00:00", "lang": "en", "topics": ["artificial-intelligence", "developer-tools", "ai-products"], "entities": ["TopoForest", "Next.js", "Koa", "PostgreSQL", "Prisma", "WeChat", "Aliyun", "Vercel"], "alternates": {"html": "https://wpnews.pro/news/i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack", "markdown": "https://wpnews.pro/news/i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack.md", "text": "https://wpnews.pro/news/i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack.txt", "jsonld": "https://wpnews.pro/news/i-built-an-ai-powered-education-platform-as-a-solo-founder-here-s-my-full-stack.jsonld"}}