fix: remote spaces, content browsing, and docs as real remote space (#66, #68)#67
Open
fix: remote spaces, content browsing, and docs as real remote space (#66, #68)#67
Conversation
Contributor
Release Version Check
This version will be released automatically when this PR is merged to Changelog preview0.8.0 (2026-03-25)FeaturesBug Fixes
Refactoring |
Contributor
Preview DeploymentThe web app for this PR has been deployed: Use this to verify the app works correctly, especially for dependency updates. |
9 tasks
nsheaps
commented
Mar 23, 2026
Owner
Author
nsheaps
left a comment
There was a problem hiding this comment.
Code Review Summary
Self-review performed with 8 parallel review agents. Issues found were fixed in commit 14c095b.
| Category | Initial | Post-Fix | Status |
|---|---|---|---|
| Simplicity | 58 | ~75 | |
| Flexibility | 62 | ~78 | |
| Usability | 78 | ~85 | ✅ Fixed: onGoBack as prop, history check, notFound clears on navigation |
| Documentation | 72 | ~78 | |
| Security | 72 | ~88 | ✅ Fixed: GitHub URL domain validation against allowlist |
| Patterns | 72 | ~80 | |
| Best Practices | 62 | ~82 | |
| Quality | 72 | ~82 |
Issues fixed in review commit
- Memory leak: Added cancellation flag to inactive space stats
useEffect - notFound persistence: Cleared on
popstatenavigation - Open redirect: GitHub URL validated against
KNOWN_GIT_HOSTSallowlist - SVG duplication: Extracted
GitHubIconcomponent - IIFE in JSX: Replaced with
useMemoforcurrentGithubUrl - Complex scoring: Simplified
resolveRouteToSpaceto longest-prefix match - Redundant branches: Fixed
if (exact)/ else returning same value - Direct window access:
NotFoundPage.onGoBackis now an optional callback prop - Extension mismatch:
pageIdToFilenamealigned with router'sFILE_EXTENSIONS - Missing tests: Added 8 NotFoundPage tests + 4 extractFrontMatter tests
Known limitations (deferred)
- Custom YAML parser only handles
hide:— future.cept.yamlkeys will need parser updates - No page ID migration from old
git-{flattened}format — users must re-clone - Inactive space storage size shows 0 (would require reading all files; page count is shown)
- First-time visitors with multi-segment branch URLs to un-cloned repos get router's best guess
Page IDs now use actual file paths (e.g., "docs/getting-started.md") instead of flattened dash-encoded slugs (e.g., "git-docs-getting-started-md"). This prevents collisions between files like foo/bar.md and foo-bar.md. - Router uses file extension detection instead of git- prefix - Storage functions handle page IDs with .md extension - Added resolveRouteToSpace for matching minimal route spaceIds to configured spaces with subPath - Added collision regression test https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
- Space IDs now use :: separator between branch and subPath (e.g., repo@claude/fix::docs) to avoid ambiguity with / in branches - resolveRouteToSpace tries progressive branch matching to handle multi-segment branch names like "claude/setup-fix" - Added NotFoundPage component for clear 404 errors with navigation - Clone failures now show proper 404 page instead of error string - Legacy / separator still supported for backward compatibility https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
The file browser was always browsing from the filesystem root (/),
showing the demo space's files regardless of which space was selected.
Now it uses the space-specific storage path (.cept/spaces/{spaceId})
so each space browses its own files.
https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
- README.md/index.md files in folders now serve as the folder's page content instead of creating separate pages - Frontmatter title field is used for page titles when available - Added .cept.yaml folder-level config support with hide: [] to exclude files/folders from the sidebar (applies to folder and subfolders) - parseCeptYaml supports both inline [a, b] and block - a list syntax - extractFrontMatter reads YAML front matter for title/metadata https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Inactive spaces now load their stats asynchronously from the backend instead of always showing 0 for pages and storage used. The active space still uses live React state for accurate real-time counts. https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
#63 - GitHub icon button appears next to the triple-dot menu on remote pages - Menu includes "View page on GitHub" link and "Share (coming soon)" item - GitHub URL computed from space metadata (repo, branch, subPath) - Also works for docs pages via getDocsSourceUrl - Removed the source callout banner from docs pages (replaced by menu) https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Action buttons (Refresh, Browse, Delete) in space details now display horizontally in a flex row instead of stacking vertically. Labels shortened to icon + first word for a cleaner, more compact UI. https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
- Fix memory leak in inactive space stats useEffect (add cancellation) - Clear notFound state on popstate (back/forward navigation) - Validate GitHub URL domain against known hosts (prevent open redirect) - Extract GitHubIcon component to remove SVG duplication - Replace IIFE with useMemo for currentGithubUrl - Simplify resolveRouteToSpace (longest-prefix match, no scoring) - Fix redundant if/else branches in resolveRouteToSpace - Make onGoBack optional prop in NotFoundPage (no direct window access) - Align pageIdToFilename extensions with router's FILE_EXTENSIONS - Add NotFoundPage component tests (8 test cases) - Add extractFrontMatter tests (4 test cases) https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Add docs-loader module that clones github.com/nsheaps/cept scoped to docs/content/ using the existing cloneRemoteRepo infrastructure. Cloned content is cached in .cept/docs-cache/ for instant subsequent loads. When cloning fails (offline, CORS errors), falls back to the bundled DOCS_PAGES/DOCS_CONTENT constants. - New docs-loader.ts with loadDocs() and getRemoteDocsSourceUrl() - App.tsx uses loader on first docs space open - Sidebar reflects actual repository layout when loaded from remote - View on GitHub links work with both remote file paths and bundled IDs - Loading state shown while clone is in progress - Banner indicates content source (remote, cached, or bundled fallback) Closes #68 https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Remove the entire separate docs rendering path (activeSpace === 'docs', docs-specific sidebar, banner, content rendering) and make docs a normal remote space in the manifest. handleOpenDocs now: 1. Calls ensureDocsSpace() which creates a remote space entry for github.com/nsheaps/cept (docs/content subpath) if it doesn't exist 2. Clones from GitHub or falls back to bundled DOCS_PAGES/DOCS_CONTENT 3. Switches to the space via the standard loadAndApplySpaceState flow This means docs now gets the same UI as any other remote space: - Top nav buttons (GitHub link, page menu) - Settings panel with Remote URL, Branch, Last synced - Refresh button to re-clone from remote - Standard sidebar with space switcher Removed: - activeSpace state and all docs/user branching - docsPages, docsContents, docsSource, docsLoading state - handleDocsPageSelect, handleDocsPageToggle callbacks - Docs-specific sidebar with read-only handlers - Docs-specific content area with banner and CeptEditor - DOCS_SPACE_INFO constant usage - 'cept-docs' exclusion from SettingsModal refresh button Closes #68 https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Two issues after converting docs to a real remote space: 1. After data reset, docs space didn't appear in space list because it was only created on-demand when clicking "Help & Docs". Now ensureDocsSpace() runs during app initialization so the docs space is always present in the space switcher. 2. Preview deploys hardcoded DOCS_BRANCH='main' instead of using the __HEAD_BRANCH__ build-time global. Now docs-loader uses the same pattern as docs-content.ts to pick up the PR branch for previews. https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
Remote spaces (including docs) are cloned from Git repos and should not
be editable. Pass editable={false} to CeptEditor when the active space
is a remote space, which sets contenteditable="false" on the ProseMirror
element and hides the inline toolbar.
https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
When navigating to a URL like /g/repo/blob/main/docs/, the router produces a spaceId with subPath "docs" and no pageId. Previously, resolveRouteToSpace returned this as-is without searching for matching spaces, causing a redundant clone with subPath "docs" (which includes SPECIFICATION.md and other non-content files) even when a space with subPath "docs/content" already existed. Now resolveRouteToSpace searches for spaces whose subPath starts with the route's subPath on a path boundary. This prevents: - Duplicate spaces for the same repo/branch with different subPath depths - "Cloning..." flash on reload when the space already exists - Wrong content (SPECIFICATION.md) appearing instead of docs content https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD
fb17292 to
d497221
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR addresses multiple issues with remote spaces and documentation:
Remote Spaces Browsing (#66)
Docs as Real Remote Space (#68)
ensureDocsSpace()creates a remote space entry forgithub.com/nsheaps/cept(scoped todocs/content/) on app startupcloneRemoteRepoor falls back to bundledDOCS_PAGES/DOCS_CONTENT__HEAD_BRANCH__build-time global so preview deploys clone from the PR branchcept-docsexclusions from SettingsModal refresh/browse buttonsEditor Read-Only for Remote Spaces
contenteditable="false") when viewing a remote spacePartial-SubPath URL Resolution
resolveRouteToSpaceto match directory URLs (e.g.,/g/repo/blob/main/docs/) to existing spaces with more-specific subPaths (e.g.,docs/content)docsmatchesdocs/contentbutdocdoes notdocsinstead ofdocs/contentCloses #66
Closes #68
Test plan
bun run validatepasses (lint + typecheck + 1743 tests across 101 files)/g/github.com/nsheaps/cept/blob/main/docs/— verify it resolves to the existing docs space (not creating a duplicate)https://claude.ai/code/session_01TF6rYpGkqBWjzNQHgqrVmD