How I Turned a Static Site into an Agentic AI Learning Platform

When we started building First Break AI, we had a constraint that turned out to be an advantage.
We wanted a real course site — lessons, blogs, office hours, a roadmap, docs — but we did not want to run a full web application just to serve content.
No LMS.
No Next.js rewrite of a curriculum.
No server rendering pages on every request.
Static sites are fast, cheap, and easy to maintain. But they usually have one big limitation: they cannot interact with learners. They cannot remember who you are. They cannot validate your work. They cannot tell you what to do next.
So we started with a simple question:
What if the site stayed static, but AI agents became the dynamic layer on top?
That idea became the foundation of First Break AI.
The HTML is still plain static output. The learning experience is not.
Why we chose Quarto
We chose Quarto because it gave us exactly what we needed for the content layer.
You write .qmd files, run:
quarto render
and get static HTML.
We deploy that output to Cloudflare Pages. Pages load fast. URLs stay clean. Everything lives in Git. Learners can fork the repo and follow along.
For a free, open cohort, that foundation was exactly right.
The content layer needed to be boring in the best way:
easy to write
easy to review
easy to deploy
easy to fork
fast for learners
visible to search engines
not locked inside a SaaS LMS
Quarto gave us that.
But static sites have a problem.
They do not remember who you are. They cannot check your homework. They cannot tell you what lesson should come next. They cannot connect your browser, terminal, and IDE into one learning journey.
A generic chatbot widget does not solve that either.
It may answer questions, but it does not know your roadmap. It does not validate your repo. It does not sync progress. It does not become part of your development workflow.
So we decided not to make the static site “smart.”
We made the agents smart — and pointed them at the static content.
The problem with most “AI-powered” courses
Most “AI-powered” courses today fall into one of two buckets.
Either they add a chatbot that knows nothing meaningful about the course, or they lock the entire learning experience inside a platform from day one.
We wanted neither.
We wanted learners to:
read lessons as fast static pages
ask questions grounded in our actual content
run local validation from the terminal
use the same tools inside Cursor or Claude
track progress without turning the whole site into an app
keep the curriculum open and forkable
A learner should be able to read a lesson about GGUF, ask a course-aware question, validate an exercise locally, and then ask their IDE agent what to do next — all using the same underlying learning system.
That required a clean separation:
Content is static. Agency is dynamic.
The magic is in deliberately connecting the two.
The architecture: two layers
Think of the system in two layers.
1. The content layer
The content layer is simple.
Quarto builds the site. Cloudflare Pages serves the static HTML.
When a learner opens the roadmap, a lesson, or a blog post, they are reading pre-rendered HTML. There is no app server involved in delivering that page.
That matters.
It keeps the site fast. It keeps the cost low. It keeps the curriculum open. It also means search engines and learners both get real content immediately, not an empty JavaScript shell.
2. The agentic layer
The agentic layer sits beside the static content.
It does not replace Quarto. It does not convert .qmd files into React components. It does not move the curriculum into a database.
Instead, it adds connective tissue:
an on-site Ask Anything widget
a Cloudflare Worker
an MCP server
CLI validation tools
local and remote agent tools
Discord OAuth for identity
D1 for learner progress
FetchLens.ai for observability into agent traffic
This second layer gives agents the ability to act.
They can answer from cohort knowledge. They can find lessons. They can validate exercises. They can suggest next steps. They can show up inside the browser, terminal, and IDE.
The result is not just a website with a chatbot.
It is a static course site with an agentic learning layer.
The flow in plain language
Here is how it works from a learner’s point of view.
A learner reads a lesson on the site. That lesson is just static HTML generated by Quarto.
They have a question. The FetchLens-powered widget calls the Worker. The agent answers using cohort knowledge, not a generic open-web answer.
They finish an exercise. The learner runs:
firstbreakai validate 1
The CLI checks the local repo against a rubric. It can confirm real file-system facts like whether _quarto.yml exists, whether a .qmd file is present, and whether the Git remote points to GitHub.
Then the learner opens Cursor or Claude Code. The same MCP server gives their IDE agent access to cohort tools like:
ask
find
validate
next
Same brain, many surfaces.
The site stays static. The agents become shared infrastructure.
Ask Anything on every page
The lightest entry point is the website widget.
After Quarto renders the site, we include a small deferred script that mounts an “Ask Anything” button on the page.
<script src="/public/scripts/fba-lens-widget.js" defer
data-endpoint="https://fba-mcp.throbbing-thunder-4d33.workers.dev/widget/mcp"
data-button-label="Ask Anything"></script>
This does not change how Quarto works.
The static page still loads normally. The content still exists without JavaScript. If the widget fails, the lesson still works.
The agentic layer loads after the content.
From the learner’s point of view, it feels like a tutor that has read the whole course. But from the site architecture point of view, it is just an async layer on top of static HTML.
That separation is important.
It means the course remains fast and durable, while the agentic layer can evolve independently.
MCP inside the IDE
The next step was making the course available inside the learner’s actual development workflow.
The same Cloudflare Worker exposes a public MCP server over HTTP.
If a learner uses Cursor, Claude Desktop, Claude Code, or another MCP-compatible tool, they can add the cohort server and give their AI assistant access to course tools.
For Cursor, the config looks like this:
{
"mcpServers": {
"fba-cohort": {
"url": "https://fba-mcp.throbbing-thunder-4d33.workers.dev/mcp"
}
}
}
This was the moment the cohort stopped being only “a website you visit.”
It became infrastructure your agent can call.
A learner debugging their Quarto blog in Cursor can ask the IDE agent to check the cohort requirements without switching tabs. The agent can find the relevant lesson, explain the rubric, and guide the learner toward the next step.
That is what I mean by agentic learning.
Not a chatbot on a sidebar.
Tools wired into where people already work.
A CLI that validates for real
Some checks should not be left to an LLM.
If the assignment says “ship a Quarto blog on GitHub,” we should not ask an AI model to guess whether it looks good.
We should check the actual repo.
So we built a CLI package:
npm install -g @aiedx/firstbreakai
The CLI gives learners commands like:
firstbreakai doctor
firstbreakai validate 1
firstbreakai status
firstbreakai mcp
doctor checks the development environment.
validate 1 runs rubric checks for Step 1.
status shows where the learner is on the roadmap.
mcp starts a local MCP server for IDE workflows.
For example, a rubric can check whether:
Quarto is installed
Git is configured
_quarto.ymlexistsat least one
.qmdfile existsthe repo has a GitHub remote
required lesson files are present
This is the split I like:
AI agents handle ambiguity. Rubrics handle facts.
Agents are useful when a learner is confused, stuck, or exploring. Rubrics are useful when the system needs to say whether a concrete requirement passed or failed.
That keeps validation honest.
No hallucinated “looks good to me.”
Identity without turning the site into an app
Static sites do not have sessions.
We did not want to add a Node backend just for login.
So Discord OAuth runs on the Worker. A learner can log in from the navbar. The token is stored client-side, and the widget or CLI can use that identity when needed.
Progress lives in D1 behind the Worker.
That allows us to track things like:
completed lessons
validated steps
roadmap progress
learner state across the site, CLI, and widget
But the curriculum itself remains open.
This was a deliberate design choice.
Login should improve the experience, not gate the material.
Anyone can read the lessons. Anyone can fork the repo. Personalization is an overlay, not the foundation.
What FetchLens adds
FetchLens.ai powers the on-site agent experience and gives us observability into how agents interact with the site.
That matters because once agents become users of your content, normal analytics are not enough.
Traditional analytics tell you what humans clicked.
Agentic analytics should help answer different questions:
What are learners asking agents?
Which lessons are confusing?
Which tools are being called?
Where do agents fail?
Which pages trigger the most help requests?
Are agents finding the right content?
Which workflows need better rubrics?
For a learning site, this is extremely useful.
If ten learners ask the same question on a lesson, maybe the lesson needs improvement. If many validation attempts fail at the same step, maybe the rubric or instructions need to be clearer.
The agentic layer is not only for learners.
It also gives the course builder feedback.
What we deliberately did not do
We did not rebuild the cohort in React or Next.js.
Quarto was already the right tool for long-form technical lessons, blogs, and docs.
We did not embed a generic ChatGPT iframe and call it “AI-powered.”
A generic chatbot is not enough. The agent needs course context, tools, rubrics, identity, and surfaces across browser, CLI, and IDE.
We did not hide the course behind login.
The material is public. Discord and auth exist for community and progress, not for gating content.
We did not try to make the static site itself smart.
We kept the static site simple and made the agentic layer capable.
That distinction is the whole architecture.
Why this stack works
This stack works because each part has a clear job.
Quarto handles content.
Cloudflare Pages handles static delivery.
The Worker handles agent endpoints.
MCP exposes tools to AI assistants.
The CLI handles local validation.
D1 stores progress.
FetchLens gives observability into agent usage.
No single piece is trying to do everything.
That matters when you are a small team.
Adding a lesson is still simple:
write a .qmd file
quarto render
deploy
Adding a new agent capability is also separate:
add a tool to the MCP server
extend a rubric
update the CLI
Content and agency evolve on separate tracks.
That is what makes the system maintainable.
Static content, dynamic learning
The important lesson from this build is simple:
A static site does not have to mean a static learning experience.
You can keep the content layer simple, fast, and open.
Then you can add agents as the dynamic layer that answers, validates, tracks, and guides.
For First Break AI, that gave us the best of both worlds.
Quarto gives us the content machine.
AI agents give us the learning machine.
Together, they feel much closer to a teaching assistant that scales than a video platform with a comment section.
If you want to try it
First Break AI is free and open.
Start with the roadmap or Lesson 0.
Install the CLI:
npm install -g @aiedx/firstbreakai
Or run it directly with:
npx @aiedx/firstbreakai doctor
Add the MCP server to your IDE. Join the Discord if you want humans in the loop too.
We are still iterating — roadmap checkmarks when logged in, more validation rubrics, deeper FetchLens observability on agent traffic — but the core idea is stable:
Static site for content. Agents for everything that needs to act.
If you are building something similar with MCP, agentic tooling, static sites, or AI learning workflows, I would genuinely like to hear how you are approaching it.
And if you are looking for your first break in AI, the cohort is open.
First Break AI is built by AIEdx. Agentic infrastructure is powered by FetchLens.ai.
