Skip to content

feat: switch to @bitsocial/bitsocial-react-hooks 0.1.2 and rebrand subplebbit → community#816

Merged
tomcasaburi merged 5 commits intomasterfrom
codex/feature/community-rebrand
Apr 27, 2026
Merged

feat: switch to @bitsocial/bitsocial-react-hooks 0.1.2 and rebrand subplebbit → community#816
tomcasaburi merged 5 commits intomasterfrom
codex/feature/community-rebrand

Conversation

@tomcasaburi
Copy link
Copy Markdown
Member

@tomcasaburi tomcasaburi commented Apr 27, 2026

Summary

The big rebrand. Brings seedit on par with 5chan on the bitsocial-react-hooks package and the community terminology.

Package upgrades

  • Switch from @bitsocialnet/bitsocial-react-hooks (tarball install) to @bitsocial/bitsocial-react-hooks@0.1.2 (npm published, pinned).
  • Drop direct kubo dependency — kubo is now bundled by pkc-js inside the hooks package; seedit doesn't install it separately anymore.
  • Bump i18next 23 → 25, react-i18next 13 → 16, i18next-http-backend 2 → 3, @vitejs/plugin-react 4 → 6 to match 5chan exactly.
  • Remove the obsolete scripts/patch-bitsocial-react-hooks-esm.cjs postinstall hook (it was patching the old tarball layout).
  • Drop src/lib/bitsocial-react-hooks-compat.ts — that compat layer existed to expose useCommunity etc. on top of the legacy @bitsocialnet package; no longer needed since @bitsocial exposes them natively.

API surface rename (matching the new package)

  • SubplebbitCommunity
  • useSubplebbituseCommunity, useSubplebbitsuseCommunities
  • useSubplebbitStatsuseCommunityStats, useSubplebbitsStatesuseCommunitiesStates
  • useAccountSubplebbitsuseAccountCommunities
  • usePublishSubplebbitEditusePublishCommunityEdit, PublishSubplebbitEditOptionsPublishCommunityEditOptions
  • usePlebbitRpcSettingsusePkcRpcSettings
  • useAuthorAddressuseResolvedAuthorAddress

File / directory renames (git mv)

  • src/views/subplebbit/src/views/community/
  • src/views/subplebbits/src/views/communities/
  • src/views/subplebbit-settings/src/views/community-settings/
  • src/views/community-settings/subplebbit-data-editor/src/views/community-settings/community-data-editor/
  • src/stores/use-subplebbit-offline-store.tsuse-community-offline-store.ts
  • src/stores/use-subplebbit-settings-store.tsuse-community-settings-store.ts
  • src/stores/use-subplebbits-loading-start-timestamps-store.tsuse-communities-loading-start-timestamps-store.ts
  • src/hooks/use-is-subplebbit-offline.tsuse-is-community-offline.ts
  • src/hooks/use-is-nsfw-subplebbit.tsuse-is-nsfw-community.ts
  • src/hooks/use-is-broadly-nsfw-subplebbit.tsuse-is-broadly-nsfw-community.ts

Routing

  • Rename React Router param :subplebbitAddress:communityAddress (path prefix /s/ unchanged — already in place).
  • Update every useParams<{ subplebbitAddress?: string }> callsite.

Helpers

  • Add src/lib/utils/comment-utils.ts with getCommentCommunityAddress(comment) (ported from 5chan) for safe extraction of the community address from a Comment object regardless of whether the protocol returns subplebbitAddress or communityAddress.
  • Add src/hooks/use-community-identifier.ts adapting the new CommunityIdentifier shape ({ name } or { publicKey }).
  • Extract src/lib/utils/address-utils.ts for the short-address helper.

i18n

  • Update English translation values for community-related strings (subplebbit_offline_info, posts_last_synced_info, etc.).
  • Other locales' English-key references unchanged; values can be retranslated in a follow-up via the translate skill.

Commit chain (4 commits, reviewable independently)

c5cb66ec refactor: rename subplebbit → community throughout UI layer
309c553c refactor: rename subplebbit -> community across seedit
8d017a1a refactor: switch import scope from @bitsocialnet to @bitsocial
c8ce0c83 chore(deps): switch to @bitsocial/bitsocial-react-hooks@0.1.2

Stats

103 files changed, +1583 / −3310.

Sibling-PR coordination

This PR was opened alongside three Phase-1 PRs:

Deferred cleanup (follow-up PR welcome)

The functional rebrand is complete; build/lint/type-check all pass. A few cosmetic items remain that I left out to keep this PR's diff manageable:

  1. ~22 files still do direct `comment.subplebbitAddress` property reads instead of going through `getCommentCommunityAddress(comment)`. Both work correctly at runtime (Comment is typed as `{ [key: string]: any }` in the new package), but the helper pattern matches 5chan and is more robust to future protocol field renames.
  2. CSS class `.parentSubplebbit` in `src/components/reply/reply.module.css` (still consumed in `reply.tsx`) — not yet renamed to `.parentCommunity`.
  3. Some local store output payloads (`use-publish-post-store.ts`, `use-publish-reply-store.ts`) still write `{ subplebbitAddress: ... }` when handing off to the protocol — those should stay until pkc-js confirms the canonical publish-payload key.

Test plan

  • `corepack yarn install` succeeds with the new lockfile.
  • `yarn build` passes (Vite production build with no warnings except pre-existing electron lint).
  • `yarn lint` passes (1 pre-existing electron warning, 0 errors).
  • `yarn type-check` passes cleanly (tsgo exit 0).
  • Manual: open the home/all/community/community-settings views and confirm they render.
  • Manual: subscribe / unsubscribe to a community and confirm the action lands.
  • Manual: post + reply happy paths end-to-end.
  • Manual: confirm desktop electron build is unaffected (kubo is no longer a direct dep, but pkc-js bundles it).

Note

Medium Risk
Wide mechanical renames (routes/params, hooks, and data field mapping) plus dependency upgrades can cause subtle runtime navigation/data-loading regressions despite being conceptually straightforward.

Overview
Switches the app from the tarball-based @bitsocialnet/bitsocial-react-hooks to the published @bitsocial/bitsocial-react-hooks@0.1.2, along with related dependency bumps (i18n packages, @vitejs/plugin-react) and removal of the now-unneeded postinstall ESM patch script and the in-repo hooks compat layer.

Rebrands UI and routing from subplebbit to community end-to-end: route params change to :communityAddress, views/components/hooks are updated to useCommunity/useCommunities/useCommunityStats/usePkcRpcSettings, and copy/labels are updated accordingly.

Adds small adapters to bridge protocol/API differences (getCommentCommunityAddress, getCommunityIdentifier(s), getShortAddress) and updates NSFW/offline/status logic to operate on communities while remaining tolerant of legacy subplebbitAddress fields.

Reviewed by Cursor Bugbot for commit c5348a0. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Introduced community-based routing and data management across the application.
  • Bug Fixes

    • Updated offline status messaging to refer to communities instead of subplebbits.
  • Refactor

    • Migrated application terminology from "subplebbit" to "community" throughout UI and routing.
    • Updated RPC settings integration and removed legacy ESM patching.
  • Dependencies

    • Updated i18n libraries (i18next, react-i18next) to latest versions.
    • Updated React Vite plugin and package dependencies.
    • Removed kubo dependency.

- Drop the @bitsocialnet/bitsocial-react-hooks tarball install in favor
  of the canonical @bitsocial/bitsocial-react-hooks@0.1.2 from npm.
- Remove kubo direct dep (now bundled inside pkc-js via the hooks).
- Bump i18next 23 -> 25, react-i18next 13 -> 16,
  i18next-http-backend 2 -> 3, @vitejs/plugin-react 4 -> 6 to
  match 5chan.
- Remove the obsolete scripts/patch-bitsocial-react-hooks-esm.cjs
  postinstall hook (only patched the old tarball layout).
- Update AGENTS.md package scope reference.
Mechanical scope rename across src/. Build is intentionally broken
at this commit — Phase 3 renames the symbols (useSubplebbit ->
useCommunity, etc.) to match the new package's API.
Apply the broader subplebbit -> community rebrand on top of the
package switch:

- Rename hook usages (useSubplebbit -> useCommunity, useSubplebbits
  -> useCommunities, useSubplebbitStats -> useCommunityStats,
  useSubplebbitsStates -> useCommunitiesStates,
  useAccountSubplebbits -> useAccountCommunities,
  usePublishSubplebbitEdit -> usePublishCommunityEdit,
  usePlebbitRpcSettings -> usePkcRpcSettings) and types (Subplebbit
  -> Community, PublishSubplebbitEditOptions ->
  PublishCommunityEditOptions).
- Rename seedit identifiers (variables, types, store names) from
  subplebbit/Subplebbit to community/Community.
- git mv view directories, store files, hook files, and CSS modules
  from subplebbit-* to community-*. Update all imports.
- Rename the React Router :subplebbitAddress route param to
  :communityAddress (path /s/ unchanged).
- Update English translation values for community-related strings.
- Drop src/lib/bitsocial-react-hooks-compat.ts (no longer needed
  now that @bitsocial/bitsocial-react-hooks exposes the community
  names natively).
- Add src/hooks/use-community-identifier.ts and
  src/lib/utils/address-utils.ts as small adapters for the new
  CommunityIdentifier shape and short-address utility.
- Fix src/hooks/use-default-subplebbits.ts to import Community
  instead of Subplebbit (PR #813 will rename the file in a
  follow-up; tiny merge conflict expected on that one file).

Build, lint, and type-check all pass.
Cosmetic rename of local variables, prop names, type names, CSS classes,
function names, and code comments from the legacy `subplebbit` terminology
to `community` across components, hooks, stores, views, and utilities.

API protocol keys (e.g. `subplebbitAddress:` in publish options) are
intentionally preserved. A new `getCommentCommunityAddress` dual-read
helper in `comment-utils.ts` reads `communityAddress` first and falls
back to the legacy `subplebbitAddress` field for backward compat.

Renamed hook files:
- use-is-nsfw-subplebbit.ts → use-is-nsfw-community.ts
- use-is-broadly-nsfw-subplebbit.ts → use-is-broadly-nsfw-community.ts
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

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

Project Deployment Actions Updated (UTC)
seedit Ready Ready Preview, Comment Apr 27, 2026 11:53am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

This pull request systematically migrates the application's terminology and APIs from "subplebbit" to "community" semantics, updates the React hooks library package from @bitsocialnet/bitsocial-react-hooks to @bitsocial/bitsocial-react-hooks, and refactors the RPC settings integration from Plebbit-specific to PKC-specific hooks. The changes span components, hooks, stores, views, utilities, and routing throughout the codebase.

Changes

Cohort / File(s) Summary
Package & Dependency Updates
package.json, AGENTS.md, src/AGENTS.md
Updated package reference from @bitsocialnet/bitsocial-react-hooks to @bitsocial/bitsocial-react-hooks (version 0.1.2); upgraded i18n libraries and React Vite plugin; removed kubo dependency and postinstall patch script.
Translation & Documentation
public/translations/en/default.json
Changed user-facing text from "subplebbit" to "community" in offline/sync info messages.
Build & Patch Scripts
scripts/patch-bitsocial-react-hooks-esm.cjs
Deleted legacy ESM patching script for old package namespace.
Utility Functions
src/lib/utils/address-utils.ts, src/lib/utils/comment-utils.ts
Added getShortAddress() helper for address formatting; added getCommentCommunityAddress() to extract community address from comment objects.
Hook Library Consolidation
src/lib/bitsocial-react-hooks-compat.ts
Deleted compatibility layer that provided subplebbit-semantics wrappers; applications now use underlying package directly.
Community Hooks (New)
src/hooks/use-community-identifier.ts, src/hooks/use-is-broadly-nsfw-community.ts, src/hooks/use-is-community-offline.ts, src/hooks/use-is-nsfw-community.ts
New hooks for community-based data access, NSFW detection, and offline state tracking.
Subplebbit Hooks (Deleted)
src/hooks/use-is-broadly-nsfw-subplebbit.ts, src/hooks/use-is-nsfw-subplebbit.ts, src/hooks/use-is-subplebbit-offline.ts
Removed subplebbit-specific hooks; functionality migrated to community equivalents.
Hook Updates
src/hooks/use-*.ts (19 files)
Updated hook imports from old package namespace; renamed parameters/internal variables from subplebbitAddress to communityAddress and related terminology shifts across vote, reply, state, and time-filter hooks.
Store Updates
src/stores/use-community-offline-store.ts, src/stores/use-community-settings-store.ts, src/stores/use-communities-loading-start-timestamps-store.ts
New community-focused stores for offline state, settings persistence, and loading timestamps.
Store Deletions
src/stores/use-subplebbit-offline-store.ts, src/stores/use-subplebbits-loading-start-timestamps-store.ts
Removed subplebbit-specific stores; functionality replaced by community equivalents.
Store Migrations
src/stores/use-publish-post-store.ts, src/stores/use-publish-reply-store.ts
Updated to derive community address via utility function instead of direct field access.
RPC Settings Integration
src/hooks/use-challenge-settings.ts, src/hooks/use-challenges-options.ts, src/views/settings/plebbit-options/plebbit-options.tsx
Migrated from usePlebbitRpcSettings to usePkcRpcSettings for challenge and RPC configuration.
View Utilities
src/lib/utils/view-utils.ts
Renamed all view-detection functions from isSubplebbit* to isCommunity* and updated ViewType enum; changed route params from subplebbitAddress to communityAddress.
Pattern & Permission Utilities
src/lib/utils/pattern-utils.ts, src/lib/utils/user-utils.ts, src/lib/utils/url-utils.ts, src/lib/utils/nsfw-subscription-utils.ts
Refactored role/permission logic, community creation/author lookup, URL sharing, and NSFW subscription handling to use community-based APIs and naming; added getShortAddress for address display.
Component Imports
src/components/account-bar/account-bar.tsx, src/components/challenge-modal/challenge-modal.tsx, src/components/notification-handler/notification-handler.tsx, src/components/post/comment-tools/edit-menu/edit-menu.tsx, src/components/post/comment-tools/mod-menu/mod-menu.tsx, src/components/post/comment-tools/hide-menu/hide-menu.tsx, src/components/sidebar/sidebar.tsx, and 8+ others
Updated React hooks imports from old package namespace to new; no logic changes.
Post/Comment Components
src/components/post/post.tsx, src/components/post/post.module.css, src/components/post/thumbnail/thumbnail.tsx, src/components/post/comment-tools/comment-tools.tsx, src/components/post/expando/expando.tsx
Migrated from useSubplebbit/NSFW subplebbit hooks to useCommunity/community-NSFW equivalents; updated routing and component props from subplebbitAddress to communityAddress; renamed CSS classes from .subplebbit* to .community*.
Reply & Comment Components
src/components/reply-form/reply-form.tsx, src/components/reply/reply.tsx
Updated props and hooks to use communityAddress instead of subplebbitAddress; switched from subplebbit offline detection to community equivalent.
Feed & Navigation Components
src/components/header/header.tsx, src/components/search-bar/search-bar.tsx, src/components/topbar/topbar.tsx, src/components/feed-footer/feed-footer.tsx
Migrated view detection and routing from isSubplebbit*/params.subplebbitAddress to isCommunity*/params.communityAddress; replaced Plebbit.getShortAddress with local utility; updated hook dependencies to use community hooks.
Sidebar & Subscribe Components
src/components/sidebar/sidebar.tsx, src/components/sidebar/sidebar.module.css, src/components/subscribe-button/subscribe-button.tsx, src/components/author-sidebar/author-sidebar.tsx
Updated stats/offline/RPC hooks from subplebbit to community equivalents; renamed CSS margin class; migrated to useCommunity for role lookup and community listing; switched address formatting to getShortAddress.
Router Configuration
src/app.tsx
Updated route definitions and imported components from Subplebbit* to Community* variants; changed route params from :subplebbitAddress to :communityAddress.
View Components (Communities)
src/views/communities/communities.tsx, src/views/communities/communities.module.css, src/views/communities/index.ts
Renamed from Subplebbits to Communities; migrated hooks from useAccountSubplebbits/useSubplebbits to useAccountCommunities/useCommunities; updated stats/offline to community equivalents; added barrel index.ts; CSS class renames from .subplebbit* to .community*.
View Components (Community Settings)
src/views/community-settings/... (3 files), src/views/community-settings/index.ts
Renamed from SubplebbitSettings to CommunitySettings; migrated to useCommunitySettingsStore and community edit/create hooks; updated route params and navigation paths; added barrel index.ts; swapped to usePkcRpcSettings.
View Components (Community)
src/views/community/community.tsx, src/views/community/index.ts
Renamed from Subplebbit to CommunityView; migrated from useSubplebbit to useCommunity and related offline/NSFW hooks; updated routing and downstream props; added barrel index.ts.
Feed Views
src/views/all/all.tsx, src/views/domain/domain.tsx, src/views/home/home.tsx, src/views/mod/mod.tsx
Updated useFeed options from subplebbitAddresses to communities with getCommunityIdentifiers() conversion; renamed result fields to community-based equivalents; updated footer props.
Post Page
src/views/post-page/post-page.tsx
Migrated from useSubplebbit to useCommunity; updated route params, sidebar, and NSFW/Over18 logic to community-based detection; changed ReplyForm prop from subplebbitAddress to communityAddress.
Submit Page
src/views/submit-page/submit-page.tsx
Renamed component/input from SubplebbitAddressField to CommunityAddressField; migrated from useSubplebbit/useIsSubplebbitOffline to useCommunity/useIsCommunityOffline; updated store field naming and routing logic.
Settings Views
src/views/settings/account-settings/account-settings.tsx, src/views/settings/avatar-settings/avatar-settings.tsx, src/views/settings/address-settings/address-settings.tsx, src/views/settings/account-data-editor/account-data-editor.tsx, src/views/settings/wallet-settings/wallet-settings.tsx, src/views/settings/content-options/content-options.tsx, src/views/settings/plebbit-options/plebbit-options.tsx, src/views/settings/settings.tsx
Updated hook imports from old package namespace; migrated RPC settings hook in plebbit-options; updated NSFW subscription prompt to pass defaultCommunities instead of defaultSubplebbits.
Other Views
src/views/author/author.tsx, src/views/profile/profile.tsx, src/views/inbox/inbox.tsx
Updated hook imports from old package namespace; swapped getCommentCommunityAddress() for direct field access in profile view.
Deleted Index Files
src/views/subplebbit-settings/index.ts, src/views/subplebbit-settings/subplebbit-data-editor/index.ts, src/views/subplebbit/index.ts, src/views/subplebbits/index.ts
Removed old barrel exports that pointed to deleted/renamed subplebbit view components.
Test Files
src/lib/utils/account-history-utils.test.ts
Updated Comment type import from old to new package namespace.
Media & Challenge Utilities
src/lib/utils/cid-utils.ts, src/lib/utils/media-utils.ts, src/lib/utils/challenge-utils.ts
Updated type imports from old package namespace to new package.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 From subplebbits to communities, the refactoring hops,
Every import and hook gets a fresh rename,
Package namespaces dance, terminology swaps,
A systematic shift through the entire domain,
Semantics reborn, the codebase transforms with grace!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: upgrading the React hooks package and rebranding subplebbit to community terminology throughout the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/feature/community-rebrand

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 and usage tips.

Comment thread src/components/post/post.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/views/settings/avatar-settings/avatar-settings.tsx (1)

150-157: ⚠️ Potential issue | 🟡 Minor

Update stale help URL that still references the old bitsocialnet repository.

This PR rebrands the package from @bitsocialnet/bitsocial-react-hooks to @bitsocial/bitsocial-react-hooks, but the user-facing "token address whitelist" help link at line 153 still points to github.com/bitsocialnet/bitsocial-react-hooks/blob/dcfaeac... and references a pinned commit that predates version 0.1.2 (the current installed version). The line numbers and behavior users read from that link may diverge from what the app actually does.

Update the to= URL to reference the equivalent file in the new @bitsocial repository at the corresponding 0.1.2 tag/commit, point to a stable docs URL, or remove the deep link if the new repository doesn't ship that exact path.

(Side note: react-router-dom's Link is for internal navigation; for external https:// URLs, use <a target="_blank" rel="noopener noreferrer"> instead. This can be addressed separately.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/settings/avatar-settings/avatar-settings.tsx` around lines 150 -
157, The tokenAddressWhitelist help link currently uses a stale external GitHub
URL in the Link with key 'tokenAddressWhitelistLink' and
to='https://github.com/bitsocialnet/...', so update the to= value to point to
the correct `@bitsocial` repository and stable reference (e.g., the file path in
the `@bitsocial/bitsocial-react-hooks` repo at the v0.1.2 tag or a stable docs
page) or remove the deep link if the file no longer exists; locate the JSX
element named Link with key 'tokenAddressWhitelistLink' in avatar-settings.tsx
and replace the to prop accordingly (consider switching to an external <a> tag
for https:// links in a follow-up change as noted).
src/views/submit-page/submit-page.tsx (1)

330-405: 🛠️ Refactor suggestion | 🟠 Major

Drop the as any casts on setPublishPostStore({ communityAddress }).

Five call sites cast the setter argument with as any (lines 330, 347, 383, 405, 473), yet communityAddress is destructured directly from the store on line 311 — so the field is part of the store type. The casts either silence a stale setter-parameter type or are unnecessary. Either way they hide future regressions in field names. Update the store/setter types so the casts can be removed.

♻️ Example follow-up after store typing is fixed
-          setPublishPostStore({ communityAddress: e.target.value } as any);
+          setPublishPostStore({ communityAddress: e.target.value });

(apply to all five sites)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/submit-page/submit-page.tsx` around lines 330 - 405, The calls to
setPublishPostStore are being cast with "as any" (e.g. in the input onChange,
handleCommunitySelect, list item click handlers) which hides type errors; remove
these casts and fix the PublishPost store/setter types so a value like {
communityAddress: string } is accepted directly by setPublishPostStore. Update
the store interface (the type used by setPublishPostStore) to include
communityAddress (matching where inputAddress is read) or adjust the setter's
parameter type so you can call setPublishPostStore({ communityAddress }) without
"as any", then remove the five "as any" casts in functions such as
handleCommunitySelect and the input onChange/list item click handlers.
src/components/post/post.tsx (1)

249-265: ⚠️ Potential issue | 🟡 Minor

Guard against undefined in templated community links.

When communityAddress is falsy (post not yet loaded, or comment lacks both communityAddress and subplebbitAddress), the rendered URLs become literal /s/undefined, /s/undefined/c/<cid>, and the “self.undefined” label. Worth either gating the title/domain link block on communityAddress, or short-circuiting in the JSX.

🛡️ Minimal guard
-          <Link className={linkClass} to={cid ? `/s/${communityAddress}/c/${cid}` : `/profile/${post?.index}`} onClick={handlePostClick}>
+          <Link
+            className={linkClass}
+            to={cid && communityAddress ? `/s/${communityAddress}/c/${cid}` : `/profile/${post?.index}`}
+            onClick={handlePostClick}
+          >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/post/post.tsx` around lines 249 - 265, The title/domain link
code can render "/s/undefined" when communityAddress is falsy; update the JSX
around the Link usage (references: communityAddress, Link,
community?.shortAddress, getShortAddress, hostname, displayedTitle) to guard or
short-circuit: only render the community-based Links when communityAddress (or a
derived fallback) is truthy, otherwise render a safe fallback (e.g., no link, a
placeholder label, or omit the "/s/..." parts) so URLs never contain
"undefined"; ensure both the title Link and the domain self-link use the same
guard and fallbacks to avoid inconsistent rendering.
src/views/community-settings/community-data-editor/community-data-editor.tsx (1)

165-197: ⚠️ Potential issue | 🟡 Minor

Post-publish error check reads a stale publishCommunityEditError.

After await publishSubplebbitEdit(), the if (publishCommunityEditError) branch evaluates the value captured at effect creation, not the value produced by this publish. Combined with the eslint-disable react-hooks/exhaustive-deps and the [triggerSave]-only dep array, errors from the in-flight publish typically won't surface until a subsequent re-render triggers another save. This pre-dates the rebrand, but flagging since the surrounding flow was rewritten.

Consider returning a result from publishCommunityEdit() (or catching synchronously) and surfacing that locally rather than reading the hook's error field across the await boundary.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-data-editor/community-data-editor.tsx`
around lines 165 - 197, The effect reads the stale publishCommunityEditError
after awaiting publishSubplebbitEdit(), so surface the publish outcome locally
instead of relying on the hook's error field captured when the effect was
created: make publishSubplebbitEdit (or the underlying publishCommunityEdit)
return a success/failure result or throw an Error, then in the useEffect's
performSave await that result and handle errors from the returned value or catch
(calling setCurrentError, showing alerts, setShowSaving, setTriggerSave
accordingly) rather than checking publishCommunityEditError; update the effect
to use the publishSubplebbitEdit return/throw to determine success/failure and
remove the stale publishCommunityEditError check.
🧹 Nitpick comments (24)
src/components/subscribe-button/subscribe-button.tsx (1)

20-20: Nit: stale subplebbit* identifier left behind.

The local subplebbitPageString is now inconsistent with the PR-wide rename. Renaming it to communityPageString keeps the file aligned with the new terminology (and matches the deferred-cleanup intent in the PR description).

♻️ Proposed rename
-  const subplebbitPageString = subscribed ? `${t('leave')}` : `${t('join')}`;
+  const communityPageString = subscribed ? `${t('leave')}` : `${t('join')}`;
@@
-      {isInAuthorView ? authorPageString : subplebbitPageString}
+      {isInAuthorView ? authorPageString : communityPageString}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/subscribe-button/subscribe-button.tsx` at line 20, Rename the
stale local variable subplebbitPageString to communityPageString to match the
PR-wide terminology; update its declaration (currently: const
subplebbitPageString = subscribed ? `${t('leave')}` : `${t('join')}`) and every
usage site to use communityPageString instead, leaving the conditional logic and
calls to subscribed and t(...) unchanged.
src/lib/utils/account-history-utils.ts (1)

27-42: Reuse getCommentCommunityAddress and fix inverted fallback order.

The PR introduces getCommentCommunityAddress(comment) in src/lib/utils/comment-utils.ts which reads communityAddress first and falls back to subplebbitAddress. Line 30 here does the opposite (subplebbitAddress || communityAddress), which is inconsistent with the rebrand direction and also duplicates a helper that already exists. For comments that carry both fields it will deterministically prefer the legacy field, defeating the migration on this filter path.

♻️ Proposed fix
-import { type Comment } from '@bitsocial/bitsocial-react-hooks';
+import { type Comment } from '@bitsocial/bitsocial-react-hooks';
+import { getCommentCommunityAddress } from './comment-utils';
@@
 export const filterOptimisticLocalPosts = (accountComments: Comment[], feed: Comment[], subplebbitAddress: string, nowSeconds = Date.now() / 1000): Comment[] =>
   accountComments.filter((comment) => {
     const { cid, deleted, postCid, removed, state, timestamp } = comment || {};
-    const commentCommunityAddress = comment?.subplebbitAddress || comment?.communityAddress;
+    const commentCommunityAddress = getCommentCommunityAddress(comment);

While here, consider also renaming the subplebbitAddress parameter to communityAddress for consistency with the rest of the rebrand (callers can be migrated in a follow-up).

As per coding guidelines: "Follow DRY: shared UI in src/components/, shared logic in src/hooks/."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/account-history-utils.ts` around lines 27 - 42, The
filterOptimisticLocalPosts function currently computes commentCommunityAddress
using the legacy-first order (comment?.subplebbitAddress ||
comment?.communityAddress) and duplicates logic from getCommentCommunityAddress;
change filterOptimisticLocalPosts to call getCommentCommunityAddress(comment)
instead of the inline expression so the canonical communityAddress-first
fallback is used, and optionally rename the function parameter subplebbitAddress
to communityAddress for consistency with the rebrand (callers can be migrated
later).
src/hooks/use-default-subplebbits.ts (1)

112-112: Misleading type annotation: parameter is a MultisubSubplebbit, not a Community.

defaultSubplebbits is typed MultisubSubplebbit[] (via useDefaultSubplebbitsuseState<MultisubSubplebbit[]> on line 73). Annotating the filter callback parameter as Community from @bitsocial/bitsocial-react-hooks masks the actual shape (which carries multisub-specific fields like lowUptime, seeditAutoSubscribe) and will hide future regressions if Community and MultisubSubplebbit diverge. Drop the annotation (it's already inferred) or use the local type.

♻️ Proposed change
-    return defaultSubplebbits.filter((subplebbit: Community) => {
+    return defaultSubplebbits.filter((subplebbit) => {

Then the unused Community import on line 2 can be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/use-default-subplebbits.ts` at line 112, The filter callback
incorrectly annotates its parameter as Community while defaultSubplebbits is an
array of MultisubSubplebbit (set in useDefaultSubplebbits →
useState<MultisubSubplebbit[]>); update the filter to use the correct type or
remove the explicit annotation so TypeScript infers MultisubSubplebbit, and then
remove the now-unused Community import from the top of the file to avoid
misleading types and dead imports.
public/translations/en/default.json (1)

296-297: Key names still use subplebbit_ prefix while values now say "community".

The translation values were updated, but the keys subplebbit_offline_info and posts_last_synced_info (and adjacent cross-references like settings_saved with {{subplebbitAddress}} and challenge_from with {{subplebbit}}) still carry the legacy naming. Renaming the keys (and their callsites) to community_offline_info etc. would keep the locale file consistent with the rest of the rebrand. Deferring is fine if it's part of the noted follow-up cleanup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/translations/en/default.json` around lines 296 - 297, Rename legacy
translation keys that use the subplebbit_ prefix to community_* and update their
callsites: change "subplebbit_offline_info" -> "community_offline_info", update
"posts_last_synced_info" if it embeds subplebbit naming to match (e.g., ensure
key and interpolation use community naming), and also search for and rename
related keys/variables like settings_saved ({{subplebbitAddress}}) and
challenge_from ({{subplebbit}}) to use communityAddress/community as
appropriate; after renaming keys in public/translations/en/default.json, update
all code references (components, templates, and i18n lookups) to use the new key
names and adjusted interpolation variable names so translations continue to
resolve correctly.
src/hooks/use-is-nsfw-community.ts (1)

11-11: Nit: rename inner sub parameter for terminology consistency.

The rest of the rebrand uses community; the lambda parameter name still leaks the old vocabulary.

♻️ Suggested rename
-    const community = defaultCommunities.find((sub) => sub.address === communityAddress);
+    const community = defaultCommunities.find((c) => c.address === communityAddress);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/use-is-nsfw-community.ts` at line 11, The lambda parameter name
`sub` in the find call should be renamed for terminology consistency; update the
arrow function passed to defaultCommunities.find so it uses a clearer name
(e.g., `community`) instead of `sub` when comparing `.address` to
`communityAddress` (affecting the expression that assigns `community` from
`defaultCommunities.find`).
src/components/author-sidebar/author-sidebar.tsx (1)

77-88: Optional: drop the redundant Object.values(...).

communities is already an array (built via .communities?.filter(Boolean) || [] on line 81), so Object.values(communities) on line 88 just returns the same array. You can pass communities directly.

♻️ Proposed simplification
-  const authorCommunities = findAuthorCommunities(authorAddress, Object.values(communities));
+  const authorCommunities = findAuthorCommunities(authorAddress, communities);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/author-sidebar/author-sidebar.tsx` around lines 77 - 88, The
code passes Object.values(communities) into findAuthorCommunities even though
communities is already an array; update the call to
findAuthorCommunities(authorAddress, communities) to remove the redundant
Object.values(...) usage (locate where communities is created via useCommunities
and where authorCommunities is assigned) so findAuthorCommunities receives the
array directly.
src/components/notification-handler/notification-handler.tsx (1)

4-4: Deep dist/ import is fragile across package versions.

Importing from @bitsocial/bitsocial-react-hooks/dist/lib/localforage-lru/index.js reaches into the package's build output and bypasses its public exports map. The upstream package does not currently expose localForageLru via a stable subpath. Any internal restructure in a future patch release (file move, ESM/CJS layout change, exports field tightening) will silently break this import at runtime.

This pattern appears in at least 3 other files (src/lib/utils/media-utils.ts, src/hooks/use-fetch-gif-first-frame.ts, src/components/reply/reply.tsx), making it a systemic concern. Consider addressing all instances together by either:

  • requesting the upstream package to re-export localForageLru from a stable subpath (e.g., @bitsocial/bitsocial-react-hooks/localforage-lru), or
  • extracting a local storage abstraction layer across affected files so they do not depend on vendored paths.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/notification-handler/notification-handler.tsx` at line 4, The
deep import of localForageLru ("import localForageLru from
'@bitsocial/bitsocial-react-hooks/dist/lib/localforage-lru/index.js'") is
fragile; either (A) change all usages (notification-handler.tsx,
src/lib/utils/media-utils.ts, src/hooks/use-fetch-gif-first-frame.ts,
src/components/reply/reply.tsx) to import a stable public export from
`@bitsocial/bitsocial-react-hooks` if the package exposes one (e.g.,
`@bitsocial/bitsocial-react-hooks/localforage-lru` or a root export) or (B) add a
small local wrapper module (e.g., src/lib/localforage-lru.ts) that centralizes
the deep import and re-exports localForageLru, then update these files to import
from that wrapper; alternatively open an upstream PR/request to add a stable
re-export and switch to that new public path once available.
src/views/community/community.tsx (1)

224-226: Rename subplebbitcommunity for consistency.

The variable kept its old name while the hook, types, and surrounding code were renamed. This is a small readability tax and easy to miss in future reviews.

♻️ Proposed rename
-  const subplebbit = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
-  const { createdAt, error, shortAddress, started, title, updatedAt, settings } = subplebbit || {};
-  const { isOffline } = useIsCommunityOffline(subplebbit || {});
+  const community = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
+  const { createdAt, error, shortAddress, started, title, updatedAt, settings } = community || {};
+  const { isOffline } = useIsCommunityOffline(community || {});

(also update the <Sidebar subplebbit={subplebbit} ...> site at line 365 — the subplebbit prop on Sidebar is one of the deferred-cleanup items per the PR description.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community/community.tsx` around lines 224 - 226, Rename the local
variable subplebbit to community everywhere in this file: change the hook call
const subplebbit = useCommunity(...) to const community = useCommunity(...),
update the destructuring const { createdAt, error, shortAddress, started, title,
updatedAt, settings } = subplebbit || {} to use community, update the
useIsCommunityOffline call useIsCommunityOffline(subplebbit || {}) to
useIsCommunityOffline(community || {}), and update any JSX props (e.g., <Sidebar
subplebbit={subplebbit} ...>) to pass the new community prop name (and rename
the prop if the Sidebar component was updated accordingly); search for all
remaining occurrences of the symbol subplebbit in this file and replace them
with community to keep names consistent with useCommunity and related types.
src/views/all/all.tsx (1)

104-130: Memoize getCommunityIdentifiers(communityAddresses) for the weekly/monthly/yearly useFeed calls.

Calling getCommunityIdentifiers(communityAddresses) inline three times allocates fresh arrays on every render, which can defeat referential-equality short-circuits inside useFeed and trigger redundant work. The main feedOptions is memoized; do the same for the suggestion variants.

♻️ Proposed refactor
+  const communityIdentifiers = useMemo(() => getCommunityIdentifiers(communityAddresses), [communityAddresses]);
+
   const feedOptions = useMemo(() => {
     const options: any = {
       newerThan: searchQuery ? 0 : timeFilterSeconds,
       sortType,
-      communities: getCommunityIdentifiers(communityAddresses),
+      communities: communityIdentifiers,
     };
     ...
-  }, [communityAddresses, sortType, timeFilterSeconds, searchQuery]);
+  }, [communityIdentifiers, sortType, timeFilterSeconds, searchQuery]);
@@
   } = useFeed({
-    communities: getCommunityIdentifiers(communityAddresses),
+    communities: communityIdentifiers,
     sortType,
     newerThan: 60 * 60 * 24 * 7,
   });

(Apply analogously to the monthly/yearly blocks.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/all/all.tsx` around lines 104 - 130, The three useFeed calls pass
getCommunityIdentifiers(communityAddresses) inline, creating new arrays each
render; memoize that result (e.g., const communityIds = useMemo(() =>
getCommunityIdentifiers(communityAddresses), [communityAddresses])) and pass
communityIds into useFeed for weeklyFeed, monthlyFeed and yearlyFeed so
referential equality is preserved for the useFeed inputs (update any existing
feedOptions usage to reference communityIds). Ensure you import/use
React.useMemo and keep the dependency on communityAddresses only.
src/hooks/use-is-community-offline.ts (1)

8-10: Parameter still named subplebbit.

The hook is useIsCommunityOffline and the parameter is typed Community, but the binding is subplebbit. Renaming to community keeps the API surface and call sites self-consistent (sidebar.tsx already passes a Community).

♻️ Suggested rename
-const useIsCommunityOffline = (subplebbit: Community) => {
+const useIsCommunityOffline = (community: Community) => {
   const { t } = useTranslation();
-  const { address, state, updatedAt, updatingState } = subplebbit || {};
+  const { address, state, updatedAt, updatingState } = community || {};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/use-is-community-offline.ts` around lines 8 - 10, Rename the
parameter binding in the useIsCommunityOffline hook from subplebbit to community
everywhere in the function signature and its destructuring (currently const {
address, state, updatedAt, updatingState } = subplebbit || {}), keeping the
Community type intact; update any internal references to use community instead
of subplebbit so the hook name useIsCommunityOffline and its usage sites remain
consistent with the Community type.
src/views/community-settings/community-data-editor/community-data-editor.tsx (2)

322-323: Trans key still references Subplebbit.

resetSubplebbitSettingsButton was missed while saveCommunitySettingsButton was renamed; the keys are local React keys on the rendered buttons, so no i18n impact, just consistency.

♻️ Suggested fix
-              2: <button key='resetSubplebbitSettingsButton' onClick={() => setText(communitySettings)} />,
+              2: <button key='resetCommunitySettingsButton' onClick={() => setText(communitySettings)} />,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-data-editor/community-data-editor.tsx`
around lines 322 - 323, The button key "resetSubplebbitSettingsButton" is
inconsistent with the renamed "saveCommunitySettingsButton"; update the local
React key to match the current naming convention (e.g.,
"resetCommunitySettingsButton") where the button is rendered (the element using
key='resetSubplebbitSettingsButton') and ensure it still calls
setText(communitySettings) onClick; reference the rendered buttons with
saveCommunitySettings and the reset handler so the change is limited to the key
string only.

80-80: Leftover publishSubplebbitEdit alias from rename.

The destructure renames publishCommunityEditpublishSubplebbitEdit, then uses that name at line 171. Aligning the local name with the hook keeps grep-ability consistent with the rest of the migration.

♻️ Suggested fix
-  const { error: publishCommunityEditError, publishCommunityEdit: publishSubplebbitEdit } = usePublishCommunityEdit(publishCommunityEditOptions);
+  const { error: publishCommunityEditError, publishCommunityEdit } = usePublishCommunityEdit(publishCommunityEditOptions);
@@
-          await publishSubplebbitEdit();
+          await publishCommunityEdit();

Also applies to: 170-180

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-data-editor/community-data-editor.tsx`
at line 80, The destructured alias publishSubplebbitEdit from
usePublishCommunityEdit is a leftover name; change the destructure so
publishCommunityEdit is the local function name (i.e., const { error:
publishCommunityEditError, publishCommunityEdit } =
usePublishCommunityEdit(...)) and then update any usages of
publishSubplebbitEdit (e.g., the call at the current usage site) to the new
publishCommunityEdit identifier so names match the hook and remain grep-able.
src/components/feed-footer/feed-footer.tsx (1)

56-66: Setter name still references subplebbit.

setHasFetchedSubplebbitAddresses is the only remaining Subplebbit-named identifier in this file; the state itself was renamed to hasFetchedCommunityAddresses. Easy alignment.

♻️ Suggested rename
-  const [hasFetchedCommunityAddresses, setHasFetchedSubplebbitAddresses] = useState(false);
+  const [hasFetchedCommunityAddresses, setHasFetchedCommunityAddresses] = useState(false);
@@
-      setHasFetchedSubplebbitAddresses(true);
+      setHasFetchedCommunityAddresses(true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/feed-footer/feed-footer.tsx` around lines 56 - 66, The setter
name is inconsistent: the state is hasFetchedCommunityAddresses but the setter
is still setHasFetchedSubplebbitAddresses; update the useState call and all
usages to use a matching setter name (e.g., setHasFetchedCommunityAddresses) so
the declaration const [hasFetchedCommunityAddresses,
setHasFetchedCommunityAddresses] = useState(false) and the useEffect timer
calling setHasFetchedCommunityAddresses(true) and the conditional if
(!hasFetchedCommunityAddresses) are aligned; ensure you rename the setter symbol
everywhere in this file (including the useEffect cleanup/timeout logic).
src/stores/use-community-offline-store.ts (1)

28-36: Defensive: spread the existing entry on init.

initializeCommunityOfflineState overwrites the entry rather than merging. The single current caller in use-is-community-offline.ts only invokes this when the entry is missing, so it's correct today, but a future caller (or a re-init after data is written) would silently drop state/updatedAt/updatingState.

♻️ Suggested merge-on-init
       communityOfflineState: {
         ...state.communityOfflineState,
         [address]: {
+          ...state.communityOfflineState[address],
           initialLoad: true,
         },
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/stores/use-community-offline-store.ts` around lines 28 - 36,
initializeCommunityOfflineState currently overwrites any existing entry in
communityOfflineState, which can drop fields like state, updatedAt, and
updatingState; update the implementation in initializeCommunityOfflineState to
merge the existing entry instead of replacing it (e.g., spread the existing
state.communityOfflineState[address] into the new object) so that initialLoad is
set while preserving other fields.
src/components/sidebar/sidebar.tsx (1)

116-122: Rename the internal prop subplebbit to community for consistency with the type migration.

The SidebarProps.subplebbit field is now typed Community after the type migration. This prop is passed from 4 view files (community, post-page, about, community-settings) and would require coordinated updates across all callers.

♻️ Suggested rename
 interface SidebarProps {
   comment?: Comment;
   isSubCreatedButNotYetPublished?: boolean;
   settings?: any;
-  subplebbit?: Community;
+  community?: Community;
   reset?: () => void;
 }
@@
-const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit, reset }: SidebarProps) => {
+const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, community, reset }: SidebarProps) => {
   const { t } = useTranslation();
-  const { address, createdAt, description, roles, rules, title, updatedAt } = subplebbit || {};
+  const { address, createdAt, description, roles, rules, title, updatedAt } = community || {};
@@
-  const { isOffline, offlineTitle } = useIsCommunityOffline(subplebbit || {});
+  const { isOffline, offlineTitle } = useIsCommunityOffline(community || {});
@@
-                {subplebbit?.address}
+                {community?.address}

Update callers in: src/views/community/community.tsx, src/views/post-page/post-page.tsx, src/views/about/about.tsx (2 usages), and src/views/community-settings/community-settings.tsx.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/sidebar/sidebar.tsx` around lines 116 - 122, Rename the
SidebarProps field subplebbit to community (type Community) inside the Sidebar
component and update all usages to accept and reference props.community instead
of props.subplebbit; specifically change the interface name and any
destructuring/prop access in Sidebar and then update the callers that pass this
prop (the community, post-page, about, and community-settings view components)
to use the new prop name. Ensure prop types and any JSX prop forwards (e.g.,
<Sidebar community={...} />) and variable names inside Sidebar (destructured
parameter, default values) are adjusted and run type checks to catch missed
references.
src/views/domain/domain.tsx (1)

111-130: Memoize getCommunityIdentifiers(communityAddresses) for the suggestion feeds.

Each render rebuilds a fresh communities array passed to the three useFeed calls (weekly, monthly, yearly), while the primary feed already memoizes this in feedOptions. Passing a non-memoized array causes unnecessary re-normalization and re-computation in the hook, degrading performance.

♻️ Suggested fix
+  const communityIdentifiers = useMemo(() => getCommunityIdentifiers(communityAddresses), [communityAddresses]);
+
   const { feed: weeklyFeed } = useFeed({
-    communities: getCommunityIdentifiers(communityAddresses),
+    communities: communityIdentifiers,
     sortType,
     newerThan: 60 * 60 * 24 * 7,
     filter: { filter: matchesDomain, key: `domain-filter-weekly-${domain}` },
   });

   const { feed: monthlyFeed } = useFeed({
-    communities: getCommunityIdentifiers(communityAddresses),
+    communities: communityIdentifiers,
     sortType,
     newerThan: 60 * 60 * 24 * 30,
     filter: { filter: matchesDomain, key: `domain-filter-monthly-${domain}` },
   });

   const { feed: yearlyFeed } = useFeed({
-    communities: getCommunityIdentifiers(communityAddresses),
+    communities: communityIdentifiers,
     sortType,
     newerThan: 60 * 60 * 24 * 365,
     filter: { filter: matchesDomain, key: `domain-filter-yearly-${domain}` },
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/domain/domain.tsx` around lines 111 - 130, The three useFeed calls
(producing weeklyFeed, monthlyFeed, yearlyFeed) each call
getCommunityIdentifiers(communityAddresses) inline which recreates a new
communities array on every render and forces unnecessary re-normalization;
memoize that result (e.g., create a const communities = useMemo(() =>
getCommunityIdentifiers(communityAddresses), [communityAddresses]) ) and pass
communities into the weekly/monthly/yearly useFeed calls (and any other places
like feedOptions) so the array identity is stable and the hook avoids
recomputing.
src/components/header/header.tsx (2)

490-490: isInHomeAboutView listed twice in the AboutButton guard.

-          {(isInHomeView || isInHomeAboutView || isInCommunityView || isInHomeAboutView || isInPostPageView) && <AboutButton />}
+          {(isInHomeView || isInHomeAboutView || isInCommunityView || isInPostPageView) && <AboutButton />}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/header/header.tsx` at line 490, The conditional rendering for
AboutButton includes isInHomeAboutView twice; update the expression in the
header component so it only checks each flag once (e.g., keep isInHomeView,
isInHomeAboutView, isInCommunityView, isInPostPageView) and remove the duplicate
isInHomeAboutView reference to avoid redundant checks in the AboutButton guard.

413-413: isInSettingsView is OR-ed twice in hasFewTabs.

Minor cleanup; one of the two occurrences is redundant.

-  const hasFewTabs = isInPostPageView || isInSubmitView || isInCommunitySubmitView || isInCommunitySettingsView || isInSettingsView || isInInboxView || isInSettingsView;
+  const hasFewTabs = isInPostPageView || isInSubmitView || isInCommunitySubmitView || isInCommunitySettingsView || isInSettingsView || isInInboxView;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/header/header.tsx` at line 413, The hasFewTabs expression
currently includes isInSettingsView twice; remove the redundant occurrence so
the boolean OR list contains each view flag only once (update the constant named
hasFewTabs where it's defined and ensure any reference to isInSettingsView
remains unchanged).
src/views/community-settings/community-settings.tsx (3)

348-357: Call usePkcRpcSettings() once and reuse the result.

usePkcRpcSettings() is invoked twice (L348 for pkcRpcSettings, L357 for state). One subscription is enough and avoids any divergence between the two calls.

♻️ Suggested fix
-  const { challenges: rpcChallenges } = usePkcRpcSettings().pkcRpcSettings || {};
-  const challengeNames = Object.keys(rpcChallenges || {});
-
-  const account = useAccount();
-  const location = useLocation();
-  const navigate = useNavigate();
-  const params = useParams();
-  const isInCreateCommunityView = isCreateCommunityView(location.pathname);
-  const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
-  const isConnectedToRpc = usePkcRpcSettings()?.state === 'connected';
+  const pkcRpc = usePkcRpcSettings();
+  const { challenges: rpcChallenges } = pkcRpc?.pkcRpcSettings || {};
+  const challengeNames = Object.keys(rpcChallenges || {});
+
+  const account = useAccount();
+  const location = useLocation();
+  const navigate = useNavigate();
+  const params = useParams();
+  const isInCreateCommunityView = isCreateCommunityView(location.pathname);
+  const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
+  const isConnectedToRpc = pkcRpc?.state === 'connected';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-settings.tsx` around lines 348 - 357,
You call usePkcRpcSettings() twice which may create two subscriptions and
divergent values; call it once, store the result (e.g. const pkc =
usePkcRpcSettings()), then derive rpcChallenges with const { challenges:
rpcChallenges } = pkc.pkcRpcSettings || {}; and compute isConnectedToRpc with
pkc.state === 'connected'; update challengeNames = Object.keys(rpcChallenges ||
{}) accordingly and remove the duplicate usePkcRpcSettings() calls so all
references use the single pkc variable.

375-376: Leftover "subplebbit" naming inside the renamed file.

The file is named/exported as CommunitySettings but several local aliases still reference the old vocabulary, which makes the rebrand inconsistent and harder to grep:

  • L375: publishCommunityEdit: publishSubplebbitEdit
  • L376: createCommunity: createSubplebbit
  • L387: function saveSubplebbit (and publishSubplebbitEdit() at L392)

Renaming these to publishCommunityEdit, createCommunity, and saveCommunity finishes the migration started elsewhere.

Also applies to: 387-411, 435-457

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-settings.tsx` around lines 375 - 376,
Replace leftover "subplebbit" names with "community" variants: change the
destructured hook aliases publishSubplebbitEdit -> publishCommunityEdit (from
usePublishCommunityEdit) and createSubplebbit -> createCommunity (from
useCreateCommunity), rename the local function saveSubplebbit to saveCommunity,
and update all calls publishSubplebbitEdit() -> publishCommunityEdit() and any
createSubplebbit references to createCommunity; ensure you update the function
declaration, all internal references between lines ~387-411 and ~435-457, and
any exported/JSX usages so the file consistently uses publishCommunityEdit,
createCommunity, and saveCommunity.

343-344: Same { name: ... } hardcode as in header.tsx — route param may be a public key.

communityAddress from useParams() can be either a name or a public key. Use the existing useCommunityIdentifier so the lookup picks the right discriminator (name vs publicKey) instead of always assuming a name.

♻️ Suggested fix
-  const { communityAddress } = useParams<{ communityAddress: string }>();
-  const community = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
+  const { communityAddress } = useParams<{ communityAddress: string }>();
+  const communityIdentifier = useCommunityIdentifier(communityAddress);
+  const community = useCommunity(communityIdentifier ? { community: communityIdentifier } : undefined);

…with import { useCommunityIdentifier } from '../../hooks/use-community-identifier';

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/community-settings/community-settings.tsx` around lines 343 - 344,
The code always treats communityAddress as a name when calling useCommunity,
which breaks when the route param is a public key; replace the hardcoded { name:
communityAddress } logic by deriving the correct identifier using
useCommunityIdentifier and pass that result into useCommunity (i.e., call
useCommunity(identifierOrUndefined) where identifierOrUndefined is the output
from useCommunityIdentifier when communityAddress exists); update the import to
include useCommunityIdentifier and use the returned discriminator (name vs
publicKey) instead of always using name.
src/hooks/use-state-string.ts (1)

82-89: Memoize the identifier list to avoid a fresh array per render.

getCommunityIdentifiers(communityAddresses || []) returns a new CommunityIdentifier[] every render. The repo just introduced useCommunityIdentifiers for exactly this case — using it gives a stable reference and lets useCommunitiesStates rely on referential equality.

♻️ Suggested fix
-import { getCommunityIdentifiers } from './use-community-identifier';
+import { useCommunityIdentifiers } from './use-community-identifier';
@@
-  // multiple community feed state string
-  const { states } = useCommunitiesStates({ communities: getCommunityIdentifiers(communityAddresses || []) });
+  // multiple community feed state string
+  const communityIdentifiers = useCommunityIdentifiers(communityAddresses);
+  const { states } = useCommunitiesStates({ communities: communityIdentifiers });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/use-state-string.ts` around lines 82 - 89, useFeedStateString
currently calls getCommunityIdentifiers(communityAddresses || []) inline,
producing a new array each render; replace that with the memoized hook
useCommunityIdentifiers so useCommunitiesStates receives a stable reference.
Update the multiple-community branch to call
useCommunityIdentifiers(communityAddresses || []) (or pass communityAddresses
through the existing hook signature) and then pass the returned identifiers into
useCommunitiesStates({ communities: identifiers }) so referential equality is
preserved for useCommunitiesStates.
src/lib/utils/pattern-utils.ts (1)

261-268: Stale jsdoc — still says "subplebbit data".

After the rebrand the hook fetches community data, but the doc comment still mentions "fetching subplebbit data when needed". Worth updating to keep terminology consistent with the rest of the file.

📝 Suggested update
 /**
  * Custom hook version of commentMatchesPattern that can handle role filters
- * by fetching subplebbit data when needed
+ * by fetching community data when needed
  *
  * `@param` comment The comment to check
  * `@param` pattern The pattern to match
  * `@returns` True if the comment matches the pattern, false otherwise
  */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/utils/pattern-utils.ts` around lines 261 - 268, Update the stale
JSDoc for the custom hook version of commentMatchesPattern to replace
"subplebbit data" with the current terminology "community data" and any other
rebrand references; locate the docblock above the custom hook (the comment
describing the custom hook version of commentMatchesPattern) and edit the text
so it says the hook fetches community data when needed and uses consistent
terminology with the rest of pattern-utils.ts.
src/views/communities/communities.tsx (1)

31-37: Finish the rebrand inside this file: prop, type, and component names still say "Subplebbit".

The data layer was migrated to Community*, but the naming inside this view is still half-and-half:

  • Interface SubplebbitProps (L31) with field subplebbit: CommunityType (L33), passed everywhere as subplebbit={communityData} (L346, 402, 449, 505).
  • Component CommunityItem is named correctly but destructures the prop as subplebbit (L174) and reads subplebbit?.address, suggested, etc.
  • Sibling components are still named AccountSubplebbits (L312), SubscriberSubplebbits (L355), AllDefaultSubplebbits (L418), AllAccountSubplebbits (L458).
  • Error-store source keys also keep the *Subplebbits_* prefix (L320, 380, 430, 466, 483) and would benefit from being renamed alongside.

Renaming these now (rather than treating them as deferred cleanup) keeps the file searchable under the new vocabulary and lets the (community as any) / (communityData as any) casts at L327, L332, L334, L345, L387, L398, L437, L448, L490, L501 drop back to CommunityType.

Also applies to: 174-174, 312-312, 355-355, 418-418, 458-458, 521-521

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/communities/communities.tsx` around lines 31 - 37, Rename all
remaining "Subplebbit" identifiers to "Community" variants: change the interface
SubplebbitProps to CommunityProps (update field subplebbit: CommunityType to
community: CommunityType and all usages like subplebbit={communityData} to
community={communityData}), update ComponentItem destructuring from subplebbit
to community and replace references subplebbit?.address, suggested, etc.; rename
sibling components AccountSubplebbits, SubscriberSubplebbits,
AllDefaultSubplebbits, AllAccountSubplebbits to AccountCommunities,
SubscriberCommunities, AllDefaultCommunities, AllAccountCommunities (and update
their usages), and rename error-store keys that use the "Subplebbits_*" prefix
to "Communities_*"; finally remove the temporary (community as
any)/(communityData as any) casts after these renames so types are CommunityType
everywhere.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 62e89af3-1dfb-44c0-a292-a06e760e3647

📥 Commits

Reviewing files that changed from the base of the PR and between b81824c and c5cb66e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (102)
  • AGENTS.md
  • package.json
  • public/translations/en/default.json
  • scripts/patch-bitsocial-react-hooks-esm.cjs
  • src/AGENTS.md
  • src/app.tsx
  • src/components/account-bar/account-bar.tsx
  • src/components/author-sidebar/author-sidebar.tsx
  • src/components/challenge-modal/challenge-modal.tsx
  • src/components/comment-edit-form/comment-edit-form.tsx
  • src/components/feed-footer/feed-footer.tsx
  • src/components/header/header.tsx
  • src/components/notification-handler/notification-handler.tsx
  • src/components/post/comment-tools/comment-tools.tsx
  • src/components/post/comment-tools/edit-menu/edit-menu.tsx
  • src/components/post/comment-tools/hide-menu/hide-menu.tsx
  • src/components/post/comment-tools/mod-menu/mod-menu.tsx
  • src/components/post/expando/expando.tsx
  • src/components/post/post.module.css
  • src/components/post/post.tsx
  • src/components/post/thumbnail/thumbnail.tsx
  • src/components/reply-form/reply-form.tsx
  • src/components/reply/reply.tsx
  • src/components/search-bar/search-bar.tsx
  • src/components/sidebar/sidebar.module.css
  • src/components/sidebar/sidebar.tsx
  • src/components/subscribe-button/subscribe-button.tsx
  • src/components/topbar/topbar.tsx
  • src/hooks/use-auto-subscribe.ts
  • src/hooks/use-challenge-settings.ts
  • src/hooks/use-challenges-options.ts
  • src/hooks/use-comment-media-info.ts
  • src/hooks/use-community-identifier.ts
  • src/hooks/use-default-subplebbits.ts
  • src/hooks/use-downvote.ts
  • src/hooks/use-fetch-gif-first-frame.ts
  • src/hooks/use-is-broadly-nsfw-community.ts
  • src/hooks/use-is-broadly-nsfw-subplebbit.ts
  • src/hooks/use-is-community-offline.ts
  • src/hooks/use-is-nsfw-community.ts
  • src/hooks/use-is-nsfw-subplebbit.ts
  • src/hooks/use-is-subplebbit-offline.ts
  • src/hooks/use-publish-reply.ts
  • src/hooks/use-replies.ts
  • src/hooks/use-state-string.ts
  • src/hooks/use-time-filter.ts
  • src/hooks/use-upvote.ts
  • src/lib/bitsocial-react-hooks-compat.ts
  • src/lib/utils/account-history-utils.test.ts
  • src/lib/utils/account-history-utils.ts
  • src/lib/utils/address-utils.ts
  • src/lib/utils/challenge-utils.ts
  • src/lib/utils/cid-utils.ts
  • src/lib/utils/comment-utils.ts
  • src/lib/utils/media-utils.ts
  • src/lib/utils/nsfw-subscription-utils.ts
  • src/lib/utils/pattern-utils.ts
  • src/lib/utils/url-utils.ts
  • src/lib/utils/user-utils.ts
  • src/lib/utils/view-utils.ts
  • src/stores/use-challenges-store.ts
  • src/stores/use-communities-loading-start-timestamps-store.ts
  • src/stores/use-community-offline-store.ts
  • src/stores/use-community-settings-store.ts
  • src/stores/use-publish-post-store.ts
  • src/stores/use-publish-reply-store.ts
  • src/stores/use-subplebbit-offline-store.ts
  • src/stores/use-subplebbits-loading-start-timestamps-store.ts
  • src/views/about/about.tsx
  • src/views/all/all.tsx
  • src/views/author/author.tsx
  • src/views/communities/communities.module.css
  • src/views/communities/communities.tsx
  • src/views/communities/index.ts
  • src/views/community-settings/challenge-settings/challenge-settings.tsx
  • src/views/community-settings/challenge-settings/index.ts
  • src/views/community-settings/community-data-editor/community-data-editor.tsx
  • src/views/community-settings/community-data-editor/index.ts
  • src/views/community-settings/community-settings.module.css
  • src/views/community-settings/community-settings.tsx
  • src/views/community-settings/index.ts
  • src/views/community/community.tsx
  • src/views/community/index.ts
  • src/views/domain/domain.tsx
  • src/views/home/home.tsx
  • src/views/inbox/inbox.tsx
  • src/views/mod/mod.tsx
  • src/views/post-page/post-page.tsx
  • src/views/profile/profile.tsx
  • src/views/settings/account-data-editor/account-data-editor.tsx
  • src/views/settings/account-settings/account-settings.tsx
  • src/views/settings/address-settings/address-settings.tsx
  • src/views/settings/avatar-settings/avatar-settings.tsx
  • src/views/settings/content-options/content-options.tsx
  • src/views/settings/plebbit-options/plebbit-options.tsx
  • src/views/settings/settings.tsx
  • src/views/settings/wallet-settings/wallet-settings.tsx
  • src/views/submit-page/submit-page.tsx
  • src/views/subplebbit-settings/index.ts
  • src/views/subplebbit-settings/subplebbit-data-editor/index.ts
  • src/views/subplebbit/index.ts
  • src/views/subplebbits/index.ts
💤 Files with no reviewable changes (11)
  • src/views/subplebbits/index.ts
  • src/views/subplebbit-settings/index.ts
  • src/views/subplebbit/index.ts
  • src/views/subplebbit-settings/subplebbit-data-editor/index.ts
  • src/hooks/use-is-nsfw-subplebbit.ts
  • src/stores/use-subplebbits-loading-start-timestamps-store.ts
  • src/hooks/use-is-broadly-nsfw-subplebbit.ts
  • scripts/patch-bitsocial-react-hooks-esm.cjs
  • src/stores/use-subplebbit-offline-store.ts
  • src/hooks/use-is-subplebbit-offline.ts
  • src/lib/bitsocial-react-hooks-compat.ts

Comment thread package.json
Comment on lines +33 to +44
"i18next": "25.10.9",
"i18next-browser-languagedetector": "7.1.0",
"i18next-http-backend": "2.2.2",
"i18next-http-backend": "3.0.5",
"json-stringify-pretty-compact": "4.0.0",
"kubo": "0.39.0",
"lodash": "4.18.0",
"memoizee": "0.4.15",
"node-fetch": "2",
"react": "19.1.2",
"react-ace": "14.0.1",
"react-dom": "19.1.2",
"react-dropzone": "14.3.8",
"react-i18next": "13.2.2",
"react-i18next": "16.6.6",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 1) Surface every Trans / useTranslation usage so the team can spot-check after the bump.
rg -nP --type=tsx -C2 '\b(Trans|useTranslation)\b' src

# 2) Confirm no leftover `useSuspense` defaults are being relied on implicitly.
rg -nP -C2 'useSuspense|defaultNS|fallbackLng' src public

# 3) Cross-check React-Compiler plugin compatibility note in vite config.
fd -e ts -e js 'vite\..*config' | xargs -I{} sed -n '1,120p' {}

Repository: bitsocialnet/seedit

Length of output: 4756


🌐 Web query:

react-i18next 16 breaking changes from v13

💡 Result:

The primary breaking change when upgrading react-i18next from v13 to v16 is the required upgrade of the peer dependency i18next from >=v23.0.1 (required by v13.0.0) to >=v25.5.2+ (for v16.x, later bumped to >=25.10.9 in v16.6.6). This i18next upgrade introduces several breaking changes that affect react-i18next usage. Key i18next breaking changes impacting react-i18next (from v23 to v25+): - Build process changes: dist/es -> dist/esm, dist/commonjs -> dist/cjs (bundled files instead of individual). - TypeScript typing updates requiring corresponding react-i18next type changes. - Later v25+ changes like peer dep alignments for TransSelector types. react-i18next v16.0.0 itself notes "major upgrade i18next dep to address 1865" with no explicit API breaks listed in its changelog. Post-v16 releases (16.3.0+) include minor fixes like i18n wrappers for React Compiler/memo compatibility and Trans defaultValue handling, but these are not flagged as breaking. Migration steps: 1. Upgrade i18next to >=25.10.9 alongside react-i18next ^16.6.6. 2. Review i18next migration guide for v23->v25: https://www.i18next.com/misc/migration-guide (covers build changes, no major config/API breaks). 3. Check Trans component usage for type errors with selectors (fixed by matching peer deps). 4. Test for bundle/build issues due to new dist structure. 5. No direct react-i18next API changes; mostly transparent via i18next dep.

Citations:


🌐 Web query:

@vitejs/plugin-react 6 breaking changes

💡 Result:

The breaking changes in @vitejs/plugin-react v6.0.0 (released March 12, 2026) are: 1. Remove Babel Related Features: Babel is no longer a dependency. The babel option in the plugin config is removed. Users needing Babel must add @rolldown/plugin-babel separately. For React Compiler, use reactCompilerPreset with it. Example migration: - react({ babel: { plugins: [...] } }) + react, babel({ plugins: [...] }) 2. Drop Vite 7 and below support: Requires Vite 8+. Upgrade if using older Vite. 3. Use Oxc for React Refresh Transform in rolldown-vite: @vitejs/plugin-react-oxc is deprecated; disableOxcRecommendation option removed. 4. react and react-dom no longer added to resolve.dedupe automatically. 5. Remove old babel-plugin-react-compiler support requiring runtimeModule option: Use newer versions supporting target option. v6.0.1 (March 13, 2026) is a patch expanding @rolldown/plugin-babel peer deps, no new breaks.

Citations:


Fix vite.config.ts Babel configuration before upgrading @vitejs/plugin-react to v6.

The package.json versions are pinned correctly. However, the current vite.config.ts will break after the upgrade: @vitejs/plugin-react v6.0.0 removed the babel option from the plugin configuration. The config currently uses:

react({
  babel: {
    plugins: [['babel-plugin-react-compiler', { verbose: true }]],
  },
})

This pattern is no longer supported. You must:

  1. Add @rolldown/plugin-babel as a dependency
  2. Refactor the Vite config to pass Babel plugins via @rolldown/plugin-babel instead of via the react() plugin

See the migration guide.

The i18next 23 → 25 and react-i18next 13 → 16 upgrades are safe: fallbackLng and defaultNS are already explicitly configured in src/lib/init-translations.ts, and no implicit defaults are being silently relied upon. The react-i18next v16 breaking changes are primarily driven by the i18next peer dependency alignment, with no direct API breaks in react-i18next itself. Complete manual UI testing before merge as already planned.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 33 - 44, Add the new dependency
`@rolldown/plugin-babel` and remove the deprecated babel option from the react()
call in vite.config.ts: locate the react({ babel: { plugins: [...] } }) usage
and delete the babel property, import the `@rolldown/plugin-babel` factory (e.g.,
rollupBabel or babelPlugin) at the top of vite.config.ts, instantiate it with
the same Babel plugins (['babel-plugin-react-compiler', { verbose: true }]) and
appropriate helpers/extensions, and add that plugin instance to the Vite plugins
array alongside react(). Ensure you update imports and remove any references to
react().babel so the Babel plugins run via `@rolldown/plugin-babel` instead of the
react plugin.

Comment thread src/components/header/header.tsx Outdated
Comment thread src/components/header/header.tsx Outdated
import { getHostname } from '../../lib/utils/url-utils';
import { formatScore, getReplyScore } from '../../lib/utils/post-utils';
import { flattenCommentsPages } from '@bitsocialnet/bitsocial-react-hooks/dist/lib/utils';
import { flattenCommentsPages } from '@bitsocial/bitsocial-react-hooks/dist/lib/utils';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if flattenCommentsPages is re-exported from the package root
fd -t d 'bitsocial-react-hooks' node_modules 2>/dev/null | head -n 5

# Inspect package.json exports / main / module fields and the index file
fd -t f 'package.json' node_modules/@bitsocial -d 4 -x sh -c '
  echo "==> $1";
  jq "{name, version, main, module, types, exports}" "$1"
' _ {}

# Look for flattenCommentsPages re-exports from the package root
fd -t f -e d.ts -e js 'index' node_modules/@bitsocial/bitsocial-react-hooks -d 3 \
  -x rg -nP 'flattenCommentsPages' {} \;

Repository: bitsocialnet/seedit

Length of output: 307


🌐 Web query:

@bitsocial/bitsocial-react-hooks 0.1.2 npm public exports flattenCommentsPages

💡 Result:

The package "@bitsocial/bitsocial-react-hooks" version 0.1.2 does not appear to be published on npm. The bitsocial-react-hooks library is hosted on GitHub at https://github.com/bitsocialnet/bitsocial-react-hooks and is intended for direct installation via Git URL with a pinned commit hash (e.g., yarn add https://github.com/bitsocialnet/bitsocial-react-hooks.git#&lt;commit-hash>). The README explicitly states it is consumed directly from the GitHub repo and used by Bitsocial clients like 5chan. No npm page or published versions were found for "@bitsocial/bitsocial-react-hooks" or "@bitsocialnet/bitsocial-react-hooks". The published build is self-contained ESM. No information on "public exports" or "flattenCommentsPages" was found in available sources. "flattenCommentsPages" may refer to internal logic for handling paginated comments (e.g., subplebbit.posts.pages.hot.comments), but it is not explicitly documented or mentioned. The library provides React hooks like useFeed, useComment, useAccount for decentralized social features on the Bitsocial protocol.

Citations:


🏁 Script executed:

# Check the actual import statement in the file
cat -n src/components/reply/reply.tsx | head -20

Repository: bitsocialnet/seedit

Length of output: 1644


🏁 Script executed:

# Search for flattenCommentsPages usage across the codebase
rg 'flattenCommentsPages' --type ts --type tsx -A 2 -B 2

Repository: bitsocialnet/seedit

Length of output: 91


🌐 Web query:

site:github.com bitsocialnet/bitsocial-react-hooks flattenCommentsPages export

💡 Result:

No direct reference to a function or export named "flattenCommentsPages" was found in the bitsocialnet/bitsocial-react-hooks repository or related sources. The repository provides React hooks for building decentralized social apps on the Bitsocial protocol, including hooks like useReplies which support a 'flat' option for flattened (non-nested) replies to comments/posts. The GitHub README mentions handling replies in nested or flattened modes: - Nested: https://github.com/bitsocialnet/bitsocial-react-hooks/#get-replies-to-a-post-nested - Flattened (not nested): https://github.com/bitsocialnet/bitsocial-react-hooks/#get-replies-to-a-post-flattened-not-nested Similar to its predecessor plebbit/plebbit-react-hooks, useReplies likely takes options like {flat: true} to fetch flattened comment pages/replies without nesting. Example usage (inferred from similar plebbit-react-hooks and repo snippets): import { useReplies } from '@bitsocialnet/bitsocial-react-hooks'; const { replies, hasMoreReplies, loadMoreReplies } = useReplies({ comment: postComment, sortType: 'best', flat: true, // flattens replies across pages, not nested pageSize: 20 }); Flattening comment pages likely refers to this 'flat' mode in useReplies or similar hooks like useFeed/useComments, where comments are loaded in a flat list rather than hierarchical structure. No explicit "flattenCommentsPages" export or utility function was identified in available sources.

Citations:


🏁 Script executed:

rg 'flattenCommentsPages' -A 3 -B 2

Repository: bitsocialnet/seedit

Length of output: 1216


🏁 Script executed:

# Also check the package.json of bitsocial-react-hooks to understand its exports
cd node_modules/@bitsocial 2>/dev/null || true
find . -name 'package.json' -path '*bitsocial-react-hooks*' 2>/dev/null | head -5

Repository: bitsocialnet/seedit

Length of output: 45


🌐 Web query:

site:github.com/bitsocialnet/bitsocial-react-hooks flattenCommentsPages "export" OR "export default"

💡 Result:

flattenCommentsPages appears to be an internal function or method in the bitsocial-react-hooks library (https://github.com/bitsocialnet/bitsocial-react-hooks), a TypeScript React hooks library for building decentralized social apps, likely using Plebbit (a decentralized Reddit-like platform). It is referenced in test code for mocking comment replies pages, where it is used as a prototype method on a Pages object to generate page content: comment.replies.pages.best = Pages.prototype.pageToGet.apply({ comment }, [${comment.cid} page cid best]);. No explicit "export" or "export default" declaration for flattenCommentsPages was found in the available sources. It is likely a private utility for flattening nested comment page structures into a linear array, common in tree-like comment threading systems, but not publicly exported.

Citations:


🌐 Web query:

site:github.com/bitsocialnet/bitsocial-react-hooks index.ts index.js main export

💡 Result:

In TypeScript Node.js projects, index.ts is commonly used as the source entry point (e.g., main module with exports), compiled to index.js for runtime. The package.json "main" field points to the compiled "index.js" (not .ts, as Node.js doesn't execute TypeScript natively). index.ts often serves as a barrel file re-exporting other modules for convenient imports (e.g., export * from './foo';). No official TypeScript or Node.js docs explicitly found in results confirming exact config, but standard practice inferred from TypeScript homepage (TS compiles to JS for Node.js) and common usage in TS repos like TypeORM example.

Citations:


Avoid deep-importing undocumented internal utilities from dist/.

The import from '@bitsocial/bitsocial-react-hooks/dist/lib/utils' reaches into the compiled output and is not part of the package's public API. The function flattenCommentsPages is not explicitly exported from the main entry point and appears to be an internal utility. This is fragile because:

  • Any reorganization of the package's internal directory structure, build output, or exports will break this import silently.
  • Newer bundlers or Node versions that enforce strict exports maps will reject this deep import if not explicitly exposed.
  • It relies on an undocumented private API.

Either import flattenCommentsPages from the main package entry (@bitsocial/bitsocial-react-hooks) if it is publicly available there, or replicate the function locally in your utilities.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reply/reply.tsx` at line 10, The file reply.tsx imports
flattenCommentsPages via a deep import from
'@bitsocial/bitsocial-react-hooks/dist/lib/utils', which is a private/fragile
path; replace this by either importing flattenCommentsPages from the package
public entry ('@bitsocial/bitsocial-react-hooks') if that export exists, or
copy/implement a local utility version (e.g., in src/utils/comments.ts) and
import it from there; update the import statement in reply.tsx to reference the
public package export or the new local module and remove the deep
'/dist/lib/utils' path.

Comment on lines +35 to +39
const offlineTitle = isLoading
? t('loading')
: updatedAt
? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } })
: t('subplebbit_offline_info');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm whether the offline-info key has been renamed in any locale.
fd -e json . public/translations | xargs rg -n 'subplebbit_offline_info|community_offline_info'

Repository: bitsocialnet/seedit

Length of output: 4689


Track this translation key rename for rebrand completion.

The subplebbit_offline_info key remains unchanged across all 37 translation locales. When the rebrand cleanup removes the subplebbit_ prefix from other translation keys, this one will be silently missed unless explicitly tracked—especially since the English text already says "community" while the key name still references "subplebbit".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/use-is-community-offline.ts` around lines 35 - 39, The translation
key used in the offlineTitle expression still uses the old subplebbit key
('subplebbit_offline_info')—update the t() call in the offlineTitle ternary
(inside use-is-community-offline.ts) to the new key (e.g.,
'community_offline_info') and ensure all locale files are updated/migrated to
include that new key; also search for other occurrences of
'subplebbit_offline_info' across the repo to replace or alias them to avoid
missing translations after the rebrand.

Comment thread src/views/home/home.tsx
}, [communityAddresses, sortType, timeFilterSeconds, searchQuery, commentFilter]);

const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
const { feed, hasMore, loadMore, reset, communityKeysWithNewerPosts: communityAddressesWithNewerPosts } = useFeed(feedOptions);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the hook's TypeScript surface in the installed package to confirm
# whether `communityKeysWithNewerPosts` are addresses or opaque identifiers.
fd -t f -e d.ts . node_modules/@bitsocial/bitsocial-react-hooks 2>/dev/null | head -50
rg -nP -C3 'communityKeysWithNewerPosts|CommunityIdentifier|UseFeedResult' \
  node_modules/@bitsocial/bitsocial-react-hooks 2>/dev/null || true
# Also check FeedFooter to see how it consumes the prop.
fd -a feed-footer src/components | xargs -I{} rg -nP -C2 'community(Addresses|Keys)WithNewerPosts' {}

Repository: bitsocialnet/seedit

Length of output: 715


🌐 Web query:

@bitsocial/bitsocial-react-hooks 0.1.2 useFeed communityKeysWithNewerPosts type

💡 Result:

In @bitsocial/bitsocial-react-hooks version 0.1.2 (likely installed from GitHub repo bitsocialnet/bitsocial-react-hooks at a specific commit), the useFeed hook returns an object including communityKeysWithNewerPosts, which is an array of strings. Type: string[] This field was renamed from communityAddressesWithNewerPosts in a recent breaking change (PR #49, merged around April 2026) to use stable community keys derived preferably from publicKey. It tracks community keys (string identifiers) that have newer posts available beyond the current feed's time window. Full useFeed return type (from README): { feed: Comment[], loadMore: function, hasMore: boolean, reset: function, updatedFeed: Comment[], bufferedFeed: Comment[], communityKeysWithNewerPosts: string[] } Recent updates added expandTimeWindow function, but core type for communityKeysWithNewerPosts remains string[].

Citations:


communityKeysWithNewerPosts are not addresses—they are stable community keys derived from publicKey. The alias to communityAddressesWithNewerPosts hides a semantic mismatch.

The useFeed hook now returns communityKeysWithNewerPosts (a recent breaking change in PR #49), which are stable string identifiers derived from publicKey, not community addresses. Line 92 aliases this to communityAddressesWithNewerPosts and passes it to FeedFooter, which expects address-based data for operations like subscription matching or constructing /s/:address links. If FeedFooter or downstream code treats these keys as addresses, it will silently fail.

Rename the alias to accurately reflect the data: either update FeedFooter to accept and use community keys, or convert the keys back to addresses before passing them. The same issue appears at src/views/mod/mod.tsx line 65.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/home/home.tsx` at line 92, The aliasing of
communityKeysWithNewerPosts to communityAddressesWithNewerPosts is misleading
and causes downstream failures; stop renaming or misrepresenting the data from
useFeed — keep the returned variable as communityKeysWithNewerPosts and either
(A) update FeedFooter's prop signature and all uses to accept and operate on
community keys (rename props/params from "address" to "communityKey" and adjust
any URL/lookup logic), or (B) explicitly convert the stable community keys to
real community addresses with your conversion helper before passing them into
FeedFooter (do not alias the original variable to an address name). Apply the
same fix in the other occurrence in mod.tsx (line with useFeed there) so both
places consistently handle communityKeysWithNewerPosts correctly.

Comment thread src/views/mod/mod.tsx Outdated
Comment thread src/views/mod/mod.tsx Outdated
const { t } = useTranslation();
const account = useAccount();
const defaultSubplebbits = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubplebbits();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Minor inconsistency: hook name vs. variable name.

useDefaultSubplebbits() still uses the old name while the destination variable is defaultCommunities. Per the PR description this is an intentional deferred rename (pending pkc-js confirmation), so no change required here — just flagging so it isn't lost in the follow-up sweep.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/settings/content-options/content-options.tsx` at line 141, The hook
name useDefaultSubplebbits is inconsistent with the destination variable
defaultCommunities; rename the hook to useDefaultCommunities (and update its
export/imports and any references) so the hook name matches the variable, e.g.,
update the hook declaration and its usages (useDefaultSubplebbits ->
useDefaultCommunities) including the file that exports it and the import in
content-options.tsx where defaultCommunities is assigned.

Comment thread src/views/submit-page/submit-page.tsx Outdated
Comment on lines +476 to +479
const selectedCommunityData = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
const { rules, title: communityTitle } = selectedCommunityData;
const shortAddress = communityAddress && getShortAddress(communityAddress);
const { isOffline, offlineTitle } = useIsCommunityOffline(selectedCommunityData);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

@bitsocial/bitsocial-react-hooks 0.1.2 useCommunity return value when called with undefined arguments

💡 Result:

The useCommunity hook from @bitsocial/bitsocial-react-hooks (likely the same as bitsocialnet/bitsocial-react-hooks repo) expects an options object with a required 'community' property of type {name?: string, publicKey?: string} and an optional 'onlyIfCached?: boolean' parameter. When called with undefined arguments (e.g., useCommunity(undefined) or useCommunity), it will fail validation. Recent changes in PR #49 explicitly reject invalid inputs like legacy string parameters at runtime, and the hook computes a communityKey for store lookups via addCommunityToStore. No source explicitly states the exact return value for undefined args, but typical React custom hook patterns (especially data-fetching hooks) return undefined/null or throw during validation before returning. The signature indicates it returns a Community object or undefined when no valid community identifier is provided, as it relies on store state which would be empty/missing for invalid keys. For version 0.1.2 specifically, no release notes or tags found; the repo uses git commit pinning for consumption, so behavior matches current main branch post-PR#49 (April 2026).

Citations:


🏁 Script executed:

# Find the submit-page.tsx file and check its usage patterns
fd -t f "submit-page.tsx" src/

Repository: bitsocialnet/seedit

Length of output: 101


🏁 Script executed:

# Check the context around lines 476-479 and look for useCommunity usage patterns
if [ -f "src/views/submit-page/submit-page.tsx" ]; then
  echo "=== Context around lines 476-479 ==="
  sed -n '470,485p' src/views/submit-page/submit-page.tsx
  
  echo -e "\n=== All useCommunity calls in the file ==="
  grep -n "useCommunity" src/views/submit-page/submit-page.tsx
  
  echo -e "\n=== Lines 330, 347, 383, 405, 473 (mentioned as any casts) ==="
  sed -n '325,335p' src/views/submit-page/submit-page.tsx | cat -n
  sed -n '345,352p' src/views/submit-page/submit-page.tsx | cat -n
  sed -n '380,390p' src/views/submit-page/submit-page.tsx | cat -n
  sed -n '402,412p' src/views/submit-page/submit-page.tsx | cat -n
  sed -n '470,478p' src/views/submit-page/submit-page.tsx | cat -n
fi

Repository: bitsocialnet/seedit

Length of output: 3620


🏁 Script executed:

# Check how useCommunity is used elsewhere in the codebase to understand defensive patterns
echo "=== Other useCommunity call patterns in codebase ==="
rg "useCommunity" src/components src/views src/hooks --no-heading -A 2 -B 1 | head -100

Repository: bitsocialnet/seedit

Length of output: 8464


Defensively destructure selectedCommunityData to prevent runtime TypeError.

Line 477 directly destructures selectedCommunityData without null safety, but when communityAddress is empty, useCommunity(undefined) may return undefined. Other call sites in the codebase defensively handle this: community.tsx uses const { createdAt, ... } = subplebbit || {}; and post.tsx uses optional chaining community?.roles. This inconsistency will cause a TypeError when destructuring an undefined value.

Proposed fix
-  const { rules, title: communityTitle } = selectedCommunityData;
+  const { rules, title: communityTitle } = selectedCommunityData ?? {};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const selectedCommunityData = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
const { rules, title: communityTitle } = selectedCommunityData;
const shortAddress = communityAddress && getShortAddress(communityAddress);
const { isOffline, offlineTitle } = useIsCommunityOffline(selectedCommunityData);
const selectedCommunityData = useCommunity(communityAddress ? { community: { name: communityAddress } } : undefined);
const { rules, title: communityTitle } = selectedCommunityData ?? {};
const shortAddress = communityAddress && getShortAddress(communityAddress);
const { isOffline, offlineTitle } = useIsCommunityOffline(selectedCommunityData);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/submit-page/submit-page.tsx` around lines 476 - 479,
selectedCommunityData may be undefined, so defensively destructure it and guard
downstream uses: instead of directly extracting "rules" and "title" from
selectedCommunityData, default it to an empty object (e.g., destructure from
selectedCommunityData || {}) and compute shortAddress using optional chaining
(e.g., getShortAddress(selectedCommunityData?.address or communityAddress) or
guard with communityAddress). Ensure the call to
useIsCommunityOffline(selectedCommunityData) still receives the possibly
undefined value but all local destructuring (rules, communityTitle) is safe to
avoid a TypeError.

- Use getCommunityIdentifier in every useCommunity / useCommunityStats
  call site so hash-style (publicKey) community addresses are routed
  to the correct CommunityIdentifier branch instead of always being
  treated as { name }.
- Move the create-community redirect in community-settings.tsx out
  of the render body and into useEffect to avoid the "cannot update
  a component while rendering" warning and re-fire on every render.
- useMemo Object.keys(accountCommunities) in mod.tsx so feedOptions
  and the three useFeed calls receive a stable communityAddresses
  array.
- Simplify the tautological logo-avatar guard in header.tsx.
- (Verified flattenCommentsPages import resolves; left as-is.)
- (Comment import in mod.tsx confirmed from @bitsocial/...)
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c5348a0. Configure here.

<div className={styles.logoContainer}>
<Link to={logoLink} className={styles.logoLink}>
{(logoIsAvatar || (!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
{(logoIsAvatar || (!isInCommunityView && !isInProfileView && !isInAuthorView)) && (
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Accidental logic change hides logo in header

Medium Severity

During the rename refactor, || !logoIsAvatar was accidentally dropped from the first logo-rendering condition. The old expression (logoIsAvatar || (!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) was a tautology (always true), so the logo <img> always rendered. The new expression (logoIsAvatar || (!isInCommunityView && !isInProfileView && !isInAuthorView)) is no longer always true — when logoIsAvatar is false and the user is in a community, profile, or author view, the sprout logo image will no longer render. This is a visual regression introduced by a rename-only commit.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c5348a0. Configure here.


export const useCommunityIdentifiers = (communityAddresses?: Array<string | undefined>): CommunityIdentifier[] => {
return useMemo(() => getCommunityIdentifiers(communityAddresses ?? []), [communityAddresses]);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Exported hooks useCommunityIdentifier(s) are never imported

Low Severity

The newly added useCommunityIdentifier and useCommunityIdentifiers hook exports are never imported anywhere in the codebase. Every call site instead uses the plain function variants getCommunityIdentifier and getCommunityIdentifiers. These two hooks are dead code that add unnecessary API surface.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c5348a0. Configure here.

@tomcasaburi tomcasaburi merged commit 3665384 into master Apr 27, 2026
8 checks passed
@tomcasaburi tomcasaburi deleted the codex/feature/community-rebrand branch April 27, 2026 11:57
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