You have written the same Nómada Tasks screen four times: in plain JavaScript, in React, in Vue and in Angular. Every version does exactly the same thing —the task list, the assignee filter and the mark-as-done button, with the canonical numbers intact— and each one does it in a different way, with different costs. Now comes the question that gives the whole module its point and that no tutorial answers well: how you choose. Not with a table of stars or the opinion from a conference talk, but with a method you can defend to your team and to yourself three years from now. In this lesson you will see the criteria that really matter —product, team, job market, longevity, performance, SEO, accessibility, ecosystem and the cost of hiring and training— with a weighting table you can fill in; the honest technical comparison of the four approaches in a two-way table; the four versions of the same screen side by side with their metrics and a nuanced conclusion; the decision that usually matters more than the framework one —where the rendering happens: client, server, static or hybrid, with SPA, SSR, SSG and islands and their meta-frameworks—; the criteria for SEO and accessibility, and why none of the four saves you from getting them wrong; how to evaluate a new technology without falling for fashions, with the one-day prototype of your hardest case; and migration strategies with no total rewrites. It is the module's last lesson, and it closes with what does not expire —the language, the DOM, HTTP, testing, performance: exactly what you have learned— versus what does.
Contents
- Why this lesson exists
- The criteria that matter
- The weighting table you can fill in
- How it is used: Taller Nómada's decision, step by step
- The honest technical comparison
- The four versions of the same screen, with metrics
- What pays off according to the context
- The decision that usually matters more: where the rendering happens
- SPA: rendering on the client
- SSR: rendering on the server
- SSG: static generation
- Islands and hybrid rendering
- The meta-frameworks in one table
- SEO: what a framework saves you from and what it does not
- Accessibility: none of them saves you from getting it wrong
- How to evaluate a new technology without falling for fashions
- The one-day prototype with the hardest case
- Migration strategies with no total rewrites
- Web components as a boundary
- What does not expire versus what does
- Module 11: plain JavaScript, now by decision
- Common Mistakes and Tips
- Exercises
- Conclusion
- Why this lesson exists
There are two ways of choosing technology, and both are seen every day.
The first is the dominant one: you choose what you know, what you saw in a talk, what the company next door uses, or what appears most often in job ads. It is not irrational —the job market is a legitimate criterion, and we will look at it— but it is applied without being stated, and therefore without being open to discussion.
The second is the one you are going to learn here: list the criteria, weight them according to the context, measure your own case and decide with the data in front of you. It does not guarantee being right; it guarantees that the decision can be explained, reviewed and corrected. And above all it guarantees that it is yours.
A word of honesty before starting, because this lesson is not going to give you a winner. The four approaches you have seen are good, and there are excellent applications built with each one. Any text telling you that one is objectively superior is ignoring the context, which is exactly what determines the answer. What I can give you is the method, the tables for applying it and the data from your own project measured four times.
- The criteria that matter
Eight criteria, and not one of them is "which has the best benchmark performance".
1 · The product's needs. How much interactivity does it have? How many screens? Are there complex forms, real time, charts, collaborative editing? A website with a dropdown menu and a management application with role-based permissions are not the same problem, even though both "are web".
2 · The team's size and experience. One person alone optimizes for writing speed and low ceremony. Six people optimize for shared conventions, explicit contracts and the ability to review each other's code. And what the team already knows is worth more than any marginal technical advantage: the productivity of a team expert in one tool almost always beats that of a team new to a better one.
3 · The local job market. It is an uncomfortable criterion but a real one, and it works in both directions: if you are hiring, you need to find people; if you are looking for work, you need your experience to be in demand where you live. And it is local: the proportions between React, Vue and Angular vary a great deal between countries and between sectors. Look at real ads in your city, not global surveys.
4 · The project's longevity and stability. How long does this have to last? A three-month project can afford a new technology. One that has to keep working for ten years with nobody touching it has to bet on stability, a clear versioning policy and automatic migrations — or on depending on nothing.
5 · Performance and SEO requirements. What is your byte budget? Are your users on fiber or on 3G? Does the content need indexing? These questions usually decide where the rendering happens (section 8) before deciding which framework is used.
6 · Accessibility. Is there a legal obligation? A diverse audience? Heavy keyboard use? No framework gives it to you ready-made, but some make doing it well easier than others.
7 · Ecosystem. Do you need an advanced data grid, a rich text editor, complex charts, a calendar? The more specific the need, the more the ecosystem's size weighs.
8 · The cost of hiring and training. How much it costs to bring somebody in productive and how long it takes until they are. It is measured in weeks, and it is paid every time somebody new joins.
Notice something: five of the eight are not technical. That proportion is representative of how the decisions that work out are made.
- The weighting table you can fill in
The method is simple. For each criterion, assign a weight from 1 to 5 according to what matters in your context —not in the abstract—, score each option from 1 to 5, multiply and add.
| Criterion | Weight (1-5) | Plain JS | React | Vue | Angular |
|---|---|---|---|---|---|
| The product's needs | |||||
| The team's size and experience | |||||
| Local job market | |||||
| The project's longevity | |||||
| Performance and weight | |||||
| SEO | |||||
| Accessibility | |||||
| Available ecosystem | |||||
| Cost of hiring and training | |||||
| Weighted total |
Three rules for using it, without which the table is decoration:
Rule 1 · The weights are set before scoring. If you decide the weights after seeing the scores, you are justifying a decision already made. It is the most common bias and the easiest to avoid.
Rule 2 · A weight of 5 means it can veto. If the local job market weighs 5 and an option scores 1, that option is out even if it wins overall. Knockout criteria are not averaged.
Rule 3 · Scores are justified with one sentence. "React scores 4 on ecosystem because the data grid we need exists and is maintained." Without the sentence, the number is an opinion dressed up as data.
And a warning about the instrument: the table does not decide, it organizes the thinking. If the result makes you uncomfortable, it almost always means there is a criterion you have not written down or a weight set wrongly. That is valuable information too.
- How it is used: Taller Nómada's decision, step by step
Let us do it with a concrete case. Marta wants to turn Nómada Tasks into a product for twenty coworking workshops: five screens, role-based permissions, reports, real-time collaborative editing, a team of four people and a five-year horizon.
Step 1 · The weights, with their justification:
| Criterion | Weight | Why |
|---|---|---|
| The product's needs | 5 | Five screens, permissions, real time: it is a genuine application |
| The team's size and experience | 5 | Four people need shared conventions |
| Local job market | 4 | There will be hiring over five years |
| Longevity | 4 | Five years is a long time: the versioning policy matters |
| Performance and weight | 2 | It is an internal tool, with users in an office and long sessions |
| SEO | 1 | It is behind a sign-in: nothing gets indexed |
| Accessibility | 3 | Daily, intensive use, with the keyboard: it genuinely matters |
| Ecosystem | 3 | A data grid, charts and a text editor will be needed |
| Cost of training | 3 | Two of the four people come from plain JavaScript |
Step 2 · The scores, each with its sentence:
| Criterion | Weight | Plain JS | React | Vue | Angular |
|---|---|---|---|---|---|
| The product's needs | 5 | 2 | 5 | 5 | 5 |
| A team of four | 5 | 1 | 3 | 4 | 5 |
| Local job market | 4 | 2 | 5 | 3 | 4 |
| Longevity | 4 | 5 | 3 | 4 | 5 |
| Performance and weight | 2 | 5 | 3 | 4 | 3 |
| SEO | 1 | 3 | 3 | 3 | 3 |
| Accessibility | 3 | 4 | 3 | 3 | 3 |
| Ecosystem | 3 | 1 | 5 | 4 | 4 |
| Cost of training | 3 | 4 | 3 | 4 | 2 |
| Total | 83 | 125 | 131 | 136 |
Some justifications, so that the reasoning is visible:
- Plain JS scores 1 on "a team of four": every convention would have to be invented, written down and enforced with no help from tooling. It is 10-01's problem 8, and with four people it is expensive.
- Plain JS scores 5 on longevity: it is the only one that will still work in ten years with nothing updated.
- Angular scores 5 on "a team of four": imposed conventions, mandatory typing and explicit contracts are exactly what a team reviewing each other's code needs.
- Angular scores 2 on training: two people would have to learn TypeScript, decorators, dependency injection, signals and RxJS.
- Plain JS scores 4 on accessibility: not because the framework prevents it, but because writing the HTML by hand makes it more visible which elements are being used; with a framework it is easier to end up with a
<div>with anonClick.
Step 3 · Read the result with judgment. The three frameworks are very close (125, 131, 136) and plain JavaScript is clearly ruled out for this case. A difference of eleven points out of 130 is not a difference: it is within the noise of the scores. The correct reading is not "Angular wins", but:
For this context, any of the three frameworks is a defensible decision and plain JavaScript is not. The final choice has to be made with the tie-breaking criterion the table does not capture: what the team already knows, and what can be prototyped in a day (section 17).
That is the honest use of a weighting table: to rule out what does not fit and to recognize when there is a tie, not to manufacture a precision that does not exist.
- The honest technical comparison
Now the two-way table of the four approaches, with what you have seen in the five previous lessons.
| Dimension | Plain JavaScript | React | Vue | Angular |
|---|---|---|---|---|
| Reactivity model | Manual: render() by hand |
Virtual DOM + reconciliation | Signals with proxies + compilation | Signals + (Zone.js in older code) |
| Update granularity | Whatever you program | The whole component | The specific expression | The specific expression |
| Immutability | Recommended | Mandatory | Not needed | Mandatory |
| Learning curve | You have already done it | Medium (hooks, reconciliation) | Low to medium | Steep (TS, DI, RxJS) |
| Baseline size (compressed, approx.) | 0 | ~45 kB | ~35 kB | ~60–90 kB |
| Opinions included | None | Very few | Some | Many |
| Tooling | Whatever you assemble (Vite, ESLint, Jest) | Excellent, third-party | Excellent, official | Excellent, official, with ng update |
| Typing | JSDoc or nothing | TS optional, widely used | TS optional, good support | TS mandatory in practice |
| Testing | Jest + Testing Library | Testing Library | Vue Test Utils / Testing Library | TestBed + whatever you like |
| SSR | By hand | Next.js, Remix | Nuxt | Included |
| Ecosystem | All of JavaScript's | The largest | Broad and coherent | Complete and official |
| Fragmentation | Total (yours) | High | Low | Very low |
| Global state | A module object | You choose (10-03) | Pinia | Injected services |
| Shines in | Widgets, simple pages, longevity, total control | Applications of any size with a rich ecosystem and a team with judgment | Progressive adoption, mid-sized teams, partial migrations | Large, long-lived applications, sizable teams, regulated sectors |
| Gets in the way in | Teams, large applications, heavy reuse | Teams with no shared judgment (every project is different) | Very specific needs with no Vue library | Small projects, prototypes, teams in a hurry |
Two rows deserve a comment because they are usually misread.
React's "fragmentation" row is not only a defect. Having four routers is a cost for a small team that has to choose, and an advantage for one that needs something the official solution does not cover. The same characteristic reads the opposite way depending on the context.
The "baseline size" row matters less than it seems. Forty compressed kilobytes are about 200 ms on a bad connection, and they usually get buried by a single unoptimized image or by one slow data request. It is only decisive in two scenarios: widgets embedded in other people's pages, and content sites where most visitors see one page and leave.
- The four versions of the same screen, with metrics
And here is what makes this lesson different from any comparison: you have written all four. These are the figures for the same screen —task list, assignee filter, advance button— with the same canonical backlog of 6 tasks and the same output numbers.
| Metric | Plain JavaScript | React | Vue | Angular |
|---|---|---|---|---|
| Lines of the view | ~210 | ~130 | ~120 | ~180 |
| Lines of your own infrastructure | ~60 | 0 | 0 | 0 |
| Lines of domain (identical in all 4) | ~40 | ~40 | ~40 | ~40 |
| View files | 5 | 6 | 6 | 5 |
| Production dependencies | 0 | 2 | 1 | ~8 |
| JavaScript downloaded (compressed, approx.) | ~18 kB | ~63 kB | ~53 kB | ~85 kB |
| Requests after building | 3 | 3 | 3 | 4 |
| First contentful paint (Slow 4G, approx.) | ~0.9 s | ~1.3 s | ~1.2 s | ~1.6 s |
| Files to touch to add a piece of data to the card | 2 | 1 | 1 | 1 |
| Prior concepts required | DOM, modules | + JSX, hooks | + templates, refs | + TS, DI, signals, RxJS |
| Risk of forgetting the cleanup | High | Low | Low | Low |
| Risk of forgetting the list key | High | Medium (a warning) | Low (ESLint) | None (it does not compile) |
The weight and first-paint figures are orders of magnitude measured under equivalent conditions, not absolute marks: they change with the version, with the build configuration and with how much of each framework you use. What does not change is the relationship between them, which is what matters for deciding.
And now the honest reading, column by column:
Plain JavaScript wins on weight, on requests and on time to first paint. No surprise: there is no engine to download. It also wins on dependencies, which is the longevity criterion. And it loses badly on two rows: the 60 lines of infrastructure you maintain and test —reconcile, buildElement, $, $$, the delegation—, and the risk of forgetting the cleanup and the keys, which are real failures you already suffered in 06-06 and in 09-03.
Vue has the best balance on this particular screen: fewer lines than any of the others, one file per component with isolated styles, one dependency and the lightest engine of the three.
React is very close in lines and buys the largest ecosystem, in exchange for the manual memoization 10-02 forced you to discuss and a somewhat heavier engine.
Angular is the most verbose and the heaviest, and in exchange it is the only one where the key mistake is impossible, typing comes as standard and shared state needs no decision at all.
An important clarification about the 40 lines of domain: they are exactly the same file in all four versions. NEXT, LABEL, WEIGHTS, TODAY, isOverdue, openHours. That row is the empirical proof of the discipline 10-01 recommended: the framework takes the view, not the application.
- What pays off according to the context
With the data above, the nuanced conclusion:
| If your situation is… | It pays off to use | Why |
|---|---|---|
| One screen, one person, little change | Plain JavaScript | The 60 lines of infrastructure are a one-off cost; the engine would be a permanent one |
| A widget embedded in other people's pages | Plain JavaScript or web components | The weight adds to a page you do not control, and isolation is a requirement |
| Content with some interaction and critical SEO | Islands (section 12) | Most of the HTML needs no JavaScript at all |
| An application with several screens and a team | Any of the three | Here your own infrastructure starts to cost more than the engine |
| A mid-sized team coming from HTML and jQuery | Vue | A gentler curve, progressive adoption, a coherent ecosystem |
| A team that needs the broadest ecosystem or React Native | React | It is where almost everything specific lives |
| A sizable team, a project spanning years, a regulated sector | Angular | Conventions, typing, DI and automatic migrations |
| You already know one well | That one | The team's productivity beats almost any marginal advantage |
And the general criterion that sums up every row:
A framework pays off when the cost of maintaining your own infrastructure exceeds the cost of downloading and learning theirs. That point comes sooner than people think with large teams, and much later than people think with one person alone.
- The decision that usually matters more: where the rendering happens
Here is the most useful claim in the whole lesson, and the one most people discover late:
Where your HTML is rendered affects perceived performance, SEO and architecture more than which framework you use.
The reason is arithmetic. Switching from React to Vue saves you about 10 kB and a few milliseconds per update. Switching from client rendering to server or static rendering can take you from 1.9 s of LCP to 0.6 s, and from "Google sees an empty page" to "Google sees the complete content". It is an order of magnitude more impact, and yet it is discussed far less.
The four approaches, with the same diagram so they can be compared:
graph TD
subgraph SPA["SPA · on the client"]
A1["Empty HTML"] --> A2["Download JS"] --> A3["Run it"] --> A4["Request data"] --> A5["Paint"]
end
subgraph SSR["SSR · on the server, per request"]
B1["The server paints HTML"] --> B2["The user sees content"] --> B3["Download JS"] --> B4["Hydrate"]
end
subgraph SSG["SSG · static, at build time"]
C1["HTML generated at build time"] --> C2["A CDN serves it"] --> C3["The user sees content"] --> C4["JS optional"]
end
subgraph ISLANDS["Islands · hybrid"]
D1["Static HTML"] --> D2["Only the interactive pieces<br/>load their JS"]
end
- SPA: rendering on the client
It is what you have done all course and what the four versions of the screen do. The server sends an almost empty HTML document and the JavaScript builds the interface.
In favor: instant navigation between screens once loaded; very rich interactions without going to the server; simple deployment (static files); and a clean separation between front end and API.
Against: the first load is the slowest of the four —you have to download, parse, run, request data and paint, in a chain—; the initial HTML is empty, which hurts SEO and anything that reads the page without running JavaScript; and if the JavaScript fails, there is nothing.
When it is the right choice: applications behind a sign-in, internal tools, data dashboards, editors. Anything where SEO does not matter and where the user opens the application once and uses it for hours — which is exactly Nómada Tasks' case.
- SSR: rendering on the server
The server runs the components and sends already-painted HTML. The browser displays it immediately and then downloads the JavaScript to hydrate the page: attaching the event handlers and restoring the state, turning the static HTML into the interactive application.
In favor: the content is visible much sooner (better LCP and FCP); the HTML is complete from the first byte, so search engines and link previews see it; it works on slow devices, where the cost is in running JavaScript.
Against: you need a server running Node.js, with its cost, its scaling and its maintenance; TTFB gets worse, because the server has to work before responding; hydration has a real cost and produces the awkward effect of a page you can see but that does not respond yet; and the code has to work in both environments, which means watching any use of window or document.
When it is the right choice: e-commerce, media, any product where the content has to be indexed and where the first impression determines whether the user stays.
- SSG: static generation
The HTML is generated at build time, once, and served from a CDN as static files.
In favor: it is the fastest thing there is —the server computes nothing, it just delivers a file from the nearest node—; it is the cheapest to host; it is the most secure (there is no server to attack); and it is the most reliable.
Against: it only works for content that does not change per user or per request; with thousands of pages, the build becomes slow; and publishing a change requires rebuilding, although incremental regeneration mitigates this by rebuilding only what changed.
When it is the right choice: documentation, blogs, product sites, portfolios, catalogs that change a few times a day. And yes: Taller Nómada's public website fits here perfectly.
- Islands and hybrid rendering
The islands architecture starts from an uncomfortable observation: on most pages, almost nothing needs JavaScript. An article, a product page or a pricing page are text and images; only the search box, the cart or the calendar are interactive.
The idea: generate static HTML for the whole page and load JavaScript only for the interactive pieces, each one independent, each one hydrating when it needs to —when it appears on screen, on interaction, or never.
The result is that a page with three widgets downloads the JavaScript of those three widgets, not that of the whole page. And the widgets can be written in different frameworks, because each island is independent.
If this sounds familiar, it is because you have already done it: Angular's @defer (on viewport) in 10-05 and your lazy loading with IntersectionObserver from 09-05 are the same idea applied inside an application. Islands apply it to the whole architecture.
When it is the right choice: content sites with occasional interactivity. It is the sweet spot of the modern public web, and the reason this approach has grown so much.
- The meta-frameworks in one table
A meta-framework is a layer above the component framework that provides file-based routing, server or static rendering, build optimization and deployment.
| Meta-framework | On top of | Modes supported | Distinguishing trait |
|---|---|---|---|
| Next.js | React | SSR, SSG, partial islands, server components | The most used; server components (10-02) |
| Remix / React Router | React | SSR with a focus on web forms and standards | It leans heavily on the platform: forms, HTTP caches |
| Nuxt | Vue | SSR, SSG, hybrid per route | Coherence with Vue's official ecosystem |
| Angular with SSR | Angular | SSR, prerendering, incremental hydration | Included: ng add @angular/ssr |
| Astro | Any | Static with islands; SSR optional | Zero JavaScript by default; islands of React, Vue, Svelte… mixed |
| SvelteKit | Svelte | SSR, SSG, hybrid | Very small bundles |
| htmx (a different approach) | None | HTML from the server | No build step; the server returns HTML fragments |
The last row deserves attention, even if it looks marginal. htmx questions the module's entire premise: instead of building the interface in the browser with local state, the server returns HTML and the client inserts it where it belongs. For form-and-list applications —which there are a great many of— it works surprisingly well and removes at a stroke the state synchronization between client and server, which is 10-01's problem 15. It is not the answer for a collaborative editor, but it is a legitimate answer worth having on the map.
And the practical rule for choosing a rendering mode, which is simpler than it looks:
| Your content… | Render it… |
|---|---|
| Is the same for everyone and rarely changes | Static (SSG) |
| Is the same for everyone but changes often | SSR with caching, or static with incremental regeneration |
| Is different for each user and must be indexed | SSR |
| Is different for each user and is behind a sign-in | SPA |
| Is mostly static with interactive pieces | Islands |
- SEO: what a framework saves you from and what it does not
Modern search engines do run JavaScript, but with caveats that make complacency expensive:
- The indexing of client-rendered content can be delayed by days relative to direct HTML, because it requires a second pass with more resources.
- Other crawlers —social networks for link previews, aggregators, analysis tools, some search engines— do not run JavaScript at all.
- The Core Web Vitals you measured in 09-01 (LCP, INP, CLS) are ranking signals, and an SPA starts at a disadvantage on LCP.
What a framework gives you: nothing by itself. What a meta-framework with SSR or SSG gives you: complete HTML in the first response, which is half the problem.
And what no framework gives you, and remains your responsibility:
| Requirement | What has to be done |
|---|---|
<title> and <meta description> tags per page |
Managing them per route |
| Clean, stable URLs | Route design, redirects when they change |
Real <a href> links |
Not <div onClick={navigate}>: crawlers follow href |
| Semantic HTML | A single <h1>, a correct heading hierarchy |
| Structured data | Schema markup for rich results |
Sitemap and robots.txt |
Generated at build time |
Images with alt, dimensions and a modern format |
09-05, as it is |
| Performance | The whole of module 9 |
Notice that most of that table is HTML and architectural decisions, not framework. It is the same message as section 20.
- Accessibility: none of them saves you from getting it wrong
Here it is worth being blunt, because it is the point where a false sense of security does the most damage.
No framework makes your application accessible. On the contrary: frameworks make it easy to write inaccessible things, because they make it just as easy to write <button> as <div onClick>, and the second one works perfectly well with a mouse.
The four failures that keep coming up in framework-built applications, all of which you already know how to avoid:
1 · Non-semantic elements with handlers. A <div> with an onClick does not receive focus with Tab, does not respond to Enter or Space, and is not announced as a button. The solution is a <button>, always. You worked on this in 06-03 and in 06-07.
2 · Focus lost on update. It is 10-01's problem 2, the one that led you to write reconcile. When the key is wrong or the content is recreated, focus jumps back to the start. Whoever navigates by keyboard or with a screen reader gets lost; whoever uses a mouse never notices. That all three frameworks solve reconciliation by default is, in fact, a real accessibility advantage — provided you use the right key.
3 · Changes that are not announced. When filtering by Lucía, the list goes from 6 items to 1. Visually it is obvious; for a screen reader, nothing has happened. A live region is needed:
<p role="status" aria-live="polite">
{{ visible.length }} of {{ total }} tasks · {{ openHours }} h open
</p>That role="status" works the same in all four versions, because it is HTML, not framework.
4 · SPA navigation with no announcement. In a normal navigation, the browser announces the new page and moves the focus. With a client-side router nothing happens: the URL changes and so does the content, but the screen reader stays where it was. You have to move the focus to the main heading and announce the change by hand.
What frameworks do help with: ready-built accessible components —dialogs, menus, tabs, comboboxes— that implement the ARIA patterns correctly, which is difficult work and easy to get wrong. That is where the ecosystem weighs: there are unstyled, accessible component libraries for all three.
The conclusion: accessibility depends on the HTML you produce and the decisions you make, not on the framework. Exactly like SEO.
- How to evaluate a new technology without falling for fashions
Every year something new appears, with impressive demos and an enthusiastic community. A four-step method for evaluating it without being swept along and without dismissing it by default.
Step 1 · Read the documentation, not the tweets. Specifically, look for three things: the getting started guide (how long does it take you to understand the mental model?), the migration guide from the previous version (how much does updating cost?), and the section on limitations or when not to use it. A project that documents its limitations honestly is a mature project; one that does not mention them has not yet run into them.
Step 2 · Look at the release cadence and the versioning policy. Concrete, checkable questions:
| Question | Good sign | Bad sign |
|---|---|---|
| How often do they release? | Regularly and predictably | Long silences, or constant breaking changes |
| Is there a published versioning policy? | Yes, with support dates | There is no telling how long a version lasts |
| What are the breaking changes like? | Announced, documented, with automatic migration | A surprise in a minor version |
| Who maintains it? | A team or a foundation, several people | One person with no succession plan |
| How are issues answered? | With judgment and within a reasonable time | They pile up unanswered |
| Are there known production use cases? | Yes, and of a size comparable to yours | Only demos |
Step 3 · Measure your own example. Not the front-page example, which is chosen to look good: yours. Take the most representative screen of your application, implement it and measure with 09-01's tools: bytes downloaded, time to first paint, INP on interaction, DOM nodes. It is what you have done four times in this module, and that is why section 6's table is worth more than any comparison written by somebody else.
Step 4 · Do the one-day prototype. The next section.
- The one-day prototype with the hardest case
It is the most profitable advice in this lesson, and the most ignored.
Pick your hardest case, not the most representative one. Nobody has trouble with the tutorial's to-do list. The problems are in the odd stuff: the 600-row table with live filtering, the form with twenty conditional fields, the collaborative editor, the integration with that old library that has no types.
For Nómada Tasks, the hard case has been identified since 09-01: the virtualized list of 600 tasks with real-time filtering and incoming WebSocket updates. That is where you find out whether the tool is up to it.
How it is done, in one day:
| Hour | What |
|---|---|
| 0–1 | Set up the empty project and check that it builds and deploys |
| 1–3 | Implement the hard screen, with real or realistic data |
| 3–4 | Integrate the external piece you are worried about (the library, the WebSocket, the API) |
| 4–5 | Write one integration test and one end-to-end test |
| 5–6 | Measure: bytes, LCP, INP, memory after five minutes of use |
| 6–7 | Break it on purpose: network down, a 500 response, malformed data |
| 7–8 | Write half a page about what it cost, what surprised you and what you could not work out |
That last hour is the most valuable and the one always skipped. The list of what you could not work out in a day is the best prediction of what will cost you over a year.
And a golden rule: the prototype gets thrown away. It is not the start of the project, it is an experiment. If you turn it into the product's foundation, you will have chosen technology with code written in a hurry and without judgment.
- Migration strategies with no total rewrites
If you already have a working application —like Nómada Tasks— and you decide to change, there is a temptation that almost always ends badly: rewriting everything from scratch.
Why it fails, with concrete names:
- During the rewrite, the product does not move forward. The business does not stop and the pressure builds.
- The old version still needs fixes, so there are two codebases to maintain and keep in sync.
- The amount of business rules accumulated over years of fixes is systematically underestimated. Every odd
ifthat looks unnecessary is usually a real bug somebody fixed. - The most frequent outcome: six months later, an incomplete new version and an old one still in production.
The three strategies that do work, in order of granularity:
Strategy 1 · Migrate by route. The new application and the old one coexist, and a server or proxy decides which version serves each URL.
/board → old application (plain JavaScript) /reports → new application (React) /settings → new application
In favor: total isolation, each screen is migrated when its turn comes, you can stop at any moment without leaving anything half-done, and you learn with a real screen before committing. Against: navigating between screens of different generations means a full reload; and session, styles and state have to be shared between the two.
Strategy 2 · Migrate by component. The new framework is mounted inside the existing application, controlling a piece of screen.
// Mounting a new component inside the usual application
import { createRoot } from 'react-dom/client';
import { WorkloadReport } from './new/WorkloadReport.jsx';
const container = document.querySelector('#report-panel');
createRoot(container).render(<WorkloadReport tasks={board.tasks} />);Remember that 10-02's createRoot and 10-04's createApp(...).mount('#id') do exactly this: they take a DOM node and govern it, without touching the rest of the page. Vue is especially well prepared for this because of its progressive nature.
In favor: the finest possible granularity, with no reloads, with results from the first week.
Against: two worlds have to communicate —06-04's CustomEvents work perfectly as a bridge— and for a while two engines coexist on the same page, with their cost in bytes.
Strategy 3 · By layer, starting from the bottom. Sometimes the correct migration is not of the view. If your problem is state and not rendering, you first extract the model into a store, stabilize it, and only then change the view. In Nómada Tasks this is already done: js/model/ and js/data/ have been independent of the view from the start, and that is exactly the reason the domain file was identical in all four versions.
- Web components as a boundary
There is a fourth option that solves a specific problem: components that have to work anywhere, including an application from another generation or another framework.
Web components are a browser standard: customElements.define registers a tag of your own, the Shadow DOM genuinely isolates styles, and the result is an ordinary HTML element any page can use.
// A component that works on any page, with or without a framework
class TaskCard extends HTMLElement {
#controller = new AbortController();
connectedCallback() { // ← mount
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>:host { display: block; border-left: 4px solid var(--border, #ccc); }</style>
<h3></h3><button>Start</button>
`;
shadow.querySelector('h3').textContent = this.getAttribute('title');
shadow.querySelector('button').addEventListener(
'click',
() => this.dispatchEvent(new CustomEvent('advance', {
detail: { id: Number(this.dataset.id) }, bubbles: true
})),
{ signal: this.#controller.signal } // 09-03
);
}
disconnectedCallback() { // ← unmount: your destroy()
this.#controller.abort();
}
}
customElements.define('task-card', TaskCard);Notice what you already know how to do here: connectedCallback and disconnectedCallback are the lifecycle from 10-01, attachShadow is Vue's scoped taken to the standard, the CustomEvent with bubbles is your mechanism from 06-04, and the AbortController is your cleanup from 09-03. Web components are the lifecycle and the isolation without a framework.
| Web components | In favor | Against |
|---|---|---|
| Longevity | A standard: they will last as long as the web | — |
| Interoperability | They work in React, Vue, Angular and with nothing | Passing complex data through attributes is awkward |
| Isolation | Real Shadow DOM | Global styles do not get in: good and bad |
| Reactivity | — | None included: you have to write it or bring it |
| Ergonomics | — | Considerably more verbose than any framework |
| Ideal use | Embeddable widgets, shared design systems, migration boundaries | Complete applications |
The case where they shine and that is worth remembering: when two parts of an organization use different technologies and need to share components. A design system in web components is consumed by every team, today and when they change framework.
- What does not expire versus what does
Here is the balance sheet of the whole course, and it deserves a table:
| Does not expire | Does expire |
|---|---|
| The language: types, closures, prototypes, modules, promises, iterators (M1–M5) | A framework's specific syntax |
| The DOM and events: selection, delegation, a node's lifecycle (M6) | The name of the hook or directive of the day |
| HTTP and the network: statuses, headers, caching, cancellation, retries (M7) | The fashionable request library |
| Testing: unit, integration, end-to-end, doubles, queries by role (M8) | The specific test runner |
| Performance: measure before optimizing, critical path, memory, DOM, code splitting (M9) | A metric's exact thresholds |
| Accessibility: semantics, focus, announcements, keyboard | Each ecosystem's utilities |
The declarative model: UI = f(state), stable keys, lifecycle |
The implementation that realizes it |
| Modeling state: local, lifted, shared, server | Whichever store is fashionable |
| Judgment for deciding | The tools being decided between |
One figure from this module supports the table better than any argument: the domain/rules.js file was identical in all four versions of the screen. The same forty lines —NEXT, LABEL, WEIGHTS, TODAY, isOverdue— worked without a comma changed in plain JavaScript, in React, in Vue and in Angular. 100% of the code that changed was view.
That is the practical reason for the discipline 10-01 recommended and the five lessons have repeated: keep the business logic outside the framework. It is not architectural purism; it is what makes a change of framework mean rewriting the view and not rewriting the application.
And there is a personal consequence, beyond the code. What you learned in the previous nine modules you do not lose when you change tools. When the next framework appears —and it will— you will not be starting from zero: you will know what problem it claims to solve, with what mechanism, in exchange for what, and you will be able to judge it in an afternoon. That capability is the asset, not the list of tools you have used.
- Module 11: plain JavaScript, now by decision
It was said in 10-01 and it is confirmed here: the final project is built in plain JavaScript, with Nómada Tasks exactly as it is.
And now that statement has a justification you can defend with section 3's table. Applying it to the course's final project:
| Criterion | Weight | Why | Favors |
|---|---|---|---|
| The product's needs | 3 | One main screen, one flow, moderate complexity | A tie |
| Team size | 5 | One person: there are no conventions to share | Plain JS |
| Job market | 2 | It is a learning project, not a product | Neutral |
| Longevity | 4 | It must still work in your portfolio years from now, with no maintenance | Plain JS |
| Performance and weight | 4 | Already measured and optimized: 58.3 kB, LCP 1.9 s | Plain JS |
| Pedagogical goal | 5 | Demonstrating command of the language, the DOM, testing and performance | Plain JS |
| Ecosystem | 2 | Nothing specific is needed | Neutral |
| Cost of training | 3 | You already know how to do it | Plain JS |
The result is not ambiguous: for this project, in this context, plain JavaScript is the right choice. The application already exists, it is measured, it is tested with 124 tests and three end-to-end journeys, it has a working service worker and a performance budget in continuous integration. Adding a framework now would solve no problem you have and would add all of 10-01's costs.
What has changed is not the technology: it is that now you know why. In Module 1 you used plain JavaScript because it was all you knew. From now on you use it because, with the four approaches in front of you and the metrics measured, it is what this case calls for. And that difference —between doing something out of ignorance and doing it by decision— is probably the most valuable thing anybody takes away from a module like this one.
Common Mistakes and Tips
Choosing by performance comparisons. The differences between the big ones, in real applications, are milliseconds, and they get buried by how much data you request, how many images you load and where you render. Optimizing the framework choice for a 10,000-row benchmark is optimizing a row you do not have.
Choosing by popularity without looking at the local context. "It is the most used" is a global figure; you hire and work in a specific market. Look at real ads in your city and your sector.
Ignoring what the team already knows. The productivity of a team expert in one tool almost always beats that of a team new to an objectively better one. Changing framework has a learning cost that is rarely budgeted for.
Confusing "not using a framework" with "not using tooling". Nómada Tasks has Vite, ESLint, Prettier, Jest and Cypress. The decision not to use a component framework does not mean giving up the toolchain.
Rewriting from scratch. It is the decision that has sunk the most projects. Migrate by route or by component, with the application in production the whole time.
Forgetting the rendering decision. People argue for weeks about which framework and then decide in ten minutes that it will be an SPA, when that second decision usually has more impact on LCP, on SEO and on the architecture.
Believing that the framework gives you SEO or accessibility. None of them gives you either. They are given to you by the HTML you produce, the URLs you design, the real <a href>s, the focus you manage and the live regions you announce.
Putting business logic in the components. It is the mistake that makes the choice irreversible. The proof is on the table: 40 lines of domain identical in all four versions.
Evaluating only with the front-page example. It is chosen to look good. Prototype your hardest case, and spend the last hour writing down what you could not work out.
Tip: write the decision down. Half a page with the context, the criteria, the weights and the reasoning. Two years from now, when somebody asks "why do we use this?", the answer will exist and can be revisited with new data.
Tip: review the decision from time to time, without changing it out of habit. Contexts change —the team grows, an SEO requirement appears, the project stabilizes— and a decision that was right three years ago may not be right today. Reviewing is not migrating: it is checking.
Tip: learn one properly. After this module, pick one and build a complete project with it, with tests and deployment. The mental model transfers; real command does not.
Exercises
Exercise 1 · Your own weighting table
Pick a real project —yours, from your job, or one you would like to build— and fill in section 3's table completely:
- Describe the context in five lines: what it is, who uses it, how many people develop it, how long it must last.
- Assign the weights before scoring, and justify each one with a sentence.
- Score the four options, with a sentence of justification per cell.
- Compute the totals and read them with judgment: is there a clear winner or a tie? Does any criterion with weight 5 rule out an option on its own?
- Write the final decision in a paragraph, including what cost you are accepting.
Exercise 2 · Choosing where the rendering happens
For each of these four scenarios, decide the rendering mode (SPA, SSR, SSG or islands), name a suitable meta-framework and justify it with at least three criteria from the lesson. Also state which metric from 09-01 would be the most important to watch.
- (a) Taller Nómada's public website: who we are, prices, gallery, contact form and an availability calendar that updates every hour. It has to rank well. One person maintains it three hours a month.
- (b) Nómada Tasks as a product for twenty workshops, behind a sign-in, with real-time collaborative editing.
- (c) An online store with 4,000 products, prices that change daily and user reviews. 70% of the traffic arrives from search engines.
- (d) The public documentation for Nómada Tasks' API: 120 pages of text and code examples, a search box and a widget for trying out the calls.
Exercise 3 · Planning a migration
Three years later, Taller Nómada decides to migrate Nómada Tasks from plain JavaScript to a framework. The application then has seven screens, 380 tests and three people working on it. Development of new features cannot be paused.
- Choose the migration strategy and justify it.
- Write a five-phase plan, stating in each one what is migrated, what stays the same and how it is checked that nothing has broken.
- Which parts of the current code should not be migrated at all? Name them specifically.
- What would you do with the 380 tests? Classify them into those kept as they are, those that need adapting and those that need rewriting.
- Define three stopping criteria: objective signals that the migration is going badly and needs rethinking.
Solutions
Solution 1
There is no single solution, but there is one correct way of doing it and several incorrect ones. A worked example, to calibrate:
Context. An internal booking-management panel for a chain of five gyms. Twelve receptionists use it throughout their shift. Two people develop it, one with React experience and one with plain JavaScript. It must last at least five years. It is behind a sign-in, on desktop computers with a good connection.
Weights, with justification:
| Criterion | Weight | Why |
|---|---|---|
| The product's needs | 5 | Many forms, a calendar, permissions, ticket printing |
| Team | 4 | Two people: conventions matter, but less than with six |
| Job market | 3 | Somebody will have to be replaced within five years |
| Longevity | 5 | Five years with no possibility of stopping: the versioning policy is critical |
| Performance and weight | 1 | Desktop, a good connection, eight-hour sessions |
| SEO | 0 | Behind a sign-in: does not apply |
| Accessibility | 4 | Intensive keyboard use all day |
| Ecosystem | 4 | A serious calendar and data grid are needed |
| Training | 3 | One of the two people would have to learn |
Scores and total:
| Criterion | Weight | Plain JS | React | Vue | Angular |
|---|---|---|---|---|---|
| Product | 5 | 2 | 5 | 5 | 5 |
| Team | 4 | 2 | 4 | 4 | 5 |
| Market | 3 | 2 | 5 | 3 | 4 |
| Longevity | 5 | 5 | 3 | 4 | 5 |
| Performance | 1 | 5 | 3 | 4 | 3 |
| SEO | 0 | — | — | — | — |
| Accessibility | 4 | 4 | 3 | 3 | 3 |
| Ecosystem | 4 | 1 | 5 | 4 | 4 |
| Training | 3 | 3 | 5 | 4 | 2 |
| Total | 83 | 117 | 113 | 116 |
Reading. React and Angular tie (117 and 116), Vue is three points behind and plain JavaScript is ruled out. The tie is broken by a criterion the table does not score but that the brief does mention: one of the two people already knows React, and with a team of two that is worth more than any three-point difference.
Decision. React, with TypeScript from day one (to make up for the weak point against Angular in a five-year project) and with a written list of ecosystem decisions —router, forms, data, state— to mitigate the fragmentation with a small team.
Cost accepted. React's fragmentation forces us to maintain our own conventions and to update six third-party dependencies over five years, without Angular's automatic migrations. It is mitigated by choosing libraries with a demonstrated maintenance record and by reviewing the dependencies every six months.
What makes this solution correct is not the result, but that the weights were set beforehand, every cell has a reason, the tie is recognized as a tie and the cost is declared.
Solution 2
(a) Taller Nómada's public website → Static with islands (Astro).
Criteria: the content changes very rarely and is the same for everyone; SEO is critical and the HTML must arrive complete; maintenance is three hours a month, so ecosystem churn is the dominant risk; and only one element (the calendar) needs interactivity and fresh data.
Approach: the pages are generated statically and the calendar is an island that loads its JavaScript when it appears on screen, querying availability once loaded. The contact form can be native HTML posting to an endpoint, with no JavaScript at all.
Metric to watch: LCP, because it determines the first impression and is a ranking signal. With SSG it should be comfortably below 1 s.
(b) Nómada Tasks as a product → SPA.
Criteria: it is behind a sign-in, so SEO does not apply at all; the content is different for each user and not cacheable; collaborative editing requires client-side state and a permanent WebSocket connection; and the usage pattern is opening the application once and using it for hours, so the cost of the first load is amortized.
Approach: a pure SPA, with code splitting by route (09-05) so that the first screen is light.
Metric to watch: INP, because what decides the experience is the response to each interaction over eight hours, not the startup. It is exactly the row you brought down from 480 to 42 ms in module 9.
(c) A store with 4,000 products → SSR with caching, or static with incremental regeneration.
Criteria: 70% of the traffic comes from search engines, so the HTML has to arrive complete and fast; prices change daily, which rules out pure static without regeneration; reviews are user-generated content that must be indexed; and 4,000 pages make a complete rebuild on every change unworkable.
Approach: Next.js or Nuxt with server rendering and per-page caching, or static generation with incremental regeneration so that only the product pages whose price changed are rebuilt.
Metric to watch: LCP and, very closely, CLS: product pages with images and price blocks are where reserved dimensions are most often neglected, exactly the problem you closed out in 09-05.
(d) The API documentation → Static (SSG) with two islands.
Criteria: 120 pages of text that change with each version, the same for everyone; SEO matters because people arrive searching for specific errors; and only two things are interactive: the search box and the try-it widget.
Approach: SSG with a documentation generator, a search box with an index generated at build time —loaded lazily when the search field is focused— and the try-it widget as an island that only loads when expanded.
Metric to watch: the weight of the initial JavaScript. In documentation, most visits read one page and leave; every loaded kilobyte that goes unused is pure waste. It is row 10 of your 09-01 baseline.
Solution 3
1 · Strategy: migration by route, with shared components.
Justification: with seven screens and three people who cannot stop, migrating by route lets you work on a new screen while the others stay in production untouched, and it gives you the option of stopping at any point without leaving anything half-done. Component-level granularity is reserved for use inside an already-migrated screen.
2 · Five-phase plan:
| Phase | What is migrated | What stays the same | How it is checked |
|---|---|---|---|
| 1 · Preparation | No view code. The contract of model/ and data/ is isolated and documented; the new project is set up with the toolchain and the deployment |
The whole application | The 380 tests stay green; the new deployment serves an empty page |
| 2 · Pilot screen | The simplest and least critical screen (for example, Settings) | The other six | A specific Cypress journey + a manual check of session and shared styles |
| 3 · Secondary screens | Two or three read-only screens (reports, detail) | The board and the forms | End-to-end journeys per screen; comparison of metrics against the 09-01 baseline |
| 4 · The board | The main screen, including the virtualized list and the WebSocket | Nothing else | The three original journeys, adapted + load tests with 600 tasks |
| 5 · Removal | The old code, the dual routing and the dead dependencies are removed | — | Coverage, the performance budget in CI, and the absence of dead references |
Phase 2 has a goal that is not delivering value: discovering every integration problem —shared session, styles, common header, navigation between generations— with the screen that hurts least if it goes wrong.
3 · What should NOT be migrated:
- All of
js/model/:task.js,board.js,errors.js. They are plain JavaScript with rules R1–R10; they are imported as they are from the new framework. js/data/http.js:fetchJson,ApiErrorandwithRetriesfrom 07-03. No framework improves on this.js/util/:dates.js,format.jswithIntl,time.jswithdebounce,throttleandinBatches. Pure and reusable.js/data/realtime.js: theBoardChannel. The subscription changes place, the channel does not.sw.jsandmanifest.json: 07-05's service worker and PWA are framework-independent; the precache list just has to be regenerated.
That is, literally, most of the project's value. What gets migrated is js/view/.
4 · The 380 tests:
| Group | Approx. | What to do |
|---|---|---|
| Unit tests of model, data and utilities | ~200 | Kept as they are. They do not depend on the view |
| Integration with Testing Library (08-05) | ~120 | Adapted: the queries by role and userEvent are kept; only how the component is rendered changes |
| End-to-end with Cypress (08-06) | 3 journeys | Kept almost entirely: they operate on the real interface. If the data-ids and the roles were kept, there may be nothing to touch |
Unit tests coupled to view/'s specific DOM |
~57 | Rewritten: they tested reconcile, paintCard and the delegation, which cease to exist |
That split —around 85% kept or adapted— is the best demonstration of the value of integration tests by role over tests coupled to implementation details. It is exactly what 08-05 argued for, cashed in three years later.
5 · Three stopping criteria:
- Phase 2 takes more than three times the estimate. If migrating the simplest screen costs three weeks instead of one, the problem is not the screen: it is hidden coupling or a lack of command of the tool. You have to stop and find out which of the two.
- Development of new features drops by more than 30% for two consecutive months. The migration must coexist with the product. If it devours it, the by-route strategy is not being respected.
- The metrics get worse relative to the 09-01 baseline and do not recover within two weeks. If LCP goes from 1.9 to 3.5 s on the migrated screen and does not come down, something is wrong in the configuration or the approach, and migrating more screens only multiplies the problem.
A fourth criterion, informal but very reliable: if nobody on the team can explain why the migration is happening without using the word "modern", the decision had no judgment behind it and is worth revisiting.
Conclusion
You have closed the module with what gave it its point: the judgment for deciding.
You know the eight criteria that matter —the product's needs, the team's size and experience, the local job market, longevity, performance and SEO, accessibility, ecosystem and the cost of hiring and training— with the observation that five of the eight are not technical. You have the weighting table with its three rules of use: weights are set before scoring, a weight of 5 can veto, and every score is justified with a sentence. And you know how to read it honestly: it serves to rule out what does not fit and to recognize ties, not to manufacture a precision that does not exist.
You have the technical comparison of the four approaches —reactivity model, granularity, immutability, curve, size, opinions, tooling, typing, testing, SSR, ecosystem, fragmentation, global state, and where each one shines and where it gets in the way— with two nuances that prevent misunderstandings: React's fragmentation is a cost or an advantage depending on the context, and baseline size matters far less than people say except in widgets and content sites. And you have, above all, the four versions of your own screen measured: ~210 lines and 18 kB in plain JavaScript with 60 lines of your own infrastructure and a high risk of forgetting; ~130 lines and 63 kB in React; ~120 lines and 53 kB in Vue; ~180 lines and 85 kB in Angular with the key mistake made impossible by the compiler. With the conclusion no external comparison could have given you: a framework pays off when maintaining your own infrastructure costs more than downloading and learning theirs, and that point comes sooner with large teams and much later with one person alone.
You know that there is one decision that usually weighs more than the framework one: where the rendering happens. You know the SPA with its slow first load and its instant navigation; SSR with its complete HTML, its hydration and its server to maintain; SSG as the fastest, cheapest and most secure thing there is when the content does not change per user; and islands, which start from the observation that almost nothing on a page needs JavaScript —the same idea as your lazy loading from 09-05 taken to the architecture. You have the meta-frameworks placed in a table, including the uncomfortable htmx row, which questions the whole premise and is sometimes right; and the five-row rule that pairs a type of content with a rendering mode.
You know what a framework does and does not give you in SEO —complete HTML comes from SSR, and the rest is yours: titles, URLs, real <a href>s, semantics, structured data, sitemap, images and performance— and in accessibility, where the answer is blunter: none of them saves you from getting it wrong, and in fact all four make it easy to write a <div onClick> that works with a mouse and with nothing else. With the four failures that keep recurring and that you already know how to avoid: non-semantic elements, focus lost on update, changes that are not announced and silent SPA navigation.
You have a method for evaluating new technology: read the documentation looking for the declared limitations, check cadence and versioning policy with six concrete questions, measure your own example with 09-01's tools, and do the one-day prototype with the hardest case —not the most representative— spending the last hour writing down what you could not work out, which is the best prediction of what it will cost over a year. And you know that the prototype gets thrown away.
You know the migration strategies that work —by route, by component mounting the new framework on a node of the existing page, and by layer starting from the bottom— as against the total rewrite, which is the decision that has sunk the most projects. And you know that web components are the boundary when something needs to work anywhere: connectedCallback and disconnectedCallback are 10-01's lifecycle, attachShadow is style isolation taken to the standard, and the CustomEvent with bubbles is your mechanism from 06-04 — all without a framework and lasting as long as the platform itself.
And you have the final balance, backed by a figure from this very module and not by an opinion: the domain/rules.js file was identical in all four versions. The same forty lines in plain JavaScript, React, Vue and Angular. Everything that changed was view. That is what separates what does not expire —the language, the DOM, HTTP, testing, performance, accessibility, the declarative model, knowing how to model state and the judgment for deciding— from what does: the specific syntax, the name of the hook, the library of the day, the exact thresholds.
Module 11 begins now, and the final project is built in plain JavaScript, with Nómada Tasks exactly as you have left it: six tasks and 48 hours on the board, its rules R1–R10, its 124 tests and its three end-to-end journeys, its service worker, its 58.3 kB across three requests and its LCP of 1.9 seconds. None of that changes. What has changed is who decides it: in Module 1 you wrote plain JavaScript because it was all you knew, and now you write it with React, Vue and Angular on the table, with the four versions of the same screen measured and with a weighting table that says, for this project and this context, that it is the right choice. That is the whole difference between a beginner and a professional, and it is not in the tool: a beginner uses what they know; a professional chooses, knows why, and can defend it. With that capability —and with an application that works, is tested, is measured and is deployed— what remains begins: Project Setup and Planning.
JavaScript Course: From Beginner to Advanced
Module 1: Introduction to JavaScript
- What Is JavaScript?
- Setting Up Your Development Environment
- Your First JavaScript Program
- JavaScript Syntax and Basic Concepts
- Variables and Data Types
- Basic Operators
- Type Conversion and Comparisons
- The Course Project: Nómada Tasks
Module 2: Control Structures
- Conditional Statements
- Loops: for, while, do-while
- Switch Statements
- Flow Control: break, continue and Nested Loops
- Error Handling with try-catch
Module 3: Functions
- Defining and Calling Functions
- Function Expressions and Arrow Functions
- Parameters and Return Values
- Scope and Closures
- Hoisting and the Execution Context
- Higher-Order Functions
- Recursion
Module 4: Objects and Arrays
- Introduction to Objects
- Object Methods and the
thisKeyword - Arrays: Basics and Methods
- Iterating over Arrays
- Searching, Sorting and Aggregating Data: find, sort and reduce
- Array Destructuring
- Object Destructuring, Spread and Rest
- JSON and Copying Objects
Module 5: Advanced Objects and Functions
- Prototypes and Inheritance
- Classes and Object-Oriented Programming
- Encapsulation: Getters, Setters and Private Fields
- Modules: Import and Export
- Asynchronous JavaScript: Callbacks
- Promises and Async/Await
- The Event Loop and the Microtask Queue
- Iterators and Generators
Module 6: The Document Object Model (DOM)
- Introduction to the DOM
- Selecting and Manipulating DOM Elements
- Handling Events
- Propagation, Delegation and Custom Events
- Creating and Removing DOM Elements
- Rendering Lists and HTML Templates
- Handling and Validating Forms
Module 7: Browser APIs and Advanced Topics
- Local and Session Storage
- The Fetch API and AJAX
- Robust Requests: Errors, Timeouts and AbortController
- WebSockets
- Service Workers and Progressive Web Apps (PWAs)
- Essential Browser APIs
- Introduction to WebAssembly
Module 8: Testing and Debugging
- Debugging JavaScript
- Code Quality: ESLint, Prettier and Conventions
- Unit Testing with Jest
- Test Doubles: Mocks, Stubs and Spies
- Integration Testing
- End-to-End Testing with Cypress
Module 9: Performance and Optimization
- Measure Before You Optimize: DevTools and Web Vitals
- Optimizing JavaScript Performance
- Memory Management
- Efficient DOM Manipulation
- Lazy Loading and Code Splitting
Module 10: JavaScript Frameworks and Libraries
- Why Frameworks Exist
- Introduction to React
- State Management with Redux
- Vue.js Basics
- Angular Basics
- Choosing the Right Framework
