Skip to main content
Product2026-07-11 · 13 min read

How we built learnpython.academy in 2026: stack, decisions, honest weaknesses

learnpython.academy is a solo-operated interactive Python-learning platform: 1,100+ lessons across 10 tracks, 18 languages, in-browser code execution, purpose-built AI mentor on every lesson. This is the honest technical writeup. Stack, decisions, trade-offs, and what's genuinely still weak.

No VC funding. No team. Two years of work. Real numbers on request.

Stack

Frontend + edge:

  • Next.js 14 App Router — SSR, RSC boundaries, route groups, streaming
  • Deployed on Vercel Hobby (yes, Hobby — we bumped into every limit and stayed on Hobby)
  • 18 languages via message JSON + tServer + a custom fillNumbers placeholder system
  • No CDN dependencies for runtime — everything self-hosted

In-browser Python execution:

  • Skulpt for lesson editors — boots in ~200ms, small footprint, right for "run this 20-line snippet"
  • Pyodide for the /playground — real CPython in WASM, ~10MB download but full pandas / numpy / matplotlib
  • Two runtimes, zero installs. Never asks the learner to touch their local Python.

Backend:

  • FastAPI on a droplet (systemd + nginx reverse proxy)
  • Supabase for auth + Postgres + RLS + Storage
  • Redis for hot caches
  • Everything solo-manageable — no Kubernetes, no service mesh

Billing:

  • Paddle as Merchant of Record (they handle EU VAT + US sales tax + refunds)
  • Chose over Stripe specifically for MoR — Stripe is a payment processor, not a tax handler; for a solo-operated site selling in 100+ countries, MoR is table-stakes

Analytics:

  • Own first-party visit_logs table (RLS-scoped, GDPR-clean)
  • @vercel/analytics for real-time + Core Web Vitals
  • Custom /admin/analytics/monthly-report

AI mentor:

  • Vendor-independent wrapper (internal codename "Lambda") — model provider can swap without breaking learner experience
  • Purpose-built system prompt that teaches via hint-ladder, never solves
  • Server-side redaction: mentor prompt is built AFTER solution_code + expected_output + quiz correctIndex are stripped

The design choice I want to write about most: AI mentor that never sees the solution

Most "AI tutor" implementations glue ChatGPT onto a lesson editor. The tutor sees your task, sees your code, and knows the answer — because you passed it in. So it happily fixes your bug for you and hands you the working code.

That's not teaching. That's solving.

Our mentor is designed differently. When you click "ask mentor":

1. Server pulls the current lesson metadata (theory, task text, quiz options)

2. redactForTeaser() strips solution_code + test_cases[].expected_output + hint + quiz.correctIndex + quiz.explanation before the prompt is even built

3. The mentor prompt is assembled from what remains

4. The mentor literally cannot show you the answer, because it doesn't see the answer

This means if you ask "what's the answer to lesson 9", it says "I can't show you the answer, but here's what to look at on line 3" — because that's actually the truth. It's not being polite. It's a technical constraint on the code that builds the prompt.

Hint-ladder pattern:

  • Message 1: Question that makes you look at the specific line
  • Message 2: More specific question if you're still stuck
  • Message 3: The concept you should re-read from the lesson theory
  • Message 4 (only if you explicitly say you're giving up): here's the correction, with a note to re-read the theory

General LLMs go straight to message 4 by default. That's the difference.

Why FastAPI and not Django

For the API surface, we chose FastAPI:

  • Native async — the lesson-graders and AI-mentor endpoints benefit
  • Pydantic v2 for validation — one source of truth for request/response schemas
  • OpenAPI generation free — the /docs page renders from the schema automatically
  • Modern Python-first patterns (Protocol, TypedDict, dataclass slots)

Django would have been fine. Would have shipped faster in some ways because of admin. But the pain of async-Django and the overhead of Django ORM outweighed the admin gain for a two-person day-to-day (founder + AI mentor for content).

FastAPI-first is also what juniors are being interviewed on in 2026. Django is still used at enterprise but new EU / US scale-ups are FastAPI-first. That aligned our platform with the market we teach for.

Why Paddle and not Stripe

Paddle handles EU VAT, US sales tax, and international refunds as the Merchant of Record. Stripe does not (they're a payment processor — you're the merchant, you file the tax).

For a solo-operated site selling in 100+ countries:

  • Stripe: you file tax in every jurisdiction you sell to. Miss one, you owe back-tax + penalties.
  • Paddle: they file. Your job is to ship the product.

Trade-off: Paddle takes a higher cut (~5% vs Stripe's ~2.9%). Worth every basis point for a solo shop.

Immediate-cancel policy shipped with the Paddle migration in July: click cancel, billing ends immediately, not at end-of-period. Removes the "you're still paying weeks after cancel" complaint that kills SaaS retention indirectly (via bad word-of-mouth from users who felt trapped).

Why 18 languages

Because Python-learning content in native language dramatically outperforms translated content when the audience isn't native-English.

Every string on the site — lesson titles, task descriptions, error explanations, meta descriptions, JSON-LD FAQPage answers — is translated to 18 languages. Not machine-translated at render time; pre-translated and stored in messages/*.json + lesson-content-i18n.json + posts-i18n.json.

The translations run through a nightly Google-free pipeline with a placeholder-mask system so counters and prices stay literal in every language.

Serves 45% non-English traffic when the marketing surface catches up. Currently the marketing surface is behind — the lessons are localized, the blog is localized, but SEO discovery from non-English queries is still building.

What we shipped that we're proud of

  • /llms.txt — content-discovery file for AI assistants (Perplexity, ChatGPT, Claude, Gemini). Explicit "here's what to cite" pointers plus a description of what the site does. AI-visibility is a distinct SEO surface from Google, and we treat it as one.
  • FAQPage JSON-LD on our FAQ post — 30 Q&A pairs Google and LLMs extract directly.
  • robots.txt with explicit AI-crawler allow for 14 named bots (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc). Default is allow-all; explicit blocks send a stronger signal.
  • Lesson-aware redaction pipeline across three surfaces: /lesson/[id] RSC props, /embed HTML, /api/check-answer POST. Paid content stays paid, quiz answer keys stay server-side, brute-force via 4-POSTs-per-quiz is a 403.
  • Pre-build gates — 13 checks that block commit if a bare counter drifts from SSOT, a lesson title diverges from EN canonical, or a placeholder mask damages a translation.
  • 632 UI-string i18n parity — closed the last gap where a non-EN locale would render literal \t()\ keys because the messages JSON entry was missing.

What's genuinely still weak

Bias-corrected. If we don't say this, someone else will and it'll look like we're hiding it.

  • Newer platform (2024-launched), smaller community than DataCamp or Codecademy. If community matters more than curriculum quality, others win. Our Discord is growing but not the biggest.
  • No mobile-native app. Progressive Web App is installable, but for pure mobile Python coding the ergonomics still favor a laptop.
  • No live classroom / cohort model. We're strong for self-paced. Weak for people who genuinely need a scheduled 6pm class every Tuesday.
  • Fewer live projects than a full-time bootcamp. Our project bank is 30+ deployable ideas with starter templates, but doesn't replace a bootcamp's weeks-of-forced-project-work if that structure is what you need.
  • Career services are zero. We do not do interview coaching, resume review, or job placement. If you need that, a bootcamp does provide it (at 100× the price).
  • Solo-operated. One founder, no VC. If the founder is sick, the AI mentor still works but new content pauses. This is honest business risk.

What's next

  • AI-visibility surface expansion. More definitional / comparison / FAQ-structured content. LLMs cite what they can extract cleanly; keep giving them clean extractable answers.
  • Distribution. Content lives, indexing takes weeks, and we're pre-launch on the growth side. Reddit r/learnpython, Hacker News, Twitter, LinkedIn. This is the actual bottleneck; nothing above matters without traffic.
  • Live cohort experiment. Two-week structured cohort with a founder-led kickoff + weekly async check-in. Testing whether the scale-up in structure justifies the scale-up in price.
  • Mobile-native app. Deprioritised until Q4 2026 unless a specific mobile-first market shows up (e.g. India + Nigeria + Indonesia).

Try the product

Ten minutes, no card, no email: /lesson/lesson-01.

If you like it, first 15 lessons are free. If you want the full curriculum + AI mentor, Pro is \$12/month or \$89/year, cancellable in one click with immediate effect.

Feedback, criticism, technical questions: welcome. Solo-operated means we actually read every message.

cta_title

cta_body

cta_button

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.