Skip to content

refactor(web-core): extract the shared frontend substrate - #404

Merged
didinele merged 2 commits into
mainfrom
refactor/web-core
Sep 8, 2026
Merged

didinele merged 2 commits into
mainfrom
refactor/web-core

Conversation

@didinele

@didinele didinele commented Sep 8, 2026

Copy link
Copy Markdown
Member

No description provided.

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
chatsift-website Ready Ready Preview Sep 8, 2026 11:13am UTC

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 259 files, which is 159 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 356de1af-c8c2-46ca-9642-48edf6ee3019

📥 Commits

Reviewing files that changed from the base of the PR and between 30266b0 and 1f7467d.

⛔ Files ignored due to path filters (57)
  • packages/private/web-core/assets/fonts/Author-Bold.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Bold.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Bold.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Bold.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-BoldItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-BoldItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-BoldItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-BoldItalic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Extralight.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Extralight.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Extralight.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Extralight.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-ExtralightItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-ExtralightItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-ExtralightItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-ExtralightItalic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Italic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Italic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Italic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Italic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Light.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Light.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Light.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Light.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-LightItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-LightItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-LightItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-LightItalic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Medium.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Medium.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Medium.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Medium.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-MediumItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-MediumItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-MediumItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-MediumItalic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Regular.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Regular.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Regular.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Regular.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Semibold.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Semibold.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Semibold.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Semibold.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-SemiboldItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-SemiboldItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-SemiboldItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-SemiboldItalic.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-Variable.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-Variable.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-Variable.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-Variable.woff2 is excluded by !**/*.woff2
  • packages/private/web-core/assets/fonts/Author-VariableItalic.eot is excluded by !**/*.eot
  • packages/private/web-core/assets/fonts/Author-VariableItalic.ttf is excluded by !**/*.ttf
  • packages/private/web-core/assets/fonts/Author-VariableItalic.woff is excluded by !**/*.woff
  • packages/private/web-core/assets/fonts/Author-VariableItalic.woff2 is excluded by !**/*.woff2
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (259)
  • .dockerignore
  • .gitignore
  • CLAUDE.md
  • apps/website/next.config.mjs
  • apps/website/package.json
  • apps/website/src/api/queryClient.ts
  • apps/website/src/api/routes/ama.ts
  • apps/website/src/api/routes/auth.ts
  • apps/website/src/api/routes/automoderator.ts
  • apps/website/src/api/routes/automoderatorBanwords.ts
  • apps/website/src/api/routes/automoderatorBypassRoles.ts
  • apps/website/src/api/routes/automoderatorCases.ts
  • apps/website/src/api/routes/automoderatorFilters.ts
  • apps/website/src/api/routes/automoderatorReports.ts
  • apps/website/src/api/routes/automoderatorTriggerPunishments.ts
  • apps/website/src/api/routes/automoderatorWarnPunishments.ts
  • apps/website/src/api/routes/experiments.ts
  • apps/website/src/api/routes/guilds.ts
  • apps/website/src/api/routes/modmail.ts
  • apps/website/src/api/routes/modmailThreads.ts
  • apps/website/src/api/routes/social.ts
  • apps/website/src/api/token.ts
  • apps/website/src/api/ws.ts
  • apps/website/src/app/admin/_components/ExperimentCard.tsx
  • apps/website/src/app/admin/_components/ExperimentForm.tsx
  • apps/website/src/app/admin/_components/ExperimentsConsole.tsx
  • apps/website/src/app/admin/_components/GuildChecker.tsx
  • apps/website/src/app/ama-answers/[shareToken]/_components/PublicAnswers.tsx
  • apps/website/src/app/ama-answers/[shareToken]/_lib/publicAnswers.ts
  • apps/website/src/app/ama-answers/[shareToken]/page.tsx
  • apps/website/src/app/automoderator/history/[token]/_components/PublicHistory.tsx
  • apps/website/src/app/automoderator/report/[token]/_components/ReportDraft.tsx
  • apps/website/src/app/automoderator/whats-changing/_components/FeatureChangeList.tsx
  • apps/website/src/app/automoderator/whats-changing/_components/OutcomeLegend.tsx
  • apps/website/src/app/automoderator/whats-changing/page.tsx
  • apps/website/src/app/bot/[name]/page.tsx
  • apps/website/src/app/dashboard/[id]/_components/GuildNav.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/_components/AMADetails.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/page.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/AuthorAvatar.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/BulkMergePicker.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/MergeDuplicatePicker.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/QuestionDetailPanel.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/QuestionStateTabs.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/QuestionTagFilter.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/QuestionsList.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/_components/TagPicker.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/new/_components/CreateQuestionForm.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/new/page.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/[amaId]/questions/page.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/AMASessionCard.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/AMASessionsHeading.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/AMASessionsList.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/NormalPromptFields.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/OpenOnlyToggle.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/PromptModeToggle.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/_components/PromptPreview.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/new/_components/CreateAMAForm.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/new/page.tsx
  • apps/website/src/app/dashboard/[id]/ama/amas/page.tsx
  • apps/website/src/app/dashboard/[id]/ama/page.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/_components/FilterToggle.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/_components/UserBadge.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/anti-spam/_components/AntiSpamForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/banned-words/_components/BannedWordsList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/banned-words/_components/BanwordPolicyForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/banned-words/_components/RefreshRulesButton.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/cases/[caseId]/_components/CaseDetail.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/cases/_components/CaseFilters.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/cases/_components/CasesList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/cases/page.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/exemptions/_components/BypassRolesForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/exemptions/_components/FilterExemptionsForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/filter-ladder/_components/TriggerDecayForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/filter-ladder/_components/TriggerLadderList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/filter-ladder/_components/TriggerPunishmentForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/invite-filter/_components/InviteFilterForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/join-gate/_components/JoinGateForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/logging/_components/LogChannelsForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/logging/_components/LogExemptionsForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-prompts/[promptId]/_components/EditReportPromptForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-prompts/_components/ReportPromptCard.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-prompts/_components/ReportPromptForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-prompts/_components/ReportPromptsList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-settings/_components/ReportPresetsForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/report-settings/_components/ReportsChannelForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/reports/[reportId]/_components/ReportDetail.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/reports/_components/ReportFilters.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/reports/_components/ReportsList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/reports/page.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/url-filter/_components/UrlFilterForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/warn-ladder/_components/AutoPardonForm.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/warn-ladder/_components/WarnLadderList.tsx
  • apps/website/src/app/dashboard/[id]/automoderator/warn-ladder/_components/WarnPunishmentForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/blocks/_components/BlockCard.tsx
  • apps/website/src/app/dashboard/[id]/modmail/blocks/_components/BlocksList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/blocks/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/[categoryId]/_components/EditCategoryForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/[categoryId]/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/_components/CategoriesList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/_components/CategoryCard.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/_components/categoryForm.ts
  • apps/website/src/app/dashboard/[id]/modmail/categories/new/_components/CreateCategoryForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/new/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/categories/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/config/_components/ModmailConfigForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/config/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/[panelId]/_components/EditPanelForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/[panelId]/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/_components/CategoryCheckboxList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/_components/PanelCard.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/_components/PanelEmbedFields.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/_components/PanelModeToggle.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/_components/PanelsList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/new/_components/CreatePanelForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/new/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/panels/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/[snippetId]/_components/EditSnippetForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/[snippetId]/_components/SnippetRevisionHistory.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/[snippetId]/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/_components/SnippetCard.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/_components/SnippetsList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/_components/snippetForm.ts
  • apps/website/src/app/dashboard/[id]/modmail/snippets/new/_components/CreateSnippetForm.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/new/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/snippets/page.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/[threadId]/_components/EditHistoryBadge.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/[threadId]/_components/ThreadDetail.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/[threadId]/_components/ThreadMessage.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/[threadId]/_components/ThreadMessageList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/[threadId]/_components/ThreadSidebar.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/_components/CategoryFilter.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/_components/IncludeClosedToggle.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/_components/ThreadsList.tsx
  • apps/website/src/app/dashboard/[id]/modmail/threads/page.tsx
  • apps/website/src/app/dashboard/[id]/page.tsx
  • apps/website/src/app/dashboard/[id]/settings/_components/GrantCard.tsx
  • apps/website/src/app/dashboard/[id]/settings/_components/GrantsList.tsx
  • apps/website/src/app/dashboard/[id]/settings/new/_components/CreateGrantForm.tsx
  • apps/website/src/app/dashboard/[id]/settings/new/page.tsx
  • apps/website/src/app/dashboard/[id]/settings/page.tsx
  • apps/website/src/app/dashboard/[id]/social/channels/[channelId]/page.tsx
  • apps/website/src/app/dashboard/[id]/social/channels/_components/SocialChannelForm.tsx
  • apps/website/src/app/dashboard/[id]/social/channels/_components/SocialChannelsList.tsx
  • apps/website/src/app/dashboard/[id]/social/channels/new/page.tsx
  • apps/website/src/app/dashboard/[id]/social/channels/page.tsx
  • apps/website/src/app/dashboard/[id]/social/config/_components/SocialConfigForm.tsx
  • apps/website/src/app/dashboard/[id]/social/config/page.tsx
  • apps/website/src/app/dashboard/[id]/social/interactions/[interactionId]/page.tsx
  • apps/website/src/app/dashboard/[id]/social/interactions/_components/SocialInteractionForm.tsx
  • apps/website/src/app/dashboard/[id]/social/interactions/_components/SocialInteractionsList.tsx
  • apps/website/src/app/dashboard/[id]/social/interactions/_components/interactionForm.ts
  • apps/website/src/app/dashboard/[id]/social/interactions/new/page.tsx
  • apps/website/src/app/dashboard/[id]/social/interactions/page.tsx
  • apps/website/src/app/dashboard/[id]/social/leaderboard/_components/PublicLeaderboardCard.tsx
  • apps/website/src/app/dashboard/[id]/social/leaderboard/_components/SocialLeaderboard.tsx
  • apps/website/src/app/dashboard/[id]/social/leaderboard/page.tsx
  • apps/website/src/app/dashboard/[id]/social/page.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/[roleId]/page.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/_components/RewardLadder.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/_components/SocialRewardForm.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/_components/SocialRewardsList.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/new/page.tsx
  • apps/website/src/app/dashboard/[id]/social/rewards/page.tsx
  • apps/website/src/app/dashboard/[id]/social/roles/[roleId]/page.tsx
  • apps/website/src/app/dashboard/[id]/social/roles/_components/SocialRoleForm.tsx
  • apps/website/src/app/dashboard/[id]/social/roles/_components/SocialRolesList.tsx
  • apps/website/src/app/dashboard/[id]/social/roles/new/page.tsx
  • apps/website/src/app/dashboard/[id]/social/roles/page.tsx
  • apps/website/src/app/dashboard/_components/DashboardLinkErrorNotice.tsx
  • apps/website/src/app/dashboard/_components/GuildCard.tsx
  • apps/website/src/app/dashboard/_components/GuildList.tsx
  • apps/website/src/app/dashboard/_components/RefreshGuildsButton.tsx
  • apps/website/src/app/dashboard/page.tsx
  • apps/website/src/app/error.tsx
  • apps/website/src/app/global-error.tsx
  • apps/website/src/app/layout.tsx
  • apps/website/src/app/leaderboard/[guildId]/_components/PublicLeaderboard.tsx
  • apps/website/src/app/leaderboard/[guildId]/_lib/publicLeaderboard.ts
  • apps/website/src/app/leaderboard/[guildId]/page.tsx
  • apps/website/src/app/not-found.tsx
  • apps/website/src/app/page.tsx
  • apps/website/src/app/privacy/page.tsx
  • apps/website/src/app/terms/page.tsx
  • apps/website/src/components/common/Breadcrumb.tsx
  • apps/website/src/components/common/BreadcrumbDropdown.tsx
  • apps/website/src/components/common/ChannelSelect.tsx
  • apps/website/src/components/common/DiscordMarkdown.tsx
  • apps/website/src/components/common/EmbedMessagePreview.tsx
  • apps/website/src/components/common/EmojiInput.tsx
  • apps/website/src/components/common/ForumTagSelect.tsx
  • apps/website/src/components/common/NavGate.tsx
  • apps/website/src/components/common/Providers.tsx
  • apps/website/src/components/common/RefreshServerDataButton.tsx
  • apps/website/src/components/common/RoleSelect.tsx
  • apps/website/src/components/dashboard/DashboardCrumbs.tsx
  • apps/website/src/components/dashboard/PageHeader.tsx
  • apps/website/src/components/dashboard/ResyncCard.tsx
  • apps/website/src/components/footer/ThemeSwitchButton.tsx
  • apps/website/src/components/marketing/LinkButton.tsx
  • apps/website/src/components/marketing/ScreenshotGallery.tsx
  • apps/website/src/components/nav/NavbarMobile.tsx
  • apps/website/src/components/social/LeaderboardTable.tsx
  • apps/website/src/components/user/LoginButton.tsx
  • apps/website/src/components/user/LogoutButton.tsx
  • apps/website/src/components/user/UserAvatar.tsx
  • apps/website/src/components/user/UserDesktop.tsx
  • apps/website/src/components/user/UserErrorHandler.tsx
  • apps/website/src/instrumentation-client.ts
  • apps/website/src/instrumentation.ts
  • apps/website/src/styles/globals.css
  • apps/website/src/utils/util.ts
  • apps/website/turbo.json
  • docs/frontend.md
  • docs/roadmap/09-appeals.md
  • eslint.config.js
  • packages/private/web-core/package.json
  • packages/private/web-core/src/api/__tests__/report.test.ts
  • packages/private/web-core/src/api/error.ts
  • packages/private/web-core/src/api/errorBanner.ts
  • packages/private/web-core/src/api/fetch.ts
  • packages/private/web-core/src/api/formErrors.ts
  • packages/private/web-core/src/api/queryClient.ts
  • packages/private/web-core/src/api/realtimeClientId.ts
  • packages/private/web-core/src/api/report.ts
  • packages/private/web-core/src/api/serverTokenCache.ts
  • packages/private/web-core/src/api/store.ts
  • packages/private/web-core/src/api/token.ts
  • packages/private/web-core/src/components/Avatar.tsx
  • packages/private/web-core/src/components/Button.tsx
  • packages/private/web-core/src/components/ColorField.tsx
  • packages/private/web-core/src/components/ConfirmModal.tsx
  • packages/private/web-core/src/components/DiscordUserAvatar.tsx
  • packages/private/web-core/src/components/Emoji.tsx
  • packages/private/web-core/src/components/EmptyState.tsx
  • packages/private/web-core/src/components/ErrorBanner.tsx
  • packages/private/web-core/src/components/FormActions.tsx
  • packages/private/web-core/src/components/GenericAvatar.tsx
  • packages/private/web-core/src/components/GenericAvatarImages.tsx
  • packages/private/web-core/src/components/Heading.tsx
  • packages/private/web-core/src/components/RawJsonField.tsx
  • packages/private/web-core/src/components/ScrollArea.tsx
  • packages/private/web-core/src/components/SearchBar.tsx
  • packages/private/web-core/src/components/SegmentedControl.tsx
  • packages/private/web-core/src/components/Skeleton.tsx
  • packages/private/web-core/src/components/SnowflakeInput.tsx
  • packages/private/web-core/src/components/TextAreaField.tsx
  • packages/private/web-core/src/components/TextField.tsx
  • packages/private/web-core/src/components/Tooltip.tsx
  • packages/private/web-core/src/components/buttonStyles.ts
  • packages/private/web-core/src/styles/author.css
  • packages/private/web-core/src/styles/theme.css
  • packages/private/web-core/src/utils/cn.ts
  • packages/private/web-core/tsconfig.eslint.json
  • packages/private/web-core/tsconfig.json
  • packages/private/web-core/turbo.json
  • packages/private/web-core/vitest.config.ts
  • scripts/sync-web-core-assets.mjs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown

Claude finished @didinele's task in 4m 22s —— View job


Review: extract the shared frontend substrate (@chatsift/web-core)

  • Gather context (diff, new package config, non-trivial changes)
  • Review correctness / edge cases
  • Review conventions (CLAUDE.md, frontend.md)
  • Review security & performance
  • Post feedback

This is a large but overwhelmingly mechanical and clean refactor: ~300 files are pure import-path swaps (@/components/common/* and @/api/*@chatsift/web-core/*), and the genuinely new surface is small and well-documented. I verified the moving parts statically (I could not run yarn build/lint/testyarn install isn't in the pre-approved set for this job, so those remain for you to confirm in CI).

What I checked and found consistent

  • queryClient split is faithful. The extracted makeQueryClient in web-core preserves the #386 "report once" ordering, the 401/background-refetch/banner branches, retry policy, and the reporting-only MutationCache. The app-specific me-cache-nulling correctly moved behind the new onUnauthorized callback, and getBrowserQueryClient's SSR-throwaway-vs-browser-singleton behaviour is unchanged.
  • Atom move is safe. accessTokenAtom now lives in web-core and is read/written only through the shared web-core/api/store singleton; Providers.tsx passes that same store to <JotaiProvider>, so there's no second store to desync against. No duplicate accessTokenAtom remains in the app, and the app-local lastExplicitLogoutAtAtom stayed behind (correctly — it's dashboard-nav-specific).
  • No dangling imports. No remaining @/components/common/* imports resolve to a moved component, no app file imports a moved @/api/* module, cn was removed from @/utils/util with no stragglers, and web-core/src contains no @/… imports that couldn't resolve outside the app.
  • Dependency hygiene. Every third-party import inside web-core/src (@chatsift/core, discord-api-types, react-aria-components, usehooks-ts, @radix-ui/*, react-icons, clsx, tailwind-merge) is a declared dependency; React/Next/jotai/Sentry/react-query are correctly peerDependencies (+ dev for typechecking), which is what keeps single instances under transpilePackages.
  • Build-system reasoning is sound and well-justified in comments. transpilePackages (to keep per-file 'use client' boundaries and keep next/headers out of the client graph), .dockerignore excluding a React-only package the service images never build, noEmit typecheck-only build, and the bare-string CSS @import requirement are all correct and explained.

Notes (all minor, none blocking)

  1. Font-sync vs next start — flagged inline on apps/website/package.json. build/dev re-sync the gitignored fonts but start doesn't; just verify the website's deploy carries the synced public/assets/fonts/ (Next standalone doesn't copy public/ automatically), since a missing @font-face src fails silently.
  2. Package scope vs. Next couplingweb-core is described as the substrate for every app in apps/, yet api/fetch.ts dynamically imports next/headers and api/report.ts pulls @sentry/nextjs, so any future apps/* is effectively pinned to Next. That's consistent with the repo's YAGNI stance (one app today), so it's an observation, not a request to abstract now.
  3. Stale wording in a moved commentweb-core/src/api/queryClient.ts:54 still reads "The app's first MutationCache". Verbatim-correct when it lived in the app; now that it's package-level, "the app's" reads slightly off. Trivial.
  4. Doc alignment — the CLAUDE.md frontend section was updated (Button path, theme.css location, split component locations). Worth confirming docs/frontend.md itself got the same treatment, since it's the linked source of truth for those conventions and isn't in this diff.

Nice work — the comment culture (issue-referencing "why" comments) and the silent-failure guardrails carried through the move intact. Nothing here blocks merge from a static-review standpoint; the remaining gate is a green yarn build/lint/test/format:check in CI.
· refactor/web-core

Comment thread apps/website/package.json Outdated
"dev": "next dev",
"build": "node ../../scripts/sync-web-core-assets.mjs website && next build",
"dev": "node ../../scripts/sync-web-core-assets.mjs website && next dev",
"start": "next start",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Minor / deployment consideration: build and dev re-run sync-web-core-assets.mjs, but start does not. Since the synced public/assets/fonts/ is gitignored and only produced by that script, next start relies on public/ having been populated by a prior build in the same working tree. That holds for the normal build && start flow, but is worth double-checking against the website's actual deploy: Next's standalone output does not automatically copy public/, so if the deploy artifact is assembled from a fresh checkout (where the sync never ran) the @font-face bytes will 404 — and per the script's own comment, a missing font src fails silently by falling back down the stack. Not a bug in this PR, just flagging the coupling so the deploy step is verified to carry the synced fonts.

@didinele
didinele merged commit 114fc09 into main Sep 8, 2026
1 check was pending
@didinele
didinele deleted the refactor/web-core branch September 8, 2026 11:11
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown

Claude finished @didinele's task in 1m 59s —— View job


Review: extract the shared frontend substrate (@chatsift/web-core)

  • Gather context (new package, non-trivial moves)
  • Review correctness / edge cases
  • Review conventions (CLAUDE.md, frontend.md)
  • Review security & performance
  • Post feedback

Re-reviewed after the latest push. This remains a large but overwhelmingly mechanical and clean extraction: the vast majority of files are pure import-path swaps (@/components/common/*, @/api/*@chatsift/web-core/*), and the genuinely new surface (the web-core package) is small, careful, and heavily "why"-commented in the house style. I verified the moving parts statically against the working tree; I couldn't run yarn build/lint/test (yarn install isn't pre-approved for this job), so a green CI run remains the final gate.

Previously-flagged item is now resolved

  • Font-sync on start. The earlier round flagged that start didn't re-run sync-web-core-assets.mjs while build/dev did. apps/website/package.json:10 now reads node ../../scripts/sync-web-core-assets.mjs website && next start, so all three entrypoints regenerate the gitignored public/assets/fonts/, and the script's own comment (build, dev and start) is now accurate. The one residual coupling to keep in mind is the script's own note: if any app ever sets output: 'standalone', public/ isn't copied into the output and the deploy step would have to carry the synced fonts itself.

What I verified consistent

  • queryClient split is faithful. makeQueryClient preserves the #386 "report once before branching" ordering, the 401 / background-refetch / banner branches, the retry policy, and the reporting-only MutationCache. The app-specific me-nulling correctly moved behind the new onUnauthorized callback (apps/website/src/api/queryClient.ts:26-40), the browser-singleton-vs-SSR-throwaway behaviour is unchanged, and onUnauthorized still excludes the auth key so it can't recurse.
  • Single jotai store, no desync. accessTokenAtom now lives in web-core/api/token and is read/written only through the shared web-core/api/store singleton; the app keeps only the dashboard-specific lastExplicitLogoutAtAtom. No duplicate accessTokenAtom survives in the app (only a doc-comment reference).
  • No dangling imports. Remaining @/components/common/* references resolve to the 14 session/guild-coupled components that intentionally stayed in the app (ChannelSelect, RoleSelect, NavGate, …); remaining @/api/queryClient references resolve to the app-local queryKeys. Nothing points at a moved module.
  • Dependency hygiene / bundling. React/Next/jotai/Sentry/react-query are peerDependencies (plus dev for typecheck), which is what keeps single instances under transpilePackages; every other third-party import in web-core/src is a declared dependency. The exports map handles the .ts outlier (./components/buttonStyles) explicitly before the ./components/**.tsx wildcard, and next/headers / @tanstack/react-query stay behind dynamic imports in fetch.ts so the SSR branch never enters the client graph.

Minor (non-blocking)

  1. Stale wording in a moved commentpackages/private/web-core/src/api/queryClient.ts:54 still says "The app's first MutationCache"; verbatim-correct in the app, slightly off now that it's package-level. Left an inline suggestion. Fix this →
  2. Package scope vs. Next couplingweb-core is billed as the substrate for every apps/*, yet api/fetch.ts dynamically imports next/headers and api/report.ts pulls @sentry/nextjs, so any future app is effectively pinned to Next. Consistent with the repo's YAGNI stance (one app today) — an observation, not a request to abstract now.
  3. Doc alignment — CLAUDE.md's frontend section was updated in this PR; docs/frontend.md is the linked source of truth for the same conventions, so worth confirming it carries the same web-core paths.

Nice work — the issue-referencing "why" comments and the silent-failure guardrails carried through the move intact. Nothing here blocks from a static-review standpoint; the remaining gate is a green yarn build/lint/test/format:check in CI.
· refactor/web-core

}
},
}),
// The app's first `MutationCache`, and deliberately reporting-only: no banner, no toast, no UX change

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Trivial: this comment moved verbatim from the app, so "The app's first MutationCache" now reads slightly off at package level -- it's the substrate's, shared by every app. Consider rewording.

Suggested change
// The app's first `MutationCache`, and deliberately reporting-only: no banner, no toast, no UX change
// The single `MutationCache` shared by every app, and deliberately reporting-only: no banner, no toast, no
// UX change at all. `Button`'s catch and each form's own field-level errors already own the user-facing
// half, and adding a second surface here would double up on every form that already handles its own failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant