chore(tutorial): align the example app with the rewritten React chat tutorial - #3251
Conversation
…rial The published tutorial was restructured (GetStream/getstream.io#345) into numbered steps 0-7 plus two optional recipes. This aligns the example app so a folder here maps 1:1 to a heading there. - Renumber the step folders to match the tutorial (2-client-setup through 7-emoji-picker), and rename the two non-linear steps to optional-*. - Add the missing 5-theming step. The tutorial teaches theming before the component overrides, but the app had no counterpart for it. - Scope every themed step's overrides under a `step-<id>` class, applied by the browser in src/App.tsx. The step browser renders all steps in one document, so all eight stylesheets are live at once; steps 3 and 4 import the SDK stylesheet unlayered (as the tutorial has them), and unlayered CSS outranks every @layer regardless of specificity. Without the scope, a layered override does nothing and an unscoped one restyles the earlier steps. README documents this as the one deliberate deviation from the tutorial. - Fix the preview panel clipping the chat UI. The chrome panes are sized in viewport units and padded, so under the default content-box the padding was added on top of 100vh and pushed the composer below the fold. Sets border-box on the six named chrome classes only, so the SDK's own box-sizing is untouched. - Drop the 16 per-step main.tsx and index.html files. They predate the step browser, were never part of any build (vite build only ever emitted dist/index.html), and had become a maintenance coupling for the scope class. Each step folder now holds exactly the files the tutorial tells you to create.
`stream-chat-react` is consumed as a workspace dependency, so Vite serves its built output from outside the app's root and resolves that copy's `react` import separately from the app's. The SDK and the app end up on two React instances and the first hook call throws "Invalid hook call", which made the tutorial app fail to boot on a clean install regardless of how it was started. `resolve.dedupe` forces both onto a single copy.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe tutorial browser and step examples were reorganized around shared client setup, updated step metadata, scoped styling, new chat examples, credential fallback support, documentation, and Vite React deduplication. Obsolete per-step HTML/bootstrap files were removed. ChangesTutorial browser and examples
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Size Change: 0 B Total Size: 881 kB ℹ️ View Unchanged
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3251 +/- ##
==========================================
+ Coverage 85.22% 85.24% +0.01%
==========================================
Files 506 506
Lines 15795 15795
Branches 5023 5023
==========================================
+ Hits 13462 13465 +3
+ Misses 2333 2330 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/tutorial/src/7-emoji-picker/layout.css`:
- Around line 11-36: Match each scoped token override to the theme actually
rendered by its Chat component: in
examples/tutorial/src/7-emoji-picker/layout.css lines 11-36, either make the
step’s Chat use theme="custom-theme" or scope the overrides to its rendered
theme class; in examples/tutorial/src/optional-livestream/layout.css lines
11-36, target .str-chat__theme-dark or change the component to use custom-theme.
Ensure both override blocks apply to their corresponding rendered themes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 744a4c03-67e4-4cda-8d9c-05f10ed38e0c
📒 Files selected for processing (42)
examples/tutorial/.env.exampleexamples/tutorial/README.mdexamples/tutorial/src/1-client-setup/index.htmlexamples/tutorial/src/1-client-setup/main.tsxexamples/tutorial/src/2-client-setup/App.tsxexamples/tutorial/src/2-client-setup/credentials.tsexamples/tutorial/src/2-core-component-setup/index.htmlexamples/tutorial/src/2-core-component-setup/main.tsxexamples/tutorial/src/3-channel-list/index.htmlexamples/tutorial/src/3-channel-list/layout.cssexamples/tutorial/src/3-channel-list/main.tsxexamples/tutorial/src/3-core-component-setup/App.tsxexamples/tutorial/src/3-core-component-setup/layout.cssexamples/tutorial/src/3-core-component-setup/stream-chat.d.tsexamples/tutorial/src/4-channel-list/App.tsxexamples/tutorial/src/4-channel-list/layout.cssexamples/tutorial/src/4-custom-ui-components/index.htmlexamples/tutorial/src/4-custom-ui-components/layout.cssexamples/tutorial/src/4-custom-ui-components/main.tsxexamples/tutorial/src/5-custom-attachment-type/index.htmlexamples/tutorial/src/5-custom-attachment-type/layout.cssexamples/tutorial/src/5-custom-attachment-type/main.tsxexamples/tutorial/src/5-theming/App.tsxexamples/tutorial/src/5-theming/layout.cssexamples/tutorial/src/6-custom-ui-components/App.tsxexamples/tutorial/src/6-custom-ui-components/layout.cssexamples/tutorial/src/6-emoji-picker/index.htmlexamples/tutorial/src/6-emoji-picker/layout.cssexamples/tutorial/src/6-emoji-picker/main.tsxexamples/tutorial/src/7-emoji-picker/App.tsxexamples/tutorial/src/7-emoji-picker/layout.cssexamples/tutorial/src/7-livestream/index.htmlexamples/tutorial/src/7-livestream/layout.cssexamples/tutorial/src/7-livestream/main.tsxexamples/tutorial/src/App.tsxexamples/tutorial/src/optional-custom-attachment-type/App.tsxexamples/tutorial/src/optional-custom-attachment-type/layout.cssexamples/tutorial/src/optional-custom-attachment-type/stream-chat.d.tsexamples/tutorial/src/optional-livestream/App.tsxexamples/tutorial/src/optional-livestream/layout.cssexamples/tutorial/src/tutorial-main.cssexamples/tutorial/vite.config.ts
💤 Files with no reviewable changes (19)
- examples/tutorial/src/7-livestream/index.html
- examples/tutorial/src/7-livestream/main.tsx
- examples/tutorial/src/5-custom-attachment-type/index.html
- examples/tutorial/src/1-client-setup/index.html
- examples/tutorial/src/5-custom-attachment-type/layout.css
- examples/tutorial/src/3-channel-list/index.html
- examples/tutorial/src/3-channel-list/main.tsx
- examples/tutorial/src/1-client-setup/main.tsx
- examples/tutorial/src/2-core-component-setup/index.html
- examples/tutorial/src/4-custom-ui-components/main.tsx
- examples/tutorial/src/6-emoji-picker/index.html
- examples/tutorial/src/3-channel-list/layout.css
- examples/tutorial/src/4-custom-ui-components/index.html
- examples/tutorial/src/6-emoji-picker/layout.css
- examples/tutorial/src/2-core-component-setup/main.tsx
- examples/tutorial/src/4-custom-ui-components/layout.css
- examples/tutorial/src/5-custom-attachment-type/main.tsx
- examples/tutorial/src/6-emoji-picker/main.tsx
- examples/tutorial/src/7-livestream/layout.css
Follow-up cleanup on the step CSS. No rendering change.
- Drop the per-step `.step-<id> .custom-theme` prefix for `.str-chat.custom-theme`.
Channel.tsx and ChannelList.tsx both do `clsx('str-chat', theme, ...)`, so the
theme class lands on the same element as `str-chat`; at 0,2,0 this beats the
SDK's own `.str-chat` (0,1,0) regardless of source order, and it only matches
the steps that actually pass `theme="custom-theme"`, so it still cannot leak
into the unthemed steps. The layout.css copies are now byte-identical within
each group - two distinct versions, matching the tutorial's two - so drift
shows up in a diff. The CSS no longer depends on the browser's wrapper class.
- Declare the html/body/#root rules in tutorial-main.css. They were coming only
from the step stylesheets, so the chrome silently relied on a step's CSS for
`body { margin: 0 }` and would pick up the UA margin if steps were ever loaded
lazily or in isolation (2-client-setup has no layout.css at all).
- Normalize steps 3 and 4 to the tutorial's 2-space indentation.
- README documents which parts of each copy are inert inside the step browser
(the custom-theme tokens in the two steps that don't opt in, and the
.str-chat__* widths, which lose to tutorial-main.css) and why they stay anyway:
the file has to remain a faithful copy of what the tutorial has readers write.
🎯 Goal
examples/tutorialhad drifted out of sync with the published React chat tutorial, which was restructured in GetStream/getstream.io#345 into numbered steps 0-7 plus two optional recipes. Folder numbering no longer lined up with the tutorial's step numbers, and there was no runnable counterpart for the theming step at all.Two things also made the example unusable as it stood:
Invalid hook callon first render. Reproduces onmaster.The point of this example is that a reader can run the exact code the tutorial gave them, so a folder here needs to map 1:1 to a heading there.
🛠 Implementation details
Three commits, each independently revertable.
1. Step alignment (
244f77697)Folders renumbered to match the tutorial, and the two non-linear steps renamed to
optional-*:2-client-setup3-core-component-setup4-channel-list5-theming6-custom-ui-components7-emoji-pickeroptional-custom-attachment-typeoptional-livestreamThe tutorial's Step 0 (environment) and Step 1 (project + credentials) have no runnable counterpart, so numbering starts at 2.
Also in this commit:
content-boxthe padding was added on top of100vh— 1312px of content in a 1272px viewport. Fixed withborder-boxon the six named chrome classes only, deliberately not.tutorial-browser *, so the SDK's own box-sizing is untouched.main.tsx/index.htmlfiles. They date to chore: add tutorial to examples #2697, when the step browser did not exist and booting a step's own HTML was the only way to run it. Since the browser landed they have been dead weight:vite buildonly ever emitteddist/index.html, nothing referenced them, and all eightmain.tsxwere byte-identical. Each step folder now holds exactly the files the tutorial tells you to create.2. React dedupe (
4b865aabc)stream-chat-reactis consumed as a workspace dependency, so Vite serves its built output from outside the app's root and resolves that copy'sreactimport separately from the app's. The SDK and the app end up on two React instances and the first hook call throws.resolve.dedupe: ['react', 'react-dom']forces both onto a single copy.Split out on its own because it is the one change that is not tutorial content — it can be cherry-picked or reverted independently.
3. Step stylesheet cleanup (
6a67e4447) — no rendering changeThe step browser renders every step in one document, so all seven stylesheets are live at once. Steps 3 and 4 import the SDK stylesheet unlayered (as the tutorial has them, since Step 5 is where you are taught to move it into a layer), and unlayered CSS outranks every
@layerregardless of specificity — so the tutorial's@layer stream-overrides { .custom-theme { ... } }silently does nothing here.The themed steps declare the tokens unlayered on
.str-chat.custom-themeinstead.Channel.tsx:163andChannelList.tsx:342both doclsx('str-chat', theme, ...), so the theme class lands on the same element asstr-chat; at 0,2,0 this beats the SDK's own.str-chat(0,1,0) regardless of source order, and it only matches steps that actually passtheme="custom-theme", so it cannot leak into the unthemed ones. README flags this as the one deliberate deviation, with a pointer to keep the tokens in the layer in your own app.That leaves
layout.csswith exactly two distinct versions, mirroring the tutorial's two, byte-identical within each group so drift shows up in a diff.Also:
html/body/#rootwere previously declared only in the step stylesheets, so the chrome silently depended on a step's CSS forbody { margin: 0 }and would pick up the UA margin if steps were ever loaded lazily or in isolation (2-client-setuphas nolayout.cssat all).tutorial-main.cssnow declares them itself.Parts of each
layout.csscopy are inert inside the step browser and stay that way on purpose, since the file has to remain a faithful copy of what the tutorial has readers write. README documents each case:custom-themetokens do nothing in7-emoji-pickerandoptional-livestream, which do not passtheme="custom-theme"— matching the tutorial, where the reader's singlelayout.cssholds the tokens and leaves them unused for those same two examples.str-chat__*widths lose to.tutorial-browser__step-shell .str-chat__*intutorial-main.css(0,2,0 against 0,1,0); the tutorial's widths assume the app owns the whole page, here it is sized to fit a preview cardNo bundle cost either way — Vite collapses the identical copies, so the built CSS contains one
width: 30%and one@layer stream.🎨 UI Changes
No change to the SDK itself, and no change to any tutorial code block. The visual deltas are all in the example app:
5-themingstep, so the tutorial's theming milestone is now runnable.overflowX/Y: 0with the preview card fully within the viewport.2-client-setuprenders bare text with no chat chrome, so it landed inside the card's 28px corner arc and the first glyph was clipped. Padded via thestep-client-setupclass.Verified across all eight steps by reading computed styles after switching:
.str-chat--str-chat__accent-primarymessaging light#005fffoptional-custom-attachment-typecustom-theme#0d47a1messaging light#005fffoptional-livestreamstr-chat__theme-dark#4586ffStep 7 intentionally shows the default accent — the tutorial's emoji block renders
<Chat>without thethemeprop, and notes so explicitly.tsc -b,vite build, and gated prettier all pass. No console errors on any step.To see it:
yarn start:tutorialfrom the repo root.Opened without a reviewer since I am not sure who owns this area — happy to add whoever should look at it.
Companion PR: GetStream/getstream.io#345
Summary by CodeRabbit
VITE_STREAM_API_KEY(with legacy fallback).