Web layer
Auth, billing, dashboard states, provisioning checks, and Telegram bot connection UI inside a Next.js app.
case_study://careerwise-io
Careerwise is an AI career coach SaaS I built as a solo founder. The web app handles auth, billing, provisioning, and bot setup. The actual coaching product lives in Telegram, where each paid user gets their own Cloud Run runtime, private workspace, persistent memory, job-search flow, and PDF CV export pipeline.
Problem
Job seekers were juggling search, tailoring, tracking, and interview prep across too many disconnected tools.
Product move
Put the agent inside Telegram so the experience lived where users could message it every day without learning a new product.
Core system
Dedicated runtime + private workspace per user, instead of a shared assistant with shallow state.
Outcome
A career coach that can search, tailor, export, and coach from persistent user context rather than one-off prompts.
why_this_product
The real pain in job search is not just finding one role. It is keeping context across many roles, rewriting documents quickly, remembering constraints, following up consistently, and staying coached while motivation drops.
Careerwise was designed around that operational mess. The system collects profile context into structured files, saves role-specific job folders, tracks applications, and keeps the conversation alive inside Telegram so the assistant can behave more like an always-on operator than a one-off chatbot.
what_i_built
Web layer
Auth, billing, dashboard states, provisioning checks, and Telegram bot connection UI inside a Next.js app.
Runtime model
One dedicated Cloud Run service per paid user, instead of one shared agent backend for everyone.
Memory model
A two-layer system: markdown workspace files for durable context plus SQLite brain.db for programmatic recall.
Document pipeline
CV and cover-letter markdown exported to PDF through a separate Cloud Run worker and sent back in Telegram.
runtime_topology
[ web app ]
auth -> billing -> dashboard -> telegram connect
|
v
[ firestore ] ---- billing state / user metadata
|
v
[ cloud run ]
careerwise-{uid}
|
+-> sync workspace from GCS
+-> inject telegram config
+-> run agent with bounded context
|
v
[ /workspace ]
USER.md
CV.md
MEMORY.md
APPLICATIONS.md
jobs/{slug}/
memory/brain.db
|
+-> job search + scoring
+-> tailored docs
+-> pdf export worker
|
v
[ telegram ]memory_and_workspace
One of the strongest parts of Careerwise is that the agent state is inspectable. The workspace is not a black box. It is a set of explicit files with clear jobs, plus a lightweight SQLite memory layer for recall.
USER.md
Identity, role targets, salary floor, location, and hard constraints.
CV.md
Master source of truth for experience, skills, and all later CV tailoring.
MEMORY.md
Coaching strategy, job-search plan, and recurring behavioral notes.
APPLICATIONS.md
Pipeline tracker for saved jobs, statuses, and follow-up work.
jobs/{slug}/
Per-role folder for JD, tailored CV, cover letter, notes, and PDFs.
memory/brain.db
SQLite memory store used for bounded programmatic recall.
key_decisions
The product deliberately avoided building a chat UI in the web app. The web layer handled signup, payment, provisioning, and bot connection, while the actual coaching experience lived in Telegram where users already spend time.
Each user got their own Cloud Run service and workspace. That kept bot tokens isolated, avoided shared-session confusion, and made the product feel like a personal agent rather than a shared SaaS inbox.
Instead of reaching for a vector database early, the system used markdown files like USER.md, CV.md, MEMORY.md, and APPLICATIONS.md, plus SQLite memory recall. That kept the product inspectable and cheap while still supporting persistent coaching.
PDF export was split into its own worker so the agent runtime stayed focused on conversation and orchestration. The export path converted markdown directly to PDF through WeasyPrint rather than sending formatting back through an LLM loop.
truth_points
Active channel
Telegram is the only active user-facing messaging channel.
Provisioning
Stripe payment unlocks workspace initialization and Cloud Run provisioning.
Workspace
User data lives in a per-user GCS workspace synced into /workspace on container boot.
Search flow
Agent reads USER.md, runs job search, saves job folders, scores fit, and returns the best roles.
Export flow
Markdown CVs and cover letters become PDFs through POST /render-cv on a separate worker.
solo_founder_scope
This was not just an LLM wrapper or a landing page. I owned the user journey from signup to payment to provisioning to messaging. That included product definition, UX, dashboard states, runtime provisioning, workspace architecture, job-search flow, PDF export, and the operational constraints around deployment and sync.
current tradeoffs
why_it_belongs_here
If you are hiring for product-minded AI builders, this project shows the parts I care about most: choosing the right interface, keeping state inspectable, making infra decisions that support real users, and turning a fuzzy workflow into a product with billing, runtime isolation, and operational discipline.