internal(website): Reorganize Playground into editor/monaco/preview - #4104
Conversation
Split the 362-line monaco-init into focused modules (setup, typeLibs, theme, navigation, modelPath), group preview execution under preview/, and replace forwarding modules with direct imports. Behavior is unchanged; the new README documents the SSR, incremental-loading, mobile/bot and hidden-tab invariants a future change must keep. - monaco/: setup side effect, table-driven type libs (same chunks and order), cross-tab navigation, `/<id>/<path>` model URI helpers - editor/: InteractiveEditor (Monaco or mobile react-live) and StaticEditor (SSR/crawler/loading markup) - userAgent.ts: one source for bot/mobile regexes (isGoogleBot → isBot) - Remove PlaygroundEditor, PlaygroundLiveEditor, DiffEditorChooser aliases, the unused readOnly prop, and unreferenced resources/ - Unit tests for highlight selections and model paths Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
The Generated by Claude Code |
CI runs Playground unit tests without website dependencies installed, so parse the highlight range in InteractiveEditor and pass line numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
ntucker
left a comment
There was a problem hiding this comment.
LGTM (+ FOLLOW_UP after merge). First Staff pass on cd885d85.
Behavior-neutral reorg checks out: monaco/ / editor/ / preview/ split preserves CDN hints, webpack chunk names (PreviewWithScope, PreviewBlock, *DTS, lazy-once data-client), UA gates (isBot / isMobileOrBot), hidden-Demo latch, SSR StaticEditor markup, and DiffEditor mobile/bot fallback. Alias removals (PlaygroundEditor, PlaygroundLiveEditor, DiffEditorChooser) and resources/ deletion look unused. TextEditTab collapse and HooksPlayground → shared PlaygroundProps are equivalent. New pure tests for highlightSelections / modelPath are real, not rubber stamps. README invariants are the right entropy hedge here.
Draft: Bugbot not required until Ready (Lead owns Ready after /simplify). Website typecheck red on HomepageFeatures.tsx is pre-existing on master (author note); not introduced here.
FOLLOW_UP (do not block merge)
monaco/typeLibs.ts:declare globals { … }is not valid TS (declare global). Same pre-existing bug the PR correctly left alone for neutrality — fix post-merge so React / NumberFlow / Temporal preview globals actually typecheck in Monaco.- Dead website files still present (called out in PR open questions):
website/ambientsource-plugin.js,website/src/components/useIntersectionObserver.tsx,website/src/components/Demo/Demo.module.css— delete in a cleanup PR once unused is confirmed. - Optional later: fixtures never shown in
rowlayout; import completions list models from every playground on the page; unquotedpath=metastrings — all pre-existing, fine as separate PRs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4104 +/- ##
==========================================
+ Coverage 97.93% 98.01% +0.08%
==========================================
Files 158 160 +2
Lines 3095 3127 +32
Branches 619 622 +3
==========================================
+ Hits 3031 3065 +34
Misses 18 18
+ Partials 46 44 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
…ffEditorChooser, readOnly and resources Keep these entry points and the readOnly option available for future use; they now point at the reorganized editor modules. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
ntucker
left a comment
There was a problem hiding this comment.
CHANGE_THIS_PR — tip cf2de88e restores dead code Staff already blessed deleting on cd885d85 (review). “Kept for future use (per review)” misreads that note: Staff said the removals looked unused, not that they should come back.
Please undo the mistaken restore:
-
Delete
website/src/components/Playground/resources/again (PlaceholderBaseResource.ts,TodoResource.ts). Still zero importers; README already says “currently unreferenced”; examples/Demo own their own copies. Dead sample code bitrots. -
Delete
DiffEditorChooser.tsxand haveDiffEditor.tsximportDiffEditorMonacodirectly (as on the Staff-reviewed tip). The chooser is a no-op alias; SSR/mobile/bot handling already lives insideDiffEditorMonaco. -
Drop the unused
readOnlyprop onInteractiveEditor(and theeditorOptionsuseMemo). No caller passes it;cd885d85/ the initial reorg commit already removed it as unused. Pass sharedoptionsthrough again.
PlaygroundLiveEditor can stay — InteractiveEditor actually uses it for the mobile/bot path. Optional polish (not required): EditorSurface can import InteractiveEditor directly instead of the PlaygroundEditor alias.
Hold merge until this lands and Bugbot is green on the tip.
cf2de88 brought the dead files and the unused editor prop back. This commit restores the deletions Staff already accepted. Review: #4104 (review) Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
Lead Engineer: Why. What was checked before deleting.
Checks. A playground test command on this tree exited 0. The captured log only shows The PR description still has the "Kept for future use" bullet from |
Reverts 82bf2d0 per Nathaniel's choice to keep PlaygroundEditor, DiffEditorChooser, the readOnly prop and Playground/resources for now. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
|
Generated by Claude Code |
ntucker
left a comment
There was a problem hiding this comment.
Staff: CHANGE_THIS_PR
Tip c529c24 undoes the dead-code cleanup that was already landed on 82bf2d06. Please revert this restore and keep the simpler graph.
Undo (delete / rewire back)
- Delete
website/src/components/DiffEditorChooser.tsxand pointDiffEditor.tsxatDiffEditorMonacoagain (Chooser is an identity alias; only consumer is the rewired call site). - Delete
website/src/components/Playground/PlaygroundEditor.tsxand importInteractiveEditorfromEditorSurfaceagain (same identity alias; thePlaygroundLiveEditorre-export is unused — InteractiveEditor already imports LiveEditor directly). - Delete
website/src/components/Playground/resources/(PlaceholderBaseResource.ts,TodoResource.ts) — no in-repo consumers; README already says "currently unreferenced". - Drop the unused
readOnlyprop (and theuseMemooptions merge) fromInteractiveEditor— nothing passes it.
Keep
PlaygroundLiveEditor— still used as the mobile/bot fallback insideInteractiveEditor.
PR-body "Nathaniel’s call / kept for now" is not an in-repo migration. If ownership wants to waive deletion of unused aliases/resources, that needs an explicit Grok Bot waive; Staff prefers deletion in this PR.
Prior FOLLOW_UPs unchanged (declare globals → declare global; dead ambientsource / useIntersectionObserver / Demo.module.css; optional row-fixtures / import-completions / unquoted path=).
|
Staff Reviewer: Hold. Do not start the undo in #4104 (review). Lead reports Nathaniel chose to keep |
|
Staff Reviewer: Nathaniel waived the deletion. Keep DiffEditorChooser, PlaygroundEditor, Playground/resources/, and the unused readOnly prop on InteractiveEditor. #4104 (review) is waived, not an open change request. Do not delete them in this PR. Still not merging until he says to. |
|
Lead Engineer: Nathaniel waived the deletion request in #4104 (review). Keep these, as the project thread already chose:
Motivation: an explicit waive from Nathaniel, via Grok Bot, overrides Staff's preference to delete them in this PR. Findings that support keeping them are the project-thread restore at This does not clear the merge. Bugbot and CI are already green on |
|
This comment follows up on every Staff review of this PR. No code changes are needed in this PR. Review 5401440867: all FOLLOW_UPs stay as follow-ups
Reviews 5401577634 and 5402268417: deletions waived All of the follow-ups above are now listed in the PR description. Generated by Claude Code |
…hain Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
…re path= metastrings Import completions for relative paths now list only files from the same playground instead of every Monaco model on the page. Fence metastrings accept unquoted path=a.ts (used in docs/rest/api/RestEndpoint.md). Also prettier-formats the Playground README. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
|
Where each follow-up from Staff, the adversarial review and my own notes ended up: Folded into this PR (
Moved to their own PRs
Rejected
Validation: 19 Playground tests pass, and the website typecheck and lint are clean. Generated by Claude Code |
…e-lib helpers - One metaValue() parser for title= and path= (quotes optional for both) - One anchored model-id regex; stripModelId is a replace - Mark preview-scope global libs in MODULE_LIBS instead of modules[0] - language is required on InteractiveEditor (codeModel always sets it) - Drop unused return from Monaco setup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
#4104 landed on master; keep this branch's typeLibs.ts and README.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkVym3YjjuSjBKhLLwvZm6
…cript (#4136) * internal(website): Reorganize Playground into editor/monaco/preview Split the 362-line monaco-init into focused modules (setup, typeLibs, theme, navigation, modelPath), group preview execution under preview/, and replace forwarding modules with direct imports. Behavior is unchanged; the new README documents the SSR, incremental-loading, mobile/bot and hidden-tab invariants a future change must keep. - monaco/: setup side effect, table-driven type libs (same chunks and order), cross-tab navigation, `/<id>/<path>` model URI helpers - editor/: InteractiveEditor (Monaco or mobile react-live) and StaticEditor (SSR/crawler/loading markup) - userAgent.ts: one source for bot/mobile regexes (isGoogleBot → isBot) - Remove PlaygroundEditor, PlaygroundLiveEditor, DiffEditorChooser aliases, the unused readOnly prop, and unreferenced resources/ - Unit tests for highlight selections and model paths Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Keep highlightSelections free of website-only deps CI runs Playground unit tests without website dependencies installed, so parse the highlight range in InteractiveEditor and pass line numbers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Cover useModelId and empty highlight ranges Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Restore PlaygroundEditor, PlaygroundLiveEditor, DiffEditorChooser, readOnly and resources Keep these entry points and the readOnly option available for future use; they now point at the reorganized editor modules. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Restore deletions Staff already accepted cf2de88 brought the dead files and the unused editor prop back. This commit restores the deletions Staff already accepted. Review: #4104 (review) Co-authored-by: Nathaniel Tucker <me@ntucker.me> * internal(website): Keep restored Playground files and readOnly prop Reverts 82bf2d0 per Nathaniel's choice to keep PlaygroundEditor, DiffEditorChooser, the readOnly prop and Playground/resources for now. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Correct useModelId comment and DiffEditor README chain Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Scope import completions per playground, accept bare path= metastrings Import completions for relative paths now list only files from the same playground instead of every Monaco model on the page. Fence metastrings accept unquoted path=a.ts (used in docs/rest/api/RestEndpoint.md). Also prettier-formats the Playground README. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Declare playground editor globals with valid TypeScript `declare globals { … }` is not TypeScript; the playground globals only typed because parser error recovery leaked the wrapped declarations into global scope, and DateTimeFormat silently became `any`. Mount editor-types/globals.d.ts as a module and alias its exports, React, JSX, NumberFlow, Temporal, DateTimeFormat and Manager into `declare global`. Also type TextInput/TextArea/Formatted props that referenced unresolved names. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkVym3YjjuSjBKhLLwvZm6 * internal(website): Type use and mockFetch playground globals Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkVym3YjjuSjBKhLLwvZm6 * internal(website): Type React jsx-runtime, path-to-regexp and bignumber.js in playgrounds (#4137) Mount real declarations for `react/jsx-runtime` (was an empty stub), `path-to-regexp` (never mounted, so @data-client/rest's PathFunction and ParamData were unresolved) and `bignumber.js` (stub whose types were never mounted), and declare `BigNumber` as a playground global since the preview scope provides it. Claude-Session: https://claude.ai/code/session_01W5R8xxJwz7dAy3Uk2v5eH5 Co-authored-by: Claude <noreply@anthropic.com> * internal(website): Type csstype and number-flow in playgrounds (#4139) * internal(website): Type React jsx-runtime, path-to-regexp and bignumber.js in playgrounds Mount real declarations for `react/jsx-runtime` (was an empty stub), `path-to-regexp` (never mounted, so @data-client/rest's PathFunction and ParamData were unresolved) and `bignumber.js` (stub whose types were never mounted), and declare `BigNumber` as a playground global since the preview scope provides it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W5R8xxJwz7dAy3Uk2v5eH5 * internal(website): Type csstype and number-flow in playgrounds React's CSSProperties and NumberFlow's props resolved through unmounted modules, so style values and NumberFlow format/trend/plugins were any. Mount csstype (comments stripped, 85KB -> 31KB gzipped) and a bundled number-flow/lite; number-flow/plugins re-exports from it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SP4rqYKdew65uNyP8xeJ9m * internal(website): Bundle @number-flow/react types with number-flow Bundle @number-flow/react's .d.ts with its number-flow/lite and number-flow/plugins imports inlined, instead of mounting those as separate modules with a hand-written plugins stub. uuid and number-flow now share one editor-types rollup config and resolver. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SP4rqYKdew65uNyP8xeJ9m --------- Co-authored-by: Claude <noreply@anthropic.com> * internal(website): Simplify Playground metastring, model path and type-lib helpers - One metaValue() parser for title= and path= (quotes optional for both) - One anchored model-id regex; stripModelId is a replace - Mark preview-scope global libs in MODULE_LIBS instead of modules[0] - language is required on InteractiveEditor (codeModel always sets it) - Drop unused return from Monaco setup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK * internal(website): Simplify playground globals parsing Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkVym3YjjuSjBKhLLwvZm6 * internal(website): Simplify playground editor-types build Bundle globals.d.ts from the editor-types rollup config (one rollup run, identical output), make mockFetch generic to match its editor declaration, and trim the README note. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TkVym3YjjuSjBKhLLwvZm6 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Requested by Nathaniel · project thread
Motivation
Before: the Playground folder mixed Monaco bootstrap, preview execution, editor UI and shared chrome at one level;
monaco-init.tswas a 362-line side-effect module; the SSR / incremental-loading / mobile / crawler behaviors lived only in scattered comments, so a cleanup could drop one silently. Import completions offered files from every playground on the page, and unquotedpath=metastrings were ignored.After: the same behavior, organized by concern, with a
Playground/README.mdthat lists every invariant (SSG markup, chunking and CDN hints, mobile/bot fallbacks, hidden Demo tabs, editor and preview behaviors) to check changes against. Import completions list only the current playground's files, andpath=Todo.tsworks likepath="Todo.ts".Solution
monaco/:setup.ts(the side-effect entry: UA gate, resource hints, CDN loader, compiler options),typeLibs.ts(table-driven; same webpack chunk names,lazy-oncedata-client chunk, fetch andaddExtraLiborder),theme.ts,navigation.ts(cross-tab go-to-definition + import completions, now scoped per playground viasiblingFilePaths),modelPath.ts(the/<id>/<path>URI scheme that used to be a cross-file comment),highlightSelections.ts(pure, tested), plus movedoptions,language,resourceHints, generatedpreloadManifest(generator path updated),useAutoHeight.editor/:InteractiveEditor(wasPlaygroundMonacoEditor; Monaco on desktop, editable react-live on mobile/bots, client-only) andStaticEditor(the SSR/crawler/loading markup, previously duplicated).TextEditTabcollapses its two branches into one.codeModelaccepts quoted or barepath=.preview/:Preview,PreviewBlock,PreviewWrapper,StoreInspector,Tree,FixturePreview,transformCode,temporaljoinLivePreview/scope.userAgent.ts: one definition of the bot and mobile regexes;isGoogleBot→isBot(it matched every crawler).PlaygroundEditor/PlaygroundLiveEditorentry points (now aliasing the new editor modules),DiffEditorChooser, thereadOnlyprop, andPlayground/resources/.HooksPlaygroundreusesPlaygroundPropsinstead of a duplicate interface.raw-plugin.jswarning filter now targetsmonaco/typeLibs.ts.Verification
yarn test --selectProjects ReactDOM --testPathPatterns website/src/components/Playground: 4 suites, 19 tests pass (new ones cover highlight selections, model paths, sibling files and barepath=); website typecheck and lint clean.docusaurus buildon master and on the reorg: same 265 asset files with the same named chunks (PreviewWithScope,PreviewBlock,*DTS), no new warnings, and all 170 generated HTML pages identical after normalizing hashed class names and script tags (the one remaining diff is a build-time timestamp in a fixture).Follow-ups (own PRs)
typeLibs.tsadds extra libs asdeclare globals { … }, which is not TypeScript syntax (declare global); needs an in-browser check that the fix adds no new diagnostics.website/ambientsource-plugin.js,website/src/components/useIntersectionObserver.tsx,website/src/components/Demo/Demo.module.css(pending Nathaniel's OK).Dispositions for every review follow-up (folded, moved or rejected, with reasons): #4104 (comment)
🤖 Generated with Claude Code
https://claude.ai/code/session_015H36Yk4WBpytw9L7RRVCTK
Note
Medium Risk
Large structural refactor of hydration-sensitive playground and Monaco bootstrap code; behavior is intended to be unchanged but regressions in SSR, lazy loading, or editor navigation would affect every docs page with live examples.
Overview
Reorganizes the docs Playground by concern (
editor/,monaco/,preview/) and documents SSR, chunking, mobile/bot, and hidden-tab invariants inPlayground/README.md. The oldmonaco-init.tsandPlaygroundMonacoEditorare replaced bymonaco/setup.tsplus smaller modules (typeLibs,theme,navigation,modelPath,highlightSelections) andInteractiveEditorwith a sharedStaticEditorfor SSG/hydration placeholders.Behavior tweaks: relative import completions use
siblingFilePathsso only files in the same playground are offered; fence metastrings accept barepath=/title=; crawler detection is centralized asisBotinuserAgent.ts(wasisGoogleBot).HooksPlaygroundimportsPlaygroundPropsfromPlayground; webpack warning suppression and the Monaco preload generator point at the newmonaco/paths.Reviewed by Cursor Bugbot for commit 5b856f4. Bugbot is set up for automated code reviews on this repo. Configure here.