Real Python, not a simulation
CPython compiled to WebAssembly. Import collections,
itertools, dataclasses — they all work, including the
tracebacks when you get it wrong.
HTML · CSS · JavaScript · Python
No account. No install. Your progress stays in this browser.
Try it now · no sign-in
Pick a goal and your experience. Fluentbyte will choose where to begin and remember it when you open the course.
Your path will appear here
Two clicks. Then the course has a useful starting point.
One page, three languages
The browser downloads a plain file and turns it into a tree of elements. That tree is the foundation — everything else decorates it.
<article class="card"> <h2>Aurora</h2> <p>Northern lights, explained.</p> <button type="button">Read more</button> </article>
Step two
Not decoration bolted on afterwards — a full declarative layout engine. Grid, container queries and scroll-linked animation all live here.
.card {
display: grid;
gap: 0.5rem;
padding: 1.5rem;
border-radius: 18px;
background: color-mix(in oklab, var(--brand) 12%, transparent);
transition: transform 250ms cubic-bezier(0.16, 1, 0.3, 1);
}
.card:hover { transform: translateY(-4px); }
Step three
One listener on the container handles every row — including rows that do not exist yet. That is the whole idea behind event delegation.
list.addEventListener("click", (e) => {
const btn = e.target.closest("[data-action]");
if (!btn) return;
if (btn.dataset.action === "delete") {
btn.closest("li").remove();
}
});
And beyond the browser
Scripts, data, automation, backends. Every Python example here runs real CPython, compiled to WebAssembly, right in your tab.
from collections import Counter
def summarise(rows: list[dict]) -> dict:
by_region = Counter()
for row in rows:
by_region[row["region"]] += float(row["amount"])
return dict(by_region.most_common())
Nothing here is a screenshot
Change a value, press Run, watch the preview update. Break it on purpose — that is usually when it sticks.
.hero-inner {
transform: translateY(calc(var(--p) * -14vh))
scale(calc(1 - var(--p) * 0.14));
opacity: calc(1 - var(--p) * 1.25);
filter: blur(calc(var(--p) * 14px));
}
That is the actual rule animating the headline you scrolled past. CSS 11 · Scroll-driven effects
The curriculum
Each starts from first principles and ends somewhere genuinely useful. Take them in order, or jump straight to what you came here for.
Adaptive · one
One question, three answers. That sets the baseline depth of every lesson — and it is the last piece of admin you will ever do here.
Where are you starting from?
Adaptive · two
Every quiz answer feeds a score kept per track. Do well on CSS and the CSS lessons deepen — the notes on stacking contexts, subgrid and cascade layers appear. Struggle, and it steps back to fundamentals without ever making a point of it.
Adaptive · three
Including the half-finished code sitting in the editor. Close the tab mid-lesson, come back next week, and your draft is still there.
Continue
Async: promises and await
The event loop, why callbacks nested, and how await untangled it.
0
lessons
0
live exercises
0
quiz questions
0
accounts required
Built the way it teaches
CPython compiled to WebAssembly. Import collections,
itertools, dataclasses — they all work, including the
tracebacks when you get it wrong.
Your code runs in an iframe with allow-scripts and nothing else — no
reach into this page, its storage, or its cookies.
Every scroll effect collapses to a plain stacked layout under
prefers-reduced-motion. None of the animation is load-bearing.
/ to search, ← → to change lesson, ⌘↵ to run code. Visible focus everywhere.
No build step and no server. Open the file and it runs. Only the Python runtime needs a connection, and only the first time.
Progress lives in this browser's localStorage. Export it as JSON or wipe
it in one click. Nothing is sent anywhere.
Start at the beginning, or skip to the thing you actually came here for.