Rename user-facing 'Community' → 'Organization'

User-visible copy now matches the Organization rebrand. Internal
symbols, file names, query keys, routes, and storage keys are
intentionally left alone for this pass — they're still pinned to
"community" / "communities" until a dedicated rename commit.

Touched strings:

- `MobileBottomNav` and `sidebarItems` labels: "Communities" →
  "Organize", matching the existing TopNav copy.
- `CommunityDetailPage` hero fallback ("Unnamed Community" →
  "Unnamed Organization") and "About this organization" aria-label.
- `CommunityContent` thumbnail fallback name.
- `ExternalContentHeader.CommunityPreview` row label and fallback name.
- `NoteCard` kind-34550 noun "community" → "organization" (used in
  feed-card action lines like "created an organization") and the
  article switches from "a" to "an".
- `NoteMoreMenu` overflow-menu labels: "Report post to community" →
  "Report post to organization", "Remove from community" → "Remove
  from organization".
- `BanConfirmDialog` title, description, and success/failure toasts.
- `CommunityContentWarning` reporter pluralization and the
  fallback report-type label ("community guidelines" →
  "organization guidelines"); reporters are now scoped to founder /
  moderators per the commit 4 cleanup, so the wording reflects that.
- `CommunityReportDialog` description copy.
- `CreateGoalDialog` placeholder example.
- `CreateActionDialog` org-scoped description string.
- `CreateCommunityEventDialog` NIP-31 `alt` tag prefix.
- `CommentContext` kind-34550 entries in the action-noun and
  rendered-noun maps ("a community" / "community" → "an
  organization" / "organization").
- `extraKinds` kind-34550 entry: label, description, and blurb.
- `kindLabels` kinds 4550, 10004, 34550.
- `DiscoverHero` ticker stat copy.
- `GetFeedTool` error message drops "communities" since the
  Following feed no longer includes organization activity (removed
  in the badge-runtime commit).
This commit is contained in:
lemon
2026-05-20 01:18:24 -07:00
parent a68cad44c3
commit ac3cdf34b2
18 changed files with 33 additions and 33 deletions
+4 -4
View File
@@ -67,20 +67,20 @@ export function BanConfirmDialog({
// immediately (removes banned content without a page refresh).
await queryClient.invalidateQueries({ queryKey: ['community-members', communityATag] });
toast({ title: 'Post removed from community' });
toast({ title: 'Post removed from organization' });
setReason('');
onOpenChange(false);
} catch {
toast({ title: 'Failed to remove post from community', variant: 'destructive' });
toast({ title: 'Failed to remove post from organization', variant: 'destructive' });
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-md rounded-2xl flex flex-col overflow-hidden">
<DialogTitle>Remove from community</DialogTitle>
<DialogTitle>Remove from organization</DialogTitle>
<DialogDescription className="text-sm text-muted-foreground">
This will hide the post from canonical community views.
This will hide the post from canonical organization views.
</DialogDescription>
<div className="space-y-2">
+2 -2
View File
@@ -146,7 +146,7 @@ const KIND_LABELS: Record<number, string> = {
32267: 'a Zapstore app',
34139: 'a playlist',
34236: 'a divine',
34550: 'a community',
34550: 'an organization',
9041: 'a goal',
35128: 'an nsite',
36639: 'a pledge',
@@ -246,7 +246,7 @@ const KIND_SUFFIXES: Partial<Record<number, string>> = {
37381: 'deck',
37516: 'treasure',
30621: 'constellation',
34550: 'community',
34550: 'organization',
30054: 'episode',
30055: 'trailer',
34139: 'playlist',
+1 -1
View File
@@ -11,7 +11,7 @@ function getTag(tags: string[][], name: string): string | undefined {
}
function parseCommunityEvent(event: NostrEvent) {
const name = getTag(event.tags, 'name') || getTag(event.tags, 'd') || 'Unnamed Community';
const name = getTag(event.tags, 'name') || getTag(event.tags, 'd') || 'Unnamed Organization';
const description = getTag(event.tags, 'description') || '';
const image = getTag(event.tags, 'image');
+3 -3
View File
@@ -14,7 +14,7 @@ const REPORT_TYPE_LABELS: Record<Nip56ReportType, string> = {
illegal: 'illegal content',
malware: 'malware',
impersonation: 'impersonation',
other: 'community guidelines',
other: 'organization guidelines',
};
interface CommunityContentWarningProps {
@@ -68,8 +68,8 @@ export function CommunityContentWarning({ event, children, className }: Communit
<p className="text-sm font-medium text-foreground">Reported Content</p>
<p className="text-xs text-muted-foreground leading-relaxed">
{reporterCount === 1
? `Reported by a community member for ${typeLabels}.`
: `Reported by ${reporterCount} community members for ${typeLabels}.`}
? `Reported by an organization moderator for ${typeLabels}.`
: `Reported by ${reporterCount} organization moderators for ${typeLabels}.`}
</p>
</div>
<Button
+2 -2
View File
@@ -421,7 +421,7 @@ export function CommunityDetailPage({ event }: { event: NostrEvent }) {
// Parse community definition
const community = useMemo(() => parseCommunityEvent(event), [event]);
const name = community?.name ?? 'Unnamed Community';
const name = community?.name ?? 'Unnamed Organization';
const description = community?.description ?? '';
const image = community?.image;
const cover = sanitizeUrl(image);
@@ -772,7 +772,7 @@ export function CommunityDetailPage({ event }: { event: NostrEvent }) {
type="button"
onClick={() => setDescriptionDialogOpen(true)}
className="-my-1 -mr-1 p-1 rounded-full text-white/75 hover:text-white hover:bg-white/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/80 transition-colors"
aria-label="About this community"
aria-label="About this organization"
>
<Info className="size-4 [text-shadow:none] drop-shadow-[0_1px_2px_rgba(0,0,0,0.85)]" />
</button>
+1 -1
View File
@@ -91,7 +91,7 @@ export function CommunityReportDialog({
<DialogContent className="max-w-md max-h-[85dvh] rounded-2xl flex flex-col overflow-hidden">
<DialogTitle>Report post</DialogTitle>
<DialogDescription className="text-sm text-muted-foreground">
Select a reason for reporting this post to the community.
Select a reason for reporting this post to the organization.
</DialogDescription>
<div className="flex-1 overflow-y-auto min-h-0 -mx-6 px-6">
+1 -1
View File
@@ -356,7 +356,7 @@ export function CreateActionDialog({ countryCode, communityATag, open, onOpenCha
if (!user) return null;
const description = communityATag
? 'New community pledge. You can optionally choose a country below.'
? 'New organization pledge. You can optionally choose a country below.'
: countryCode
? `New pledge for ${getGeoDisplayName(countryCode)}.`
: 'New pledge. You can optionally choose a country below.';
@@ -243,7 +243,7 @@ export function CreateCommunityEventDialog({ communityATag, open, onOpenChange,
const tags: string[][] = [
['d', dTag],
['title', trimmedTitle],
['alt', `${isCommunityEvent ? 'Community event' : 'Calendar event'}: ${trimmedTitle}`],
['alt', `${isCommunityEvent ? 'Organization event' : 'Calendar event'}: ${trimmedTitle}`],
...preservedTags,
];
+1 -1
View File
@@ -165,7 +165,7 @@ export function CreateGoalDialog({ communityATag, children, open: controlledOpen
<Label htmlFor="goal-title">Title</Label>
<Input
id="goal-title"
placeholder="e.g. Community meetup expenses"
placeholder="e.g. Organization meetup expenses"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
+2 -2
View File
@@ -1303,7 +1303,7 @@ export function CommunityPreview({ addr }: { addr: { kind: number; pubkey: strin
const communityName = event?.tags.find(([n]) => n === 'name')?.[1]
|| event?.tags.find(([n]) => n === 'd')?.[1]
|| 'Community';
|| 'Organization';
const communityImage = event?.tags.find(([n]) => n === 'image')?.[1];
const communityDescription = event?.tags.find(([n]) => n === 'description')?.[1];
const moderatorCount = event?.tags.filter(([n, , , role]) => n === 'p' && role === 'moderator').length ?? 0;
@@ -1347,7 +1347,7 @@ export function CommunityPreview({ addr }: { addr: { kind: number; pubkey: strin
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Users className="size-3 shrink-0" />
<span>Community</span>
<span>Organization</span>
{moderatorCount > 0 && (
<span className="text-muted-foreground/60">&middot; {moderatorCount} mod{moderatorCount !== 1 ? 's' : ''}</span>
)}
+2 -2
View File
@@ -107,10 +107,10 @@ export function MobileBottomNav() {
size="sm"
/>
{/* Communities */}
{/* Organizations */}
<NavItem
icon={Users}
label="Communities"
label="Organize"
active={isOnCommunities}
to="/communities"
onClick={() => { selectionChanged(); setSearchOpen(false); }}
+2 -2
View File
@@ -1810,8 +1810,8 @@ const KIND_HEADER_MAP: Record<number, KindHeaderConfig> = {
},
34550: {
icon: Users,
action: (event) => publishedAtAction(event, { created: "created a", updated: "updated a", fallback: "shared a" }),
noun: "community",
action: (event) => publishedAtAction(event, { created: "created an", updated: "updated an", fallback: "shared an" }),
noun: "organization",
nounRoute: "/communities",
},
30009: {
+2 -2
View File
@@ -575,7 +575,7 @@ function NoteMoreMenuContent({ event, open, onOpenChange, communityContext, onRe
{!isOwnPost && (
<MenuItem
icon={<Flag className="size-5" />}
label={communityContext ? 'Report post to community' : `Report @${displayName}`}
label={communityContext ? 'Report post to organization' : `Report @${displayName}`}
onClick={onReport}
destructive
/>
@@ -583,7 +583,7 @@ function NoteMoreMenuContent({ event, open, onOpenChange, communityContext, onRe
{!isOwnPost && communityContext?.canBan && (
<MenuItem
icon={<ShieldBan className="size-5" />}
label="Remove from community"
label="Remove from organization"
onClick={onBanContent}
destructive
/>
+1 -1
View File
@@ -192,7 +192,7 @@ export function DiscoverHero({ className }: DiscoverHeroProps) {
items.push({
id: 'communities',
value: communities.length.toLocaleString(),
label: `${communities.length === 1 ? 'community' : 'communities'} gathering on Nostr`,
label: `${communities.length === 1 ? 'organization' : 'organizations'} gathering on Nostr`,
icon: <Users className="size-5" aria-hidden />,
});
}
+3 -3
View File
@@ -355,12 +355,12 @@ export const EXTRA_KINDS: ExtraKindDef[] = [
showKey: 'showCommunities',
feedKey: 'feedIncludeCommunities',
extraFeedKinds: [9041],
label: 'Communities',
description: 'Flat communities with badge-based membership (NIP-72)',
label: 'Organizations',
description: 'Agora organizations with founder + moderator trust model (NIP-72)',
route: 'communities',
addressable: true,
section: 'social',
blurb: 'Flat communities on Nostr with one member badge, explicit moderators, and community moderation.',
blurb: 'Organizations on Nostr with an explicit founder, listed moderators, and event-level moderation.',
},
{
kind: 62,
+3 -3
View File
@@ -132,7 +132,7 @@ export const KIND_LABELS: Record<number, string> = {
3367: 'Color moment',
// NIP-72
4550: 'Community post approval',
4550: 'Organization post approval',
// NIP-90 DVM (ranges)
5000: 'Job request',
@@ -181,7 +181,7 @@ export const KIND_LABELS: Record<number, string> = {
10002: 'Relay list',
// NIP-51
10003: 'Bookmark list',
10004: 'Communities list',
10004: 'Organizations list',
10005: 'Public chats list',
10006: 'Blocked relays list',
10007: 'Search relays list',
@@ -368,7 +368,7 @@ export const KIND_LABELS: Record<number, string> = {
// Music
34139: 'Music playlist',
// NIP-72
34550: 'Community definition',
34550: 'Organization definition',
// NIP-5A
34128: 'Nsite (legacy)',
35128: 'Nsite',
+1 -1
View File
@@ -193,7 +193,7 @@ export const SIDEBAR_ITEMS: SidebarItemDef[] = [
{ id: "emojis", label: "Emojis", path: "/emojis", icon: SmilePlus },
{ id: "development", label: "Development", path: "/development", icon: Code },
{ id: "badges", label: "Badges", path: "/badges", icon: Award },
{ id: "communities", label: "Communities", path: "/communities", icon: Users },
{ id: "communities", label: "Organize", path: "/communities", icon: Users },
{ id: "world", label: "World", path: "/world", icon: Earth },
];
+1 -1
View File
@@ -227,7 +227,7 @@ function resolveFilter(
}
if (filters.length === 0) {
return { error: 'No followed people, communities, hashtags, or countries found for the Following feed.' };
return { error: 'No followed people, hashtags, or countries found for the Following feed.' };
}
return { filters, needsDittoRelay: false, feedLabel: 'following' };