Table of Contents

Cognate.dev, and why experienced developers deserve a better starting point

Here is a frustration every experienced developer eventually hits: you already know how to program. You have built real things. You understand what a class is, what a promise is, why you would reach for a hash map instead of an array. And yet every time you try to pick up a new language, the tutorial in front of you opens with “a variable is a container that stores a value.”

There is a better way to do this. Instead of re-learning programming dressed in new syntax, you need a translation layer — here is the concept you already know, here is how it is expressed in this language, and here is the handful of ideas that are genuinely new. That is the entire gap. Most tutorials don’t close it because they are not built for people who already know how to code.

Cognate.dev is built for exactly that.


The idea in one line

A cognate, linguistically, is a word that shares a root across two languages but shows up in a slightly different form — “actual” in English and “actual” in Spanish look almost the same and mean something subtly different. Language learners use cognates as shortcuts: recognize the pattern once, and a huge chunk of new vocabulary stops being new.

Programming languages are full of the exact same thing. A for loop is a cognate. A class constructor is a cognate. async/await is a cognate — even in cases (we’ll get to this) where what’s happening underneath is completely different. Cognate.dev exists to teach those pairs explicitly, instead of pretending you’re starting from zero.


What you actually land on

Open the site and the landing page says exactly what it’s for, right in the first line:

Same brain, new syntax.

That’s not just a tagline, it’s the entire design constraint. Below it, four short promises, and I want to be honest about each one because they’re not just marketing copy — they’re commitments I had to actually build against:

  • Compare, don’t re-learn — every concept sits next to its JS counterpart. Not “here’s a new concept,” but “here’s the JS thing you already know, here’s its shape over here.”
  • Run it, don’t just read it — if there’s a way to actually execute code in the browser for a given language, we use it. No “trust me, this works.”
  • The gaps get flagged — and this one matters more than people expect.
  • Nothing to install — every tutorial is a static page. Open it, start.

Scroll past that and you hit the actual point of the homepage: a grid of language tracks. Right now it’s honest about where things stand — Python is marked Live, Rust and Go are Planned, Java is just an Idea sitting there as a placeholder. I didn’t want a landing page that pretends to be more finished than it is. Each card even carries its own accent color, so as more tracks ship, the page will visually feel less like one language and more like a shelf of them.


Why “the gaps get flagged” is the part I care about most

Most comparison-based teaching material has a quiet flaw: it tries to force an analogy onto everything, and the moment the analogy breaks, the learner is quietly misled instead of helped.

The Python tutorial — the first track live on the site — is built to resist that. It’s honest, repeatedly, about where the comparison stops working:

  • Python’s async/await looks like JS’s. Same keywords, similar shape. But JS has exactly one concurrency model, always running. Python has three — asyncio for I/O, threading, multiprocessing — because of the Global Interpreter Lock, a thing with no JS analog at all. The tutorial says this outright instead of hand-waving past it.
  • Decorators and context managers get their own dedicated sections, not because they’re hard, but because there’s genuinely no native JS syntax for either — the closest you can do in JS is a higher-order function, which isn’t quite the same shape.
  • Even something as small as Python’s try/except/else/finally gets called out for its else clause, which has no slot in JS’s try/catch/finally at all.

I’d rather a learner walk away knowing “this one’s genuinely new, pay attention” than have them assume every new language concept has a tidy JS box to fit into.


It’s not just reading — it runs

The thing I was most stubborn about while building this: static code samples aren’t enough. If I’m telling you “here’s how Python’s list comprehension replaces .filter().map(),” you should be able to change the numbers and run it, right there, without opening a terminal.

So the Python track runs on Pyodide — a real CPython interpreter compiled to WebAssembly — loaded straight from a CDN. There’s no backend anywhere in this project. Every “Try it” box you see across the syntax, data structures, functions, classes, and standard-library sections is executing actual Python in your actual browser tab. The two sections that stay comparison-only (async and data validation with Pydantic) are honest about why: those specific runtimes aren’t something Pyodide is set up to run cleanly in-browser today, so rather than fake it, those sections just don’t pretend to be interactive.

There’s also a lightweight quiz after most sections and a sidebar checklist you can tick off as you go. Neither persists anywhere — no accounts, no backend, no localStorage tracking you across visits. Close the tab and it resets. That was a deliberate trade: I’d rather the whole thing stay a static file you can fork and deploy in five minutes than bolt on infrastructure just to remember your quiz score.


What Python-from-JS actually covers

If you’re a JS developer and this is your first stop, here’s the shape of it, section by section:

  1. Syntax speed-run — indentation instead of braces, f-strings instead of template literals, None instead of null/undefined, and the truthiness trap ([] is falsy in Python, not in JS — this one gets people every time).
  2. Data structures & comprehensions — why idiomatic Python reaches for [x for x in y] before it reaches for .map(), plus generators and lazy iteration.
  3. Functions — defaults, *args/**kwargs, and then the two genuinely new ideas: decorators and context managers, both with a live playground to actually try.
  4. Classes & typing — explicit self instead of implicit this, multiple inheritance, and Protocol for structural typing — the closest thing Python has to a TypeScript interface used for duck-typed arguments.
  5. The async model — where it rhymes with JS and where it very much doesn’t.
  6. Errors, strings & files — exception handling idioms, pathlib, and a tour of a standard library that’s noticeably richer than what you’re used to reaching for in Node.
  7. Data validation — Pydantic, framed directly against zod, since that’s the fastest way for a TS developer to understand what it’s for.

What’s next

Python was first because it’s the most common “what’s next” for a JS developer — scripting, data work, and increasingly, the layer people build AI tooling on top of. Rust and Go are next, and I think they’ll actually be more interesting to write, not less — both diverge from JS’s execution model in ways worth teaching head-on: ownership and borrowing for Rust, goroutines and channels for Go. Java’s after that.

If the whole premise is right, each new track should get easier to build, not harder. The shape stays the same — syntax, data structures, functions, typing, concurrency, and an honest accounting of what’s actually new. Only the words change.

Start here: https://cognatedev.subashselvaraj.com/