GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — fix(sidebar): prefetch folders and workspace permissions on cold load by waleedlatif1 · Pull Request #5426 · simstudioai/sim

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Sidebar workflow list and mothership chat list were already server-prefetched, but the folder list wasn't — so a cold sidebar load painted a flat workflow list, then flashed into folder-grouped view once useFolders resolved client-side
  • Added a folder prefetch (folderKeys.list) to prefetchWorkspaceSidebar, backed by a new listFoldersForWorkspace server-side query mirroring the existing GET /api/folders logic
  • Also prefetched workspace permissions (workspaceKeys.permissions) — WorkspaceHeader's permission-gated actions (e.g. "New workflow") were flipping shortly after mount for the same reason. Extracted the shared logic into getWorkspacePermissionsForViewer in lib/workspaces/permissions/utils.ts so the route and the prefetch use one implementation instead of two
  • Deliberately did not prefetch the full workspace list (workspaceKeys.list) — its route does invite-policy evaluation, org plan lookups, and first-run default-workspace creation side effects, not just a DB read. Duplicating that into the prefetch path would be a much larger, separate change

Type of Change

  • Bug fix

Testing

  • bunx tsc --noEmit clean
  • bun run check:client-boundary, bun run check:react-query both pass
  • bunx biome check clean on touched files
  • Existing route test suites for /api/folders and /api/workspaces/[id]/permissions (40 tests) pass unmodified against the refactored handler

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

greptile-apps[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@waleedlatif1
fix(sidebar): prefetch folders and workspace permissions on cold load
cce2e10
@vercel

vercel Bot commented Jul 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jul 5, 2026 6:08pm

Request Review

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@cursor

cursor Bot commented Jul 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches workspace permission resolution on both the permissions API and server prefetch; behavior should match prior handlers but authorization regressions would be user-visible.

Overview
Fixes sidebar UI flash on cold load by server-prefetching active folders and workspace permissions alongside workflows and chats, using the same React Query keys and mappers as the client hooks.

listFoldersForWorkspace centralizes the folder list DB query (including archived scope and ISO date wire shape) for GET /api/folders and prefetchWorkspaceSidebar. getWorkspacePermissionsForViewer does the same for the permissions payload (member list + viewer role); GET /api/workspaces/[id]/permissions now delegates to it instead of inlining access checks.

Exported FOLDER_LIST_STALE_TIME and WORKSPACE_PERMISSIONS_STALE_TIME so prefetch and hooks share stale-time constants.

Reviewed by Cursor Bugbot for commit 2a10b88. Configure here.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@greptile-apps

greptile-apps Bot commented Jul 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a cold-load flash in the sidebar where workflows appeared in a flat list briefly before jumping into the folder-grouped view, and where workspace-gated actions (like "New workflow") momentarily toggled after mount. It adds server-side prefetches for both the active folder list and workspace permissions, placing them alongside the already-prefetched workflow and chat lists.

  • lib/folders/queries.ts (new): Extracts the listFoldersForWorkspace query — including timestamp normalization to FolderApi wire format — so GET /api/folders and the prefetch share one implementation.
  • lib/workspaces/permissions/utils.ts: Adds getWorkspacePermissionsForViewer consolidating the previously scattered hasWorkspaceAdminAccess + checkWorkspaceAccess + getUserEntityPermissions + getUsersWithPermissions calls into a single function; the permissions route and sidebar prefetch both use it.
  • app/workspace/[workspaceId]/prefetch.ts: Adds two new prefetchQuery calls (folders + workspace permissions) inside the existing Promise.all; FOLDER_LIST_STALE_TIME and mapFolder are exported from their respective hook files to keep key/mapper co-location intact.

Confidence Score: 5/5

Safe to merge — the changes are additive prefetch calls and straightforward extractions of existing inline logic into shared helpers.

The folder and permissions prefetch functions are backed by the same Drizzle queries the existing API routes use; the refactored GET permissions handler preserves the exact same access-control conditions and response shape as the original; and the exported stale-time constants keep the prefetch and client hooks in lock-step. No behavioral regressions were found.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/folders/queries.ts New file extracting listFoldersForWorkspace with proper FolderApi timestamp normalization; cleanly replaces the inline Drizzle query in GET /api/folders.
apps/sim/lib/workspaces/permissions/utils.ts Adds getWorkspacePermissionsForViewer which consolidates 4 separate DB-touching calls into one; logic is equivalent to the old route handler and now shared with the prefetch path.
apps/sim/app/workspace/[workspaceId]/prefetch.ts Adds two new prefetchQuery calls (folderKeys.list + workspaceKeys.permissions) inside the existing Promise.all; query keys and stale times match the client hooks exactly.
apps/sim/app/api/workspaces/[id]/permissions/route.ts GET handler simplified from 4 separate DB calls to a single getWorkspacePermissionsForViewer call; behavior is semantically identical (same 404 conditions, same response shape).
apps/sim/app/api/folders/route.ts Inline Drizzle query replaced with listFoldersForWorkspace; filtering and ordering logic is preserved exactly.
apps/sim/hooks/queries/folders.ts Extracts FOLDER_LIST_STALE_TIME as a named export and exports mapFolder; staleTime is now consistently sourced from this constant across useFolders and useFolderMap.
apps/sim/hooks/queries/workspace.ts Extracts WORKSPACE_PERMISSIONS_STALE_TIME (30 s) as a named export so the prefetch and the hook use the same constant.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant RSC as RSC Page (server)
    participant PF as prefetchWorkspaceSidebar
    participant DB as Database

    RSC->>PF: prefetchWorkspaceSidebar(queryClient, workspaceId, userId)
    PF->>DB: checkWorkspaceAccess (getWorkspaceWithOwner + getEffectiveWorkspacePermission)
    DB-->>PF: access result

    alt user cannot access workspace
        PF-->>RSC: return (skip silently)
    else user has access
        par workflows
            PF->>DB: listWorkflowsForUser
            DB-->>PF: workflow rows → mapWorkflow[]
        and chats
            PF->>DB: listMothershipChats
            DB-->>PF: chat rows → mapChat[]
        and folders (NEW)
            PF->>DB: listFoldersForWorkspace (active)
            DB-->>PF: folder rows → FolderApi[] → mapFolder[]
        and permissions (NEW)
            PF->>DB: getWorkspacePermissionsForViewer
            note over PF,DB: getWorkspaceWithOwner + getEffectiveWorkspacePermission + getUsersWithPermissions
            DB-->>PF: WorkspacePermissionsForViewer
        end
        PF->>PF: queryClient.setQueryData for all 4 caches
        PF-->>RSC: return (caches populated)
    end

    RSC->>RSC: dehydrate(queryClient) → HydrationBoundary
    note over RSC: Client receives pre-populated cache — no flash
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant RSC as RSC Page (server)
    participant PF as prefetchWorkspaceSidebar
    participant DB as Database

    RSC->>PF: prefetchWorkspaceSidebar(queryClient, workspaceId, userId)
    PF->>DB: checkWorkspaceAccess (getWorkspaceWithOwner + getEffectiveWorkspacePermission)
    DB-->>PF: access result

    alt user cannot access workspace
        PF-->>RSC: return (skip silently)
    else user has access
        par workflows
            PF->>DB: listWorkflowsForUser
            DB-->>PF: workflow rows → mapWorkflow[]
        and chats
            PF->>DB: listMothershipChats
            DB-->>PF: chat rows → mapChat[]
        and folders (NEW)
            PF->>DB: listFoldersForWorkspace (active)
            DB-->>PF: folder rows → FolderApi[] → mapFolder[]
        and permissions (NEW)
            PF->>DB: getWorkspacePermissionsForViewer
            note over PF,DB: getWorkspaceWithOwner + getEffectiveWorkspacePermission + getUsersWithPermissions
            DB-->>PF: WorkspacePermissionsForViewer
        end
        PF->>PF: queryClient.setQueryData for all 4 caches
        PF-->>RSC: return (caches populated)
    end

    RSC->>RSC: dehydrate(queryClient) → HydrationBoundary
    note over RSC: Client receives pre-populated cache — no flash
Loading

Reviews (2): Last reviewed commit: "fix(folders): reference FOLDER_LIST_STAL..." | Re-trigger Greptile

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@waleedlatif1
refactor(sidebar): dedupe folder query and permission lookups from /s…
b90f782
…implify pass
@vercel
vercel Bot temporarily deployed to Preview July 5, 2026 03:36 Inactive
@waleedlatif1
docs(workspaces): trim getWorkspacePermissionsForViewer tsdoc to matc…
9d93827
…h repo convention
@vercel
vercel Bot temporarily deployed to Preview July 5, 2026 03:39 Inactive
@waleedlatif1
fix(folders): reference FOLDER_LIST_STALE_TIME constant instead of du…
2a10b88
…plicating literal
@vercel
vercel Bot temporarily deployed to Preview July 5, 2026 03:41 Inactive
@waleedlatif1 waleedlatif1 mentioned this pull request Jul 5, 2026
refactor(react-query): hoist every staleTime into a named exported constant #5427
Merged
5 of 6 tasks
@waleedlatif1

waleedlatif1 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile

greptile-apps[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@waleedlatif1

waleedlatif1 commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

@cursor review

cursor[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cursor[bot]
cursor Bot reviewed Jul 5, 2026
View reviewed changes

@cursor cursor Bot left a comment

Copy link
Copy Markdown

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2a10b88. Configure here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@waleedlatif1 waleedlatif1 mentioned this pull request Jul 5, 2026
fix(custom-blocks): dedupe redundant workspace lookup in POST admin check #5429
Merged
5 of 6 tasks
waleedlatif1 added a commit that referenced this pull request Jul 5, 2026
@waleedlatif1
refactor(react-query): hoist every staleTime into a named exported co…
487166f
…nstant (#5427)

* refactor(react-query): hoist every staleTime into a named exported constant

Adds a repo-wide convention (documented in .claude/rules/sim-queries.md,
CLAUDE.md, and the react-query-best-practices skill/command) that every
staleTime value must come from a named exported constant instead of an
inline numeric literal. This prevents a server-side prefetch and its
client hook from independently duplicating the same duration and
drifting out of sync, which Greptile caught on PR #5426.

Applies the convention across all of hooks/queries/** and their
prefetch.ts consumers.

* refactor(react-query): use FOLDER_LIST_STALE_TIME in folders.ts hooks

useFolders and useFolderMap still used inline 60 * 1000 despite folders.ts
already exporting FOLDER_LIST_STALE_TIME — the same prefetch-drift gap this
refactor closes everywhere else. Same value, no behavior change.
@waleedlatif1
Merge remote-tracking branch 'origin/staging' into sidebar-prefetch-f…
d9b4047
…olders-permissions

# Conflicts:
#	apps/sim/hooks/queries/workspace.ts
@waleedlatif1
waleedlatif1 merged commit 4fa1e04 into staging Jul 5, 2026
10 of 11 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@waleedlatif1
waleedlatif1 deleted the sidebar-prefetch-folders-permissions branch July 5, 2026 18:05
@vercel
vercel Bot deployed to Preview July 5, 2026 18:08
View deployment
@waleedlatif1 waleedlatif1 mentioned this pull request Jul 7, 2026
v0.7.24: frontend perf improvements, md editor fixes, mailer fix, tools audit #5458
Merged

This branch was successfully deployed

1 active deployment
Preview — d9b40473 Deployed Jul 5, 2026 by vercel[bot]
View deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@cursor cursor[bot] cursor[bot] left review comments

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@waleedlatif1
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.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.