From cc5f53c09cbe18afbe44e74b5587fa0649d6758e Mon Sep 17 00:00:00 2001 From: Ryanditko Date: Fri, 24 Jul 2026 16:33:06 -0300 Subject: [PATCH 1/7] content(frontend/advanced): enrich 10 briefs into guided exercises (bilingual) Architecture/module sketches and non-functional requirements (performance budgets, bundle size, accessibility, resilience); PT-BR versions. Guidance only, framework-agnostic. Co-Authored-By: Claude Opus 4.8 --- .../01-microfrontend-architecture/README.md | 125 ++++++++++++----- .../README.pt-BR.md | 100 ++++++++++++++ .../02-collaborative-editor/README.md | 120 ++++++++++++----- .../02-collaborative-editor/README.pt-BR.md | 94 +++++++++++++ .../advanced/03-design-system/README.md | 122 ++++++++++++----- .../advanced/03-design-system/README.pt-BR.md | 96 +++++++++++++ .../advanced/04-offline-first-pwa/README.md | 124 ++++++++++++----- .../04-offline-first-pwa/README.pt-BR.md | 98 ++++++++++++++ .../advanced/05-streaming-ui/README.md | 127 +++++++++++++----- .../advanced/05-streaming-ui/README.pt-BR.md | 101 ++++++++++++++ .../06-performance-optimized-app/README.md | 123 ++++++++++++----- .../README.pt-BR.md | 97 +++++++++++++ .../advanced/07-accessibility-ui/README.md | 124 ++++++++++++----- .../07-accessibility-ui/README.pt-BR.md | 98 ++++++++++++++ .../advanced/08-visual-page-builder/README.md | 125 ++++++++++++----- .../08-visual-page-builder/README.pt-BR.md | 99 ++++++++++++++ .../09-data-heavy-dashboard/README.md | 126 ++++++++++++----- .../09-data-heavy-dashboard/README.pt-BR.md | 100 ++++++++++++++ .../advanced/10-observability-tool/README.md | 126 ++++++++++++----- .../10-observability-tool/README.pt-BR.md | 100 ++++++++++++++ 20 files changed, 1925 insertions(+), 300 deletions(-) create mode 100644 projects/frontend/advanced/01-microfrontend-architecture/README.pt-BR.md create mode 100644 projects/frontend/advanced/02-collaborative-editor/README.pt-BR.md create mode 100644 projects/frontend/advanced/03-design-system/README.pt-BR.md create mode 100644 projects/frontend/advanced/04-offline-first-pwa/README.pt-BR.md create mode 100644 projects/frontend/advanced/05-streaming-ui/README.pt-BR.md create mode 100644 projects/frontend/advanced/06-performance-optimized-app/README.pt-BR.md create mode 100644 projects/frontend/advanced/07-accessibility-ui/README.pt-BR.md create mode 100644 projects/frontend/advanced/08-visual-page-builder/README.pt-BR.md create mode 100644 projects/frontend/advanced/09-data-heavy-dashboard/README.pt-BR.md create mode 100644 projects/frontend/advanced/10-observability-tool/README.pt-BR.md diff --git a/projects/frontend/advanced/01-microfrontend-architecture/README.md b/projects/frontend/advanced/01-microfrontend-architecture/README.md index f5acc9b..03cf2a0 100644 --- a/projects/frontend/advanced/01-microfrontend-architecture/README.md +++ b/projects/frontend/advanced/01-microfrontend-architecture/README.md @@ -1,34 +1,99 @@ # Microfrontend Architecture -## Idea -Design a system where multiple frontend applications are composed together. Learn about module federation, independent deployment, and shared dependencies. +> 🌐 **English** · [Português](./README.pt-BR.md) + +**Domain:** Frontend · **Level:** Advanced · **Estimated time:** 1–2 weeks + +## Overview + +Split a single large frontend into several independently built and deployed applications that compose into one seamless product at runtime — the pattern behind large-scale UIs at Spotify, IKEA, and DAZN. A "shell" (host) loads feature apps (remotes) on demand, so teams ship on their own cadence without a shared release train. The hard parts are not the loading mechanics but the boundaries: shared dependency versions, cross-app communication, consistent routing, and a shell that degrades gracefully when a remote fails. This project makes you confront the trade-off at the heart of every microfrontend system — team autonomy versus product consistency — and forces you to defend it with real measurements rather than opinion. + +## Prerequisites + +- A production-grade single-page app under your belt (the [Admin Panel](../../intermediate/05-admin-panel/) is a good baseline) +- Solid grasp of ES modules, bundling, and code splitting +- Comfort with client-side routing and its history model +- Familiarity with a bundler that supports federation (Vite, Webpack 5, or Rspack) ## Learning Objectives -- Implement module federation -- Create independent applications -- Share common dependencies -- Handle communication between microfrontends -- Manage routing across apps - -## Implementation Tips -- Use module federation tool (Webpack 5, Vite, etc.) -- Create separate frontend apps -- Share common libraries -- Implement app routing -- Create communication layer -- Handle shared state -- Implement authentication sharing -- Create deployment strategy -- Add versioning for apps -- Implement fallback UI -- Create monitoring -- Add dependency management -- Implement hot reloading -- Create development experience tooling - -## Key Challenges -- Dependency version conflicts -- App communication complexity -- State management across apps -- Shared state consistency -- Performance optimization + +By the end, you should be able to: + +- Compose multiple independently deployed apps behind one shell at runtime +- Share heavy libraries (framework runtime, design system) as singletons to avoid duplication +- Design a decoupled communication contract between remotes without shared global state +- Coordinate routing so deep links resolve correctly across app boundaries +- Isolate failures so one broken remote never blanks the whole page + +## Functional Requirements + +1. A host shell must dynamically load at least two independently built remote applications at runtime. +2. Each remote must be buildable and deployable on its own, without rebuilding the shell. +3. Shared framework and design-system libraries must resolve to a single shared instance, not one copy per remote. +4. The shell must own top-level routing and delegate sub-routes to the owning remote. +5. Remotes must communicate through an explicit contract (custom events or an injected event bus), never by reaching into each other's internals. +6. If a remote fails to load or throws on mount, the shell must render a fallback and keep the rest of the page usable. +7. Version metadata for each loaded remote must be observable at runtime (e.g. logged or shown in a debug panel). + +## Suggested Milestones + +1. **Milestone 1 — Shell + one remote:** Stand up a host that loads a single remote via module federation and renders it in a route. +2. **Milestone 2 — Second remote & shared deps:** Add a second remote and configure shared singletons; prove only one framework copy ships. +3. **Milestone 3 — Communication & routing:** Wire cross-remote messaging and end-to-end deep-link routing across boundaries. +4. **Milestone 4 — Resilience & versioning:** Add error boundaries, load fallbacks, and runtime version reporting per remote. + +## Data & Interface Sketch + +```text + ┌──────────────────────────────┐ + │ Shell (host) │ + │ routing · layout · auth │ + │ shared singletons ↓ │ + └───────┬───────────┬───────────┘ + loads at runtime │ │ loads at runtime + ┌─────────▼──┐ ┌────▼───────┐ + │ Remote A │ │ Remote B │ + │ (own repo, │ │ (own repo, │ + │ own build)│ │ own build)│ + └─────┬──────┘ └─────┬──────┘ + └──── event bus ──┘ (decoupled contract) + +Shared singletons: framework runtime, design-system, i18n +Communication: window CustomEvent | injected pub/sub | URL state +Failure mode: remote load rejects -> shell renders + +Non-functional targets: + shell-only JS <= 100 KB gzipped + remote entry <= 30 KB gzipped + broken remote -> rest of page stays interactive +``` + +## Stretch Goals + +- Add a runtime registry so remotes can be added without editing the shell config. +- Implement independent CI/CD where each remote publishes a versioned `remoteEntry` to a CDN. +- Support two frameworks in different remotes (e.g. React + Vue) to prove true isolation. +- Add server-side composition or an app-shell prerender for first-paint performance. + +## Definition of Done + +- [ ] Two remotes deploy independently and the shell picks up new versions without a rebuild. +- [ ] Bundle analysis proves shared libraries load once, not once per remote. +- [ ] A deliberately broken remote shows a fallback while the rest of the page stays interactive. +- [ ] Deep links into a remote's sub-route load correctly on a cold page load. +- [ ] Remotes exchange at least one message through the agreed contract, with no direct imports between them. + +## Common Pitfalls + +- Mismatched shared-dependency versions causing two framework copies to load and hooks to break subtly. +- Coupling remotes through a shared global object instead of an explicit contract — it recreates the monolith you were escaping. +- Letting each remote own routing, producing conflicting history writes and broken back-button behavior. +- Ignoring the failure path, so one 404 on a `remoteEntry` blanks the entire screen. +- Duplicating CSS resets and design tokens per remote, causing visual drift across boundaries. + +## Resources + +- [Module Federation documentation](https://module-federation.io/) — the canonical guide to the federation runtime and shared scopes. +- [martinfowler.com: Micro Frontends](https://martinfowler.com/articles/micro-frontends.html) — the reference article on the architecture and its trade-offs. +- [web.dev: Reduce JavaScript payloads with code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) — the bundling foundation federation builds on. +- [MDN: CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) — a framework-agnostic way to build a decoupled event bus. diff --git a/projects/frontend/advanced/01-microfrontend-architecture/README.pt-BR.md b/projects/frontend/advanced/01-microfrontend-architecture/README.pt-BR.md new file mode 100644 index 0000000..4e33bab --- /dev/null +++ b/projects/frontend/advanced/01-microfrontend-architecture/README.pt-BR.md @@ -0,0 +1,100 @@ +# Arquitetura de Microfrontends + +> 🌐 [English](./README.md) · **Português** + +**Domínio:** Frontend · **Nível:** Avançado · **Tempo estimado:** 1–2 semanas + +## Visão Geral + +Divida um único frontend grande em várias aplicações construídas e implantadas de forma independente que se compõem em um produto único e coeso em tempo de execução — o padrão por trás de UIs em larga escala no Spotify, na IKEA e na DAZN. Um "shell" (host) carrega apps de funcionalidades (remotes) sob demanda, para que os times entreguem no seu próprio ritmo sem um trem de release compartilhado. As partes difíceis não são os mecanismos de carregamento, mas as fronteiras: versões de dependências compartilhadas, comunicação entre apps, roteamento consistente e um shell que degrada com elegância quando um remote falha. Este projeto força você a encarar o trade-off no coração de todo sistema de microfrontends — autonomia dos times versus consistência do produto — e a defendê-lo com medições reais, não com opinião. + +## Pré-requisitos + +- Uma SPA de nível de produção já construída (o [Painel Administrativo](../../intermediate/05-admin-panel/) é uma boa base) +- Domínio sólido de módulos ES, empacotamento e code splitting +- Conforto com roteamento no cliente e seu modelo de histórico +- Familiaridade com um bundler que suporte federação (Vite, Webpack 5 ou Rspack) + +## Objetivos de Aprendizado + +Ao final, você deve ser capaz de: + +- Compor múltiplos apps implantados de forma independente atrás de um shell em tempo de execução +- Compartilhar bibliotecas pesadas (runtime do framework, design system) como singletons para evitar duplicação +- Projetar um contrato de comunicação desacoplado entre remotes sem estado global compartilhado +- Coordenar o roteamento para que deep links resolvam corretamente através das fronteiras dos apps +- Isolar falhas para que um remote quebrado nunca apague a página inteira + +## Requisitos Funcionais + +1. Um shell host deve carregar dinamicamente pelo menos duas aplicações remote construídas de forma independente em tempo de execução. +2. Cada remote deve ser construível e implantável por conta própria, sem reconstruir o shell. +3. As bibliotecas de framework e design system compartilhadas devem resolver para uma única instância, não uma cópia por remote. +4. O shell deve ser dono do roteamento de nível superior e delegar sub-rotas ao remote responsável. +5. Os remotes devem se comunicar por um contrato explícito (eventos customizados ou um event bus injetado), nunca acessando as entranhas um do outro. +6. Se um remote falhar ao carregar ou lançar erro na montagem, o shell deve renderizar um fallback e manter o resto da página utilizável. +7. Os metadados de versão de cada remote carregado devem ser observáveis em tempo de execução (ex.: logados ou exibidos em um painel de debug). + +## Marcos Sugeridos + +1. **Marco 1 — Shell + um remote:** Suba um host que carrega um único remote via module federation e o renderiza em uma rota. +2. **Marco 2 — Segundo remote e deps compartilhadas:** Adicione um segundo remote e configure singletons compartilhados; prove que só uma cópia do framework é enviada. +3. **Marco 3 — Comunicação e roteamento:** Conecte a mensageria entre remotes e o roteamento por deep link de ponta a ponta entre fronteiras. +4. **Marco 4 — Resiliência e versionamento:** Adicione error boundaries, fallbacks de carga e relato de versão em tempo de execução por remote. + +## Esboço de Dados e Interface + +```text + ┌──────────────────────────────┐ + │ Shell (host) │ + │ roteamento · layout · auth │ + │ singletons compartilhados ↓ │ + └───────┬───────────┬───────────┘ + carrega em runtime │ │ carrega em runtime + ┌─────────▼──┐ ┌────▼───────┐ + │ Remote A │ │ Remote B │ + │ (repo e │ │ (repo e │ + │ build │ │ build │ + │ próprios) │ │ próprios) │ + └─────┬──────┘ └─────┬──────┘ + └──── event bus ──┘ (contrato desacoplado) + +Singletons compartilhados: runtime do framework, design system, i18n +Comunicação: window CustomEvent | pub/sub injetado | estado na URL +Modo de falha: carga do remote rejeita -> shell renderiza + +Metas não funcionais: + JS só do shell <= 100 KB gzipado + entry do remote <= 30 KB gzipado + remote quebrado -> resto da página segue interativo +``` + +## Desafios Extras + +- Adicione um registro em tempo de execução para que remotes possam ser adicionados sem editar a config do shell. +- Implemente CI/CD independente onde cada remote publica um `remoteEntry` versionado em uma CDN. +- Suporte dois frameworks em remotes diferentes (ex.: React + Vue) para provar isolamento real. +- Adicione composição no servidor ou um prerender de app-shell para desempenho de primeira pintura. + +## Definição de Pronto + +- [ ] Dois remotes implantam de forma independente e o shell adota novas versões sem um rebuild. +- [ ] A análise de bundle prova que as bibliotecas compartilhadas carregam uma vez, não uma por remote. +- [ ] Um remote deliberadamente quebrado mostra um fallback enquanto o resto da página segue interativo. +- [ ] Deep links para a sub-rota de um remote carregam corretamente em um carregamento frio. +- [ ] Os remotes trocam pelo menos uma mensagem pelo contrato acordado, sem imports diretos entre eles. + +## Armadilhas Comuns + +- Versões incompatíveis de dependências compartilhadas fazendo duas cópias do framework carregarem e os hooks quebrarem de forma sutil. +- Acoplar remotes por um objeto global compartilhado em vez de um contrato explícito — recria o monólito do qual você fugia. +- Deixar cada remote dono do roteamento, produzindo escritas de histórico conflitantes e um botão voltar quebrado. +- Ignorar o caminho de falha, de modo que um 404 em um `remoteEntry` apaga a tela inteira. +- Duplicar resets de CSS e design tokens por remote, causando desvio visual entre fronteiras. + +## Recursos + +- [Documentação do Module Federation](https://module-federation.io/) — o guia canônico do runtime de federação e dos escopos compartilhados. +- [martinfowler.com: Micro Frontends](https://martinfowler.com/articles/micro-frontends.html) — o artigo de referência sobre a arquitetura e seus trade-offs. +- [web.dev: Reduza payloads de JavaScript com code splitting](https://web.dev/articles/reduce-javascript-payloads-with-code-splitting) — a base de empacotamento sobre a qual a federação se apoia. +- [MDN: CustomEvent](https://developer.mozilla.org/pt-BR/docs/Web/API/CustomEvent) — uma forma agnóstica de framework para construir um event bus desacoplado. diff --git a/projects/frontend/advanced/02-collaborative-editor/README.md b/projects/frontend/advanced/02-collaborative-editor/README.md index 0da85a1..7b1addb 100644 --- a/projects/frontend/advanced/02-collaborative-editor/README.md +++ b/projects/frontend/advanced/02-collaborative-editor/README.md @@ -1,34 +1,94 @@ # Real-time Collaborative Editor (like Google Docs) -## Idea -Build a collaborative document editor supporting real-time synchronization. Learn about operational transformation, WebSockets, and conflict resolution. +> 🌐 **English** · [Português](./README.pt-BR.md) + +**Domain:** Frontend · **Level:** Advanced · **Estimated time:** 1–2 weeks + +## Overview + +Build a document editor where several people type into the same document at once and every keystroke shows up on everyone's screen within moments — the experience Google Docs, Notion, and Figma popularized. The deceptively simple demo hides the hardest problem in collaborative software: two users edit the same spot offline, then reconnect, and the system must merge both intents into one consistent document without a central lock. You will lean on a proven convergence algorithm (CRDT or operational transformation) rather than inventing your own, and spend your energy on the frontend concerns that make it feel alive: remote cursors, presence, and an editor that never blocks the local typist waiting on the network. + +## Prerequisites + +- Comfortable building interactive apps with real-time state (a [Chat Application](../../intermediate/04-chat-ui/) is a good stepping stone) +- Working knowledge of WebSockets and event-driven data flow +- Understanding of the browser Selection and Range APIs, or a rich-text framework +- Awareness that naive "last write wins" loses data — the motivation for this project ## Learning Objectives -- Implement operational transformation -- Sync changes across clients -- Handle concurrent edits -- Manage merge conflicts -- Build presence indicators - -## Implementation Tips -- Implement cursor positions -- Add collaborative editing library (Yjs, Automerge) -- Create presence awareness -- Implement change tracking -- Add version history -- Implement undo/redo -- Create sharing functionality -- Implement permissions -- Add commenting system -- Create revision comparison -- Implement real-time sync -- Add offline support -- Create notification for changes -- Implement conflict resolution - -## Key Challenges -- Operational transformation complexity -- Real-time synchronization -- Merge conflict resolution -- Performance with many users -- State consistency + +By the end, you should be able to: + +- Explain why concurrent edits need CRDTs or OT rather than a simple locking scheme +- Integrate a convergence library (Yjs or Automerge) with a rich-text editing surface +- Render remote cursors and selections mapped to positions in the live document +- Keep local edits instant (optimistic) while background sync reconciles state +- Preserve edits made offline and merge them cleanly on reconnection + +## Functional Requirements + +1. Two or more clients editing the same document must converge to identical content after all changes propagate. +2. A local edit must appear instantly, without waiting for a server round-trip. +3. Each connected user's cursor and text selection must be visible to others, labelled and colored per user. +4. A presence list must show who is currently in the document and update on join/leave. +5. Edits made while offline must be retained and merged automatically once the connection returns. +6. Concurrent edits to the same region must merge deterministically, never silently dropping a user's input. +7. Undo/redo must operate on the local user's own changes without reverting other users' edits. + +## Suggested Milestones + +1. **Milestone 1 — Single-user editor + transport:** Build the editing surface and a WebSocket channel that echoes changes. +2. **Milestone 2 — Convergence:** Adopt a CRDT/OT library so two clients merge concurrent edits correctly. +3. **Milestone 3 — Presence & cursors:** Broadcast and render remote cursors, selections, and a live presence list. +4. **Milestone 4 — Offline & history:** Queue offline edits, merge on reconnect, and add per-user undo/redo. + +## Data & Interface Sketch + +```text + Client A Sync server Client B + ┌──────────┐ local ops ┌───────────────┐ ops ┌──────────┐ + │ editor │ ───────────────▶│ relay + doc │───────────▶│ editor │ + │ CRDT doc │◀─────────────── │ state (opt.) │◀───────────│ CRDT doc │ + └────┬─────┘ remote ops └───────────────┘ └────┬─────┘ + │ optimistic apply (instant, local-first) │ + └── presence: { userId, name, color, cursor, selection } ─┘ + +Op (conceptual): { type: insert|delete, pos, value?, origin, lamport } +Awareness: ephemeral, not persisted — cursors, presence, typing +Convergence: CRDT (Yjs / Automerge) or OT — pick and justify + +Non-functional targets: + local keystroke -> on screen < 16 ms (no network wait) + edit -> peer visible < 250 ms on a healthy link + offline edits never lost on reconnect +``` + +## Stretch Goals + +- Add a version history with named snapshots and a diff view between revisions. +- Support inline comments and suggestions anchored to a text range that survive edits. +- Add document-level permissions (view / comment / edit) enforced on the server. +- Show a "reconnecting" state with an edit queue counter, then a clean catch-up animation. + +## Definition of Done + +- [ ] Two browsers editing simultaneously end with byte-identical documents. +- [ ] Typing feels instant even with artificial network latency added in dev tools. +- [ ] Remote cursors track the correct character position as text is inserted above them. +- [ ] Disconnecting one client, editing on both, then reconnecting merges without data loss. +- [ ] Undo reverts only the local user's last action, leaving remote edits intact. + +## Common Pitfalls + +- Reinventing operational transformation from scratch — it is notoriously subtle; use a vetted library. +- Storing cursor positions as absolute offsets, so they point to the wrong place after remote inserts. +- Persisting ephemeral awareness data (cursors, presence) into the document and bloating it. +- Blocking the UI on server acknowledgement, destroying the instant-typing feel. +- Assuming ordered, reliable delivery — networks reorder and drop; the merge must not depend on arrival order. + +## Resources + +- [Yjs documentation](https://docs.yjs.dev/) — a mature CRDT framework with editor bindings and an awareness protocol. +- [Automerge](https://automerge.org/) — an alternative CRDT library with a strong data-structure model. +- [Martin Kleppmann: CRDTs — the hard parts](https://www.youtube.com/watch?v=x7drE24geUw) — a rigorous talk on convergence guarantees. +- [MDN: Selection API](https://developer.mozilla.org/en-US/docs/Web/API/Selection) — the browser primitive behind cursor and range handling. diff --git a/projects/frontend/advanced/02-collaborative-editor/README.pt-BR.md b/projects/frontend/advanced/02-collaborative-editor/README.pt-BR.md new file mode 100644 index 0000000..943e486 --- /dev/null +++ b/projects/frontend/advanced/02-collaborative-editor/README.pt-BR.md @@ -0,0 +1,94 @@ +# Editor Colaborativo em Tempo Real (como o Google Docs) + +> 🌐 [English](./README.md) · **Português** + +**Domínio:** Frontend · **Nível:** Avançado · **Tempo estimado:** 1–2 semanas + +## Visão Geral + +Construa um editor de documentos onde várias pessoas digitam no mesmo documento ao mesmo tempo e cada tecla aparece na tela de todos em instantes — a experiência que o Google Docs, o Notion e o Figma popularizaram. A demo enganosamente simples esconde o problema mais difícil do software colaborativo: dois usuários editam o mesmo ponto offline, reconectam, e o sistema deve fundir ambas as intenções em um documento consistente sem um lock central. Você vai se apoiar em um algoritmo de convergência comprovado (CRDT ou transformação operacional) em vez de inventar o seu, e gastar sua energia nas preocupações de frontend que fazem tudo parecer vivo: cursores remotos, presença e um editor que nunca trava o digitador local esperando a rede. + +## Pré-requisitos + +- Conforto em construir apps interativos com estado em tempo real (uma [Aplicação de Chat](../../intermediate/04-chat-ui/) é um bom degrau) +- Conhecimento prático de WebSockets e fluxo de dados orientado a eventos +- Entendimento das APIs Selection e Range do navegador, ou de um framework de rich-text +- Consciência de que o ingênuo "last write wins" perde dados — a motivação deste projeto + +## Objetivos de Aprendizado + +Ao final, você deve ser capaz de: + +- Explicar por que edições concorrentes precisam de CRDTs ou OT em vez de um esquema simples de lock +- Integrar uma biblioteca de convergência (Yjs ou Automerge) com uma superfície de edição rich-text +- Renderizar cursores e seleções remotas mapeados para posições no documento vivo +- Manter as edições locais instantâneas (otimistas) enquanto a sincronização em segundo plano reconcilia o estado +- Preservar edições feitas offline e fundi-las de forma limpa na reconexão + +## Requisitos Funcionais + +1. Dois ou mais clientes editando o mesmo documento devem convergir para conteúdo idêntico após todas as mudanças se propagarem. +2. Uma edição local deve aparecer instantaneamente, sem esperar por uma ida e volta ao servidor. +3. O cursor e a seleção de texto de cada usuário conectado devem ser visíveis aos demais, rotulados e coloridos por usuário. +4. Uma lista de presença deve mostrar quem está atualmente no documento e atualizar ao entrar/sair. +5. Edições feitas offline devem ser retidas e fundidas automaticamente assim que a conexão retornar. +6. Edições concorrentes na mesma região devem fundir de forma determinística, nunca descartando silenciosamente a entrada de um usuário. +7. Desfazer/refazer deve operar sobre as próprias mudanças do usuário local sem reverter as edições dos outros. + +## Marcos Sugeridos + +1. **Marco 1 — Editor de usuário único + transporte:** Construa a superfície de edição e um canal WebSocket que ecoa as mudanças. +2. **Marco 2 — Convergência:** Adote uma biblioteca CRDT/OT para que dois clientes fundam edições concorrentes corretamente. +3. **Marco 3 — Presença e cursores:** Transmita e renderize cursores remotos, seleções e uma lista de presença ao vivo. +4. **Marco 4 — Offline e histórico:** Enfileire edições offline, funda na reconexão e adicione desfazer/refazer por usuário. + +## Esboço de Dados e Interface + +```text + Cliente A Servidor de sync Cliente B + ┌──────────┐ ops locais ┌───────────────┐ ops ┌──────────┐ + │ editor │ ───────────────▶│ relay + estado│───────────▶│ editor │ + │ doc CRDT │◀─────────────── │ do doc (opc.) │◀───────────│ doc CRDT │ + └────┬─────┘ ops remotas └───────────────┘ └────┬─────┘ + │ aplicação otimista (instantânea, local-first) │ + └── presença: { userId, nome, cor, cursor, selection } ───┘ + +Op (conceitual): { type: insert|delete, pos, value?, origin, lamport } +Awareness: efêmero, não persistido — cursores, presença, digitação +Convergência: CRDT (Yjs / Automerge) ou OT — escolha e justifique + +Metas não funcionais: + tecla local -> na tela < 16 ms (sem espera de rede) + edição -> visível no par < 250 ms em um link saudável + edições offline nunca perdidas na reconexão +``` + +## Desafios Extras + +- Adicione um histórico de versões com snapshots nomeados e uma visão de diff entre revisões. +- Suporte comentários e sugestões inline ancorados a um intervalo de texto que sobrevivem às edições. +- Adicione permissões em nível de documento (visualizar / comentar / editar) aplicadas no servidor. +- Mostre um estado de "reconectando" com um contador da fila de edições, depois uma animação limpa de recuperação. + +## Definição de Pronto + +- [ ] Dois navegadores editando simultaneamente terminam com documentos byte a byte idênticos. +- [ ] A digitação parece instantânea mesmo com latência de rede artificial adicionada no dev tools. +- [ ] Cursores remotos acompanham a posição de caractere correta conforme texto é inserido acima deles. +- [ ] Desconectar um cliente, editar em ambos e reconectar funde sem perda de dados. +- [ ] Desfazer reverte apenas a última ação do usuário local, deixando as edições remotas intactas. + +## Armadilhas Comuns + +- Reinventar a transformação operacional do zero — é notoriamente sutil; use uma biblioteca testada. +- Armazenar posições de cursor como offsets absolutos, apontando para o lugar errado após inserções remotas. +- Persistir dados efêmeros de awareness (cursores, presença) no documento e inchá-lo. +- Bloquear a UI esperando o reconhecimento do servidor, destruindo a sensação de digitação instantânea. +- Assumir entrega ordenada e confiável — redes reordenam e descartam; a fusão não pode depender da ordem de chegada. + +## Recursos + +- [Documentação do Yjs](https://docs.yjs.dev/) — um framework CRDT maduro com bindings de editor e um protocolo de awareness. +- [Automerge](https://automerge.org/) — uma biblioteca CRDT alternativa com um forte modelo de estrutura de dados. +- [Martin Kleppmann: CRDTs — the hard parts](https://www.youtube.com/watch?v=x7drE24geUw) — uma palestra rigorosa sobre garantias de convergência. +- [MDN: Selection API](https://developer.mozilla.org/pt-BR/docs/Web/API/Selection) — a primitiva do navegador por trás do tratamento de cursor e intervalo. diff --git a/projects/frontend/advanced/03-design-system/README.md b/projects/frontend/advanced/03-design-system/README.md index a383197..ecaff30 100644 --- a/projects/frontend/advanced/03-design-system/README.md +++ b/projects/frontend/advanced/03-design-system/README.md @@ -1,34 +1,96 @@ # Full Design System (component library) -## Idea -Create a comprehensive design system with reusable components, documentation, and Storybook integration. Learn about component design and documentation. +> 🌐 **English** · [Português](./README.pt-BR.md) + +**Domain:** Frontend · **Level:** Advanced · **Estimated time:** 1–2 weeks + +## Overview + +Build the shared visual foundation that many product teams consume — the layer behind Material, Carbon, and Polaris. A real design system is more than a folder of components: it is a token layer (colors, spacing, type) that feeds themeable, accessible components, published as a versioned package with living documentation. The engineering challenge is governance at scale. How do you evolve a button used by forty screens without breaking any of them? How do you catch a one-pixel visual regression before a consumer does? This project treats the system as a product with its own users, its own release process, and its own contract — semantic versioning, visual regression tests, and docs that never drift from the code. + +## Prerequisites + +- Solid component-authoring experience in one framework +- Understanding of CSS custom properties and the cascade +- Familiarity with a package registry and semantic versioning +- Comfort setting up a build that emits a distributable library ## Learning Objectives -- Design component architecture -- Implement component library -- Create documentation -- Build Storybook stories -- Manage component versioning - -## Implementation Tips -- Define design tokens (colors, spacing, typography) -- Create base components (buttons, inputs, cards) -- Build composite components -- Implement accessibility features -- Create Storybook documentation -- Add component variations -- Create usage guidelines -- Implement theming support -- Add responsive design -- Create component testing -- Build changelog -- Implement versioning strategy -- Create component playground -- Add visual regression testing - -## Key Challenges -- Design consistency -- Component reusability -- Documentation maintenance -- Version management -- Breaking changes handling + +By the end, you should be able to: + +- Model a design-token layer that themes propagate through, decoupled from components +- Author accessible, composable components with well-typed, minimal APIs +- Publish a versioned package and communicate breaking changes via semver + changelog +- Catch visual and accessibility regressions automatically before release +- Maintain documentation that is generated from, and stays in sync with, the source + +## Functional Requirements + +1. Design tokens (color, spacing, typography, radius) must be defined once and consumed by all components. +2. At least two themes (e.g. light/dark) must switch purely by swapping token values, with no component code changes. +3. Every interactive component must be keyboard-operable and expose correct roles/ARIA. +4. The library must build into a tree-shakeable, versioned package that a separate app can install and import. +5. Documentation must render live, interactive examples of each component and its props. +6. A visual regression test must fail the build when a component's rendered output changes unexpectedly. +7. Breaking changes must bump the major version and be recorded in a human-readable changelog. + +## Suggested Milestones + +1. **Milestone 1 — Tokens & primitives:** Define the token layer and a few base components consuming it. +2. **Milestone 2 — Theming & a11y:** Add theme switching and make components keyboard- and screen-reader-friendly. +3. **Milestone 3 — Docs & playground:** Stand up Storybook (or equivalent) with interactive prop controls. +4. **Milestone 4 — Release pipeline:** Add visual regression + a11y checks and a versioned publish flow. + +## Data & Interface Sketch + +```text + ┌─────────────────────────────────────────────┐ + │ Design tokens │ + │ color.* · space.* · font.* · radius.* │ + └───────────────┬─────────────────────────────┘ + │ CSS variables / theme object + ┌───────────────▼─────────────────────────────┐ + │ Primitives: Box, Text, Icon, Stack │ + └───────────────┬─────────────────────────────┘ + ┌───────────────▼─────────────────────────────┐ + │ Components: Button, Input, Modal, Table │ + └───────────────┬─────────────────────────────┘ + ┌───────┴────────┐ ┌────────────────────┐ + │ Docs (stories) │ │ npm package (semver)│ + └────────────────┘ └────────────────────┘ + +Token flow: token -> theme -> component (never hard-coded hex) +Versioning: patch=fix · minor=additive · major=breaking API/visual +Gates: visual regression snapshot + axe a11y scan per PR +``` + +## Stretch Goals + +- Add a token pipeline (e.g. Style Dictionary) that emits CSS, JS, and native formats from one source. +- Generate an accessibility report per component and publish it alongside the docs. +- Support a runtime theming API so consumers can brand the system without a rebuild. +- Add a "deprecations" mechanism that warns in dev when a soon-to-be-removed prop is used. + +## Definition of Done + +- [ ] Switching theme changes the whole UI by swapping tokens, with zero component edits. +- [ ] A consuming app installs the package and imports only the components it uses (verified by bundle size). +- [ ] Every interactive component passes keyboard-only operation and an automated a11y scan. +- [ ] An intentional visual change fails the regression suite until the snapshot is reviewed and updated. +- [ ] The changelog and version reflect the nature of each change (patch/minor/major). + +## Common Pitfalls + +- Hard-coding colors and spacing in components instead of referencing tokens, breaking theming. +- Over-engineering component APIs with dozens of props instead of favoring composition. +- Letting docs drift from code by writing them by hand rather than generating from source. +- Publishing breaking changes as minor versions, silently breaking downstream apps. +- Treating accessibility as a later pass rather than a per-component acceptance criterion. + +## Resources + +- [Storybook documentation](https://storybook.js.org/docs) — the standard for building and documenting components in isolation. +- [Design Tokens Community Group format](https://tr.designtokens.org/format/) — the emerging standard for portable design tokens. +- [WAI-ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) — authoritative patterns for accessible components. +- [Semantic Versioning](https://semver.org/) — the contract for communicating change through version numbers. diff --git a/projects/frontend/advanced/03-design-system/README.pt-BR.md b/projects/frontend/advanced/03-design-system/README.pt-BR.md new file mode 100644 index 0000000..8c0880d --- /dev/null +++ b/projects/frontend/advanced/03-design-system/README.pt-BR.md @@ -0,0 +1,96 @@ +# Design System Completo (biblioteca de componentes) + +> 🌐 [English](./README.md) · **Português** + +**Domínio:** Frontend · **Nível:** Avançado · **Tempo estimado:** 1–2 semanas + +## Visão Geral + +Construa a fundação visual compartilhada que muitos times de produto consomem — a camada por trás do Material, do Carbon e do Polaris. Um design system de verdade é mais do que uma pasta de componentes: é uma camada de tokens (cores, espaçamento, tipografia) que alimenta componentes acessíveis e tematizáveis, publicada como um pacote versionado com documentação viva. O desafio de engenharia é a governança em escala. Como evoluir um botão usado por quarenta telas sem quebrar nenhuma delas? Como pegar uma regressão visual de um pixel antes que um consumidor pegue? Este projeto trata o sistema como um produto com seus próprios usuários, seu próprio processo de release e seu próprio contrato — versionamento semântico, testes de regressão visual e docs que nunca se descolam do código. + +## Pré-requisitos + +- Experiência sólida em criar componentes em um framework (uma [Biblioteca de Componentes Reutilizáveis](../../intermediate/06-markdown-editor/) é um bom aquecimento) +- Entendimento de propriedades customizadas de CSS e da cascata +- Familiaridade com um registro de pacotes e versionamento semântico +- Conforto em configurar um build que emite uma biblioteca distribuível + +## Objetivos de Aprendizado + +Ao final, você deve ser capaz de: + +- Modelar uma camada de design tokens pela qual os temas se propagam, desacoplada dos componentes +- Criar componentes acessíveis e componíveis com APIs mínimas e bem tipadas +- Publicar um pacote versionado e comunicar mudanças que quebram via semver + changelog +- Pegar regressões visuais e de acessibilidade automaticamente antes do release +- Manter documentação gerada a partir do código-fonte e sincronizada com ele + +## Requisitos Funcionais + +1. Os design tokens (cor, espaçamento, tipografia, raio) devem ser definidos uma vez e consumidos por todos os componentes. +2. Pelo menos dois temas (ex.: claro/escuro) devem alternar puramente trocando valores de tokens, sem mudanças de código nos componentes. +3. Todo componente interativo deve ser operável por teclado e expor roles/ARIA corretos. +4. A biblioteca deve compilar em um pacote versionado e tree-shakeable que um app separado possa instalar e importar. +5. A documentação deve renderizar exemplos vivos e interativos de cada componente e suas props. +6. Um teste de regressão visual deve falhar o build quando a saída renderizada de um componente muda inesperadamente. +7. Mudanças que quebram devem incrementar a versão maior e ser registradas em um changelog legível. + +## Marcos Sugeridos + +1. **Marco 1 — Tokens e primitivos:** Defina a camada de tokens e alguns componentes base que a consomem. +2. **Marco 2 — Temas e a11y:** Adicione troca de temas e torne os componentes amigáveis a teclado e leitor de tela. +3. **Marco 3 — Docs e playground:** Suba o Storybook (ou equivalente) com controles interativos de props. +4. **Marco 4 — Pipeline de release:** Adicione checagens de regressão visual + a11y e um fluxo de publish versionado. + +## Esboço de Dados e Interface + +```text + ┌─────────────────────────────────────────────┐ + │ Design tokens │ + │ color.* · space.* · font.* · radius.* │ + └───────────────┬─────────────────────────────┘ + │ variáveis CSS / objeto de tema + ┌───────────────▼─────────────────────────────┐ + │ Primitivos: Box, Text, Icon, Stack │ + └───────────────┬─────────────────────────────┘ + ┌───────────────▼─────────────────────────────┐ + │ Componentes: Button, Input, Modal, Table │ + └───────────────┬─────────────────────────────┘ + ┌───────┴────────┐ ┌────────────────────┐ + │ Docs (stories) │ │ pacote npm (semver)│ + └────────────────┘ └────────────────────┘ + +Fluxo de token: token -> tema -> componente (nunca hex fixo) +Versionamento: patch=fix · minor=aditivo · major=API/visual que quebra +Portões: snapshot de regressão visual + scan a11y axe por PR +``` + +## Desafios Extras + +- Adicione um pipeline de tokens (ex.: Style Dictionary) que emite CSS, JS e formatos nativos de uma única fonte. +- Gere um relatório de acessibilidade por componente e publique-o junto à documentação. +- Suporte uma API de tematização em tempo de execução para que consumidores personalizem a marca sem um rebuild. +- Adicione um mecanismo de "deprecações" que avisa em dev quando uma prop prestes a ser removida é usada. + +## Definição de Pronto + +- [ ] Trocar o tema muda toda a UI trocando tokens, com zero edições em componentes. +- [ ] Um app consumidor instala o pacote e importa apenas os componentes que usa (verificado pelo tamanho do bundle). +- [ ] Todo componente interativo passa na operação apenas por teclado e em um scan automatizado de a11y. +- [ ] Uma mudança visual intencional falha a suíte de regressão até o snapshot ser revisado e atualizado. +- [ ] O changelog e a versão refletem a natureza de cada mudança (patch/minor/major). + +## Armadilhas Comuns + +- Fixar cores e espaçamentos nos componentes em vez de referenciar tokens, quebrando a tematização. +- Superengenheirar as APIs de componentes com dezenas de props em vez de favorecer composição. +- Deixar os docs se descolarem do código ao escrevê-los à mão em vez de gerá-los a partir da fonte. +- Publicar mudanças que quebram como versões menores, quebrando silenciosamente apps downstream. +- Tratar acessibilidade como uma etapa posterior em vez de um critério de aceite por componente. + +## Recursos + +- [Documentação do Storybook](https://storybook.js.org/docs) — o padrão para construir e documentar componentes em isolamento. +- [Formato do Design Tokens Community Group](https://tr.designtokens.org/format/) — o padrão emergente para design tokens portáveis. +- [WAI-ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) — padrões autoritativos para componentes acessíveis. +- [Versionamento Semântico](https://semver.org/lang/pt-BR/) — o contrato para comunicar mudança através de números de versão. diff --git a/projects/frontend/advanced/04-offline-first-pwa/README.md b/projects/frontend/advanced/04-offline-first-pwa/README.md index c570322..59a8f34 100644 --- a/projects/frontend/advanced/04-offline-first-pwa/README.md +++ b/projects/frontend/advanced/04-offline-first-pwa/README.md @@ -1,34 +1,98 @@ # Offline-First PWA -## Idea -Build a Progressive Web App that works offline with service workers and local caching. Learn about service workers, cache strategies, and offline UX. +> 🌐 **English** · [Português](./README.pt-BR.md) + +**Domain:** Frontend · **Level:** Advanced · **Estimated time:** 1–2 weeks + +## Overview + +Build a Progressive Web App that treats the network as an enhancement, not a requirement — the app keeps working on a train, in a tunnel, or on a flaky connection, then quietly syncs when the network returns. This inverts the usual assumption that data lives on a server and the client is a thin view. Here the client owns a durable local store, renders from it instantly, and reconciles with the backend in the background. The hard parts are the ones users notice only when they break: a stale cache serving last week's data, a background sync that silently loses a write, or two edits that collide after a reconnect. You will design cache strategies deliberately and make the offline state a first-class, visible part of the UX. + +## Prerequisites + +- A working single-page app you can retrofit (an [Intermediate](../../intermediate/) project works well) +- Understanding of the request/response lifecycle and HTTP caching headers +- Familiarity with Promises and asynchronous data flow +- Awareness of IndexedDB or a wrapper as a client-side database ## Learning Objectives -- Implement service workers -- Create cache strategies -- Handle offline state -- Implement sync strategies -- Create offline UI - -## Implementation Tips -- Register service workers -- Implement caching strategies (cache-first, network-first) -- Create offline page -- Implement background sync -- Add periodic sync -- Handle offline state display -- Create data synchronization on reconnection -- Implement push notifications -- Create install prompts -- Add app shortcuts -- Implement update detection -- Create offline-first architecture -- Add data conflict resolution -- Implement performance optimization - -## Key Challenges -- Cache invalidation -- Sync reliability -- Offline data consistency -- User experience offline -- Background sync reliability + +By the end, you should be able to: + +- Register a service worker and intercept network requests with chosen cache strategies +- Choose per-resource strategies (cache-first, network-first, stale-while-revalidate) and justify each +- Persist application data locally in IndexedDB and render from it before the network responds +- Queue writes made offline and replay them reliably on reconnection via Background Sync +- Communicate connectivity and sync status clearly so the user is never confused about data freshness + +## Functional Requirements + +1. The app must load and be usable on a repeat visit with the network fully disabled. +2. Static assets (app shell) must be served from cache and updated safely when a new version deploys. +3. Application data must be readable offline from a local store, not just static HTML. +4. A write performed offline must be queued and automatically synced once connectivity returns. +5. The UI must clearly indicate offline status and pending, unsynced changes. +6. A new service worker version must not serve a broken mix of old and new assets. +7. Conflicting edits (local vs. server) must be resolved by an explicit, documented strategy — not silent loss. + +## Suggested Milestones + +1. **Milestone 1 — Installable shell:** Add a manifest and a service worker that caches the app shell for offline load. +2. **Milestone 2 — Offline data:** Store and read application data in IndexedDB; render from it first. +3. **Milestone 3 — Write queue & sync:** Queue offline mutations and replay them with Background Sync on reconnect. +4. **Milestone 4 — Conflicts & updates:** Handle edit conflicts and safe service-worker version rollovers. + +## Data & Interface Sketch + +```text + Browser tab Service worker Network + ┌────────────┐ fetch ┌─────────────────┐ fetch ┌────────┐ + │ UI reads │────────────▶ │ strategy router │─────────▶ │ API │ + │ from IDB │◀──────────── │ cache | network │◀───────── │ │ + └─────┬──────┘ response └────────┬────────┘ └────────┘ + │ writes │ cache + ┌─────▼───────────┐ ┌─────────▼────────┐ + │ IndexedDB │ │ Cache Storage │ + │ data + outbox │ │ app shell + assets│ + └─────┬───────────┘ └──────────────────┘ + │ Background Sync replays outbox on reconnect + └──────────────────────────────────────────▶ API + +Strategies: shell=cache-first · data=stale-while-revalidate · writes=queued +Conflicts: last-write-wins | version vector | manual merge — pick + document + +Non-functional targets: + repeat visit offline fully usable + app-shell cached size <= 200 KB + queued write on reconnect never lost, replayed once (idempotent) +``` + +## Stretch Goals + +- Add push notifications that surface even when the app is closed. +- Implement periodic background sync to refresh data before the user reopens the app. +- Add an install prompt with a custom, well-timed UX rather than the raw browser banner. +- Show a per-item sync badge (synced / pending / failed) with retry. + +## Definition of Done + +- [ ] With the network off, a repeat visitor can open the app, read data, and make an edit. +- [ ] That offline edit appears synced to the server automatically after reconnecting, exactly once. +- [ ] Deploying a new version updates the service worker without serving a mismatched asset set. +- [ ] The UI shows offline status and a count of unsynced changes. +- [ ] A deliberately created edit conflict resolves by the documented strategy, losing no user intent silently. + +## Common Pitfalls + +- Caching everything with cache-first, so users are stuck on stale data with no update path. +- Forgetting service-worker lifecycle (`waiting`/`skipWaiting`), leaving users on an old version indefinitely. +- Treating IndexedDB writes as synchronous, causing lost updates under rapid interaction. +- Replaying the offline outbox without idempotency, duplicating server-side records on flaky reconnects. +- Hiding offline state entirely, so users think their unsynced work is safely saved to the server. + +## Resources + +- [web.dev: Offline cookbook](https://web.dev/articles/offline-cookbook) — the definitive catalogue of service-worker caching strategies. +- [MDN: Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) — lifecycle, scope, and fetch interception. +- [MDN: IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) — the browser's durable client-side database. +- [web.dev: Background Sync](https://web.dev/articles/background-sync) — reliably deferring writes until connectivity returns. diff --git a/projects/frontend/advanced/04-offline-first-pwa/README.pt-BR.md b/projects/frontend/advanced/04-offline-first-pwa/README.pt-BR.md new file mode 100644 index 0000000..af9250e --- /dev/null +++ b/projects/frontend/advanced/04-offline-first-pwa/README.pt-BR.md @@ -0,0 +1,98 @@ +# PWA Offline-First + +> 🌐 [English](./README.md) · **Português** + +**Domínio:** Frontend · **Nível:** Avançado · **Tempo estimado:** 1–2 semanas + +## Visão Geral + +Construa um Progressive Web App que trata a rede como um aprimoramento, não um requisito — o app continua funcionando em um trem, num túnel ou numa conexão instável, e depois sincroniza discretamente quando a rede volta. Isso inverte a suposição usual de que os dados vivem em um servidor e o cliente é uma visão fina. Aqui o cliente é dono de um armazenamento local durável, renderiza a partir dele instantaneamente e reconcilia com o backend em segundo plano. As partes difíceis são as que os usuários só notam quando quebram: um cache obsoleto servindo dados da semana passada, um background sync que perde silenciosamente uma escrita, ou duas edições que colidem após uma reconexão. Você vai projetar estratégias de cache de forma deliberada e tornar o estado offline uma parte visível e de primeira classe da UX. + +## Pré-requisitos + +- Uma SPA funcional que você possa adaptar (um projeto [Intermediário](../../intermediate/) funciona bem) +- Entendimento do ciclo de vida requisição/resposta e dos cabeçalhos de cache HTTP +- Familiaridade com Promises e fluxo de dados assíncrono +- Consciência do IndexedDB ou de um wrapper como banco de dados no cliente + +## Objetivos de Aprendizado + +Ao final, você deve ser capaz de: + +- Registrar um service worker e interceptar requisições de rede com estratégias de cache escolhidas +- Escolher estratégias por recurso (cache-first, network-first, stale-while-revalidate) e justificar cada uma +- Persistir dados da aplicação localmente no IndexedDB e renderizar a partir deles antes de a rede responder +- Enfileirar escritas feitas offline e reproduzi-las de forma confiável na reconexão via Background Sync +- Comunicar o status de conectividade e de sincronização com clareza para que o usuário nunca fique confuso sobre a atualidade dos dados + +## Requisitos Funcionais + +1. O app deve carregar e ser utilizável em uma visita repetida com a rede totalmente desativada. +2. Os assets estáticos (app shell) devem ser servidos do cache e atualizados com segurança quando uma nova versão for implantada. +3. Os dados da aplicação devem ser legíveis offline a partir de um armazenamento local, não apenas HTML estático. +4. Uma escrita feita offline deve ser enfileirada e sincronizada automaticamente assim que a conectividade retornar. +5. A UI deve indicar claramente o status offline e as mudanças pendentes, não sincronizadas. +6. Uma nova versão do service worker não deve servir uma mistura quebrada de assets antigos e novos. +7. Edições conflitantes (local vs. servidor) devem ser resolvidas por uma estratégia explícita e documentada — não por perda silenciosa. + +## Marcos Sugeridos + +1. **Marco 1 — Shell instalável:** Adicione um manifest e um service worker que cacheia o app shell para carga offline. +2. **Marco 2 — Dados offline:** Armazene e leia dados da aplicação no IndexedDB; renderize a partir deles primeiro. +3. **Marco 3 — Fila de escrita e sync:** Enfileire mutações offline e reproduza-as com Background Sync na reconexão. +4. **Marco 4 — Conflitos e atualizações:** Trate conflitos de edição e trocas seguras de versão do service worker. + +## Esboço de Dados e Interface + +```text + Aba do navegador Service worker Rede + ┌────────────┐ fetch ┌─────────────────┐ fetch ┌────────┐ + │ UI lê do │────────────▶ │ roteador de │─────────▶ │ API │ + │ IndexedDB │◀──────────── │ estratégia │◀───────── │ │ + └─────┬──────┘ resposta └────────┬────────┘ └────────┘ + │ escritas │ cache + ┌─────▼───────────┐ ┌─────────▼────────┐ + │ IndexedDB │ │ Cache Storage │ + │ dados + outbox │ │ app shell + assets│ + └─────┬───────────┘ └──────────────────┘ + │ Background Sync reproduz a outbox na reconexão + └──────────────────────────────────────────▶ API + +Estratégias: shell=cache-first · dados=stale-while-revalidate · escritas=enfileiradas +Conflitos: last-write-wins | vetor de versão | merge manual — escolha + documente + +Metas não funcionais: + visita repetida offline totalmente utilizável + tamanho do shell cacheado <= 200 KB + escrita enfileirada na reconexão nunca perdida, reproduzida uma vez (idempotente) +``` + +## Desafios Extras + +- Adicione notificações push que aparecem mesmo com o app fechado. +- Implemente sincronização periódica em segundo plano para atualizar dados antes de o usuário reabrir o app. +- Adicione um prompt de instalação com uma UX customizada e bem cronometrada, em vez do banner cru do navegador. +- Mostre um selo de sync por item (sincronizado / pendente / falhou) com nova tentativa. + +## Definição de Pronto + +- [ ] Com a rede desligada, um visitante recorrente consegue abrir o app, ler dados e fazer uma edição. +- [ ] Essa edição offline aparece sincronizada ao servidor automaticamente após reconectar, exatamente uma vez. +- [ ] Implantar uma nova versão atualiza o service worker sem servir um conjunto de assets incompatível. +- [ ] A UI mostra o status offline e uma contagem de mudanças não sincronizadas. +- [ ] Um conflito de edição criado deliberadamente resolve pela estratégia documentada, sem perder intenção do usuário silenciosamente. + +## Armadilhas Comuns + +- Cachear tudo com cache-first, deixando usuários presos em dados obsoletos sem caminho de atualização. +- Esquecer o ciclo de vida do service worker (`waiting`/`skipWaiting`), deixando usuários em uma versão antiga indefinidamente. +- Tratar escritas no IndexedDB como síncronas, causando updates perdidos sob interação rápida. +- Reproduzir a outbox offline sem idempotência, duplicando registros no servidor em reconexões instáveis. +- Esconder o estado offline por completo, fazendo usuários pensarem que seu trabalho não sincronizado está salvo no servidor. + +## Recursos + +- [web.dev: Offline cookbook](https://web.dev/articles/offline-cookbook) — o catálogo definitivo de estratégias de cache de service worker. +- [MDN: Service Worker API](https://developer.mozilla.org/pt-BR/docs/Web/API/Service_Worker_API) — ciclo de vida, escopo e interceptação de fetch. +- [MDN: IndexedDB API](https://developer.mozilla.org/pt-BR/docs/Web/API/IndexedDB_API) — o banco de dados durável do navegador no cliente. +- [web.dev: Background Sync](https://web.dev/articles/background-sync) — adiar escritas de forma confiável até a conectividade retornar. diff --git a/projects/frontend/advanced/05-streaming-ui/README.md b/projects/frontend/advanced/05-streaming-ui/README.md index 42e16b9..7b326b6 100644 --- a/projects/frontend/advanced/05-streaming-ui/README.md +++ b/projects/frontend/advanced/05-streaming-ui/README.md @@ -1,34 +1,101 @@ # Streaming UI (video platform) -## Idea -Create a video streaming platform UI with adaptive bitrate selection and playback controls. Learn about video optimization and performance. +> 🌐 **English** · [Português](./README.pt-BR.md) + +**Domain:** Frontend · **Level:** Advanced · **Estimated time:** 1–2 weeks + +## Overview + +Build the playback experience of a video platform like YouTube or Netflix — adaptive streaming that shifts quality with the network, smooth controls, and an interface that stays responsive while a large media pipeline runs underneath. The core insight is that you do not download a video; you download a manifest describing many quality renditions split into small segments, and the player continuously chooses which segment to fetch next based on measured bandwidth and buffer health. Get that adaptation wrong and the user sees stalls or blurry frames; get the UI wrong and controls feel laggy against the heavy decode work. This project is about orchestrating an adaptive-bitrate engine and a polished, accessible player around it. + +## Prerequisites + +- Confident with asynchronous data flow and browser events +- Understanding of HTTP range requests and buffering concepts +- Familiarity with the HTML5 `