The amber warning alert used bg-amber-500/5 (5% opacity — nearly invisible)
and text-amber-900. The faint background combined with potential
tailwind-merge ambiguity between the Alert variant's text-foreground and
the override text-amber-900 resulted in poor readability in light mode.
Align with the established BitcoinPublicDisclaimer pattern:
- bg-amber-500/5 → bg-amber-50 (solid visible amber tint)
- text-amber-900 → text-amber-950 (darkest amber for max contrast)
- border-amber-500/50 → border-amber-300/60 + dark:border-amber-500/30
- dark:bg-amber-950/50 for a distinct dark-mode background
- Icon: !text-amber-500 → !text-amber-600 dark:!text-amber-400
No wallet logic, sweep behavior, or component structure changed.
The useMyCommunities hook was removed in a68cad44. Replace with
useUserOrganizations which returns the same community data (founded,
moderated, and followed organizations) under the UserOrganization type.
SectionHeader has built-in px-4, which stacked with the page container's
px-4 to produce 32px inset on mobile. Override with px-0 so the page
container provides the sole inset, matching the hero card and scroll
items.
New page at /my-square with personal hero, wallet summary, notification
previews, and grouped campaign sections (mine, country, community).
Includes useNotificationPreview hook for lightweight notification
display and a compact layout tweak to CampaignCard.
RoboSats trades Lightning Bitcoin, not on-chain, so a user cashing
out from their Agora address can't drop straight into it. Update the
Donor Guide ('use non-KYC Bitcoin'), the Activist Guide
('Peer-to-peer exchange'), and the cash-out comparison row to spell
out the two-step path: Boltz to swap on-chain → Lightning, then
RoboSats to trade for fiat. Bisq and HodlHodl still trade on-chain
directly and are listed separately.
The previous answer to 'Why doesn't Agora generate a new address for
every donation?' focused on the single-point-of-failure angle. Lead
with the bigger reason: rotating addresses would mean Agora has to
take custody of the Bitcoin before forwarding it on to activists,
which makes Agora a money-transmitting service. That brings
regulatory exposure and creates a real chokepoint someone could
shut down to stop every donation flowing through the platform.
Also reorder the Bitcoin Donations section so 'Why not Monero or
another cryptocurrency?' sits as the very last item, after the
silent-payments and rotating-addresses explanations.
The eyebrow label in the top-right of the guide hero was redundant
with the headline beside it. Cut the eyebrow prop and use the page
name ('Donor Guide' / 'Activist Guide') as the actual headline. The
'Back to Help' chip stays on its own row at the top of the hero.
Replace the plain sticky 'Back to Help' bar on the two guide pages
with a hero section in the same recipe as the Organize and Actions
homepage heros: rotating photo banner (HeroBanner) + atmospheric tint
(HeroAtmosphere) + scrims + overlay copy. Sub-page sized — ~280px
instead of the 460px homepage heros — and embeds a glassy
'Back to Help' chip in the eyebrow row so navigation out stays
prominent without a separate sticky strip.
- Donor Guide reuses the World Liberty Congress photos in /public/hero
with the cool palette: reads as community / supporters.
- Activist Guide reuses the protest cover gallery from
DEFAULT_ACTION_COVERS with the warm hope palette: reads as people in
motion.
Both pages drop into the new shared GuideHero component to keep the
two pages DRY.
FAQ updates in the Bitcoin Donations section:
- 'Why on-chain Bitcoin?' now spells out that on-chain donations
require zero extra setup for activists who already have a Nostr
account and zero extra setup for donors who already hold Bitcoin —
the accessibility argument that makes Agora viable for normal
people.
- 'Why doesn't Agora use Lightning?' now names Strike and Breez
alongside Wallet of Satoshi as examples of the popular custodial
Lightning wallets that can be shut down or pressured.
- New 'Why not Monero or another cryptocurrency?' item: Bitcoin's
adoption is what makes it easiest for donors to send and activists
to receive and spend; niche coins create a barrier neither side
should have to clear.
The Donor Guide and a few related FAQ items singled out Cash App as
the example of a custodial consumer Bitcoin app. Replace those with a
broader list — Cash App, Coinbase, Strike, Venmo, PayPal, Kraken,
Binance — so it doesn't read as picking on one product. The Bisq
Pros/Cons and the 'What consumer apps can't do' section heading
follow the same edit.
Also move the 'Back to Help' navigation on the Donor and Activist
guide pages from a bottom button into a sticky top bar, PWA-style. It
sits right under the TopNav (top-16, z-30) and stays visible while
scrolling so users can return to /help from anywhere on the page
without scrolling back up. Replaces the previous PageHeader, which
hid its back arrow on desktop and made navigating out of the guides
awkward.
The 'What is Agora for?' item duplicated 'What is Agora?' from the
About Agora section. Drop it.
The Network & Safety section was carrying Nostr-protocol explainers
(feed, relays, Blossom, Mastodon/Bluesky comparison, profile fields,
reporting) that aren't core to Agora's donation flow. Drop the whole
section from the visible FAQ.
The six IDs in that section that other pages reference via HelpTip
(fyp, what-are-relays, what-are-blossom, report-content, vs-mastodon-
bluesky, profile-fields) move into the existing hidden 'Legacy'
category alongside the Lightning/zap stubs, so the call sites on
NetworkSettingsPage, ContentSettingsPage, ContentPage, SearchPage,
RelayListManager, and ProfileSettings continue to resolve.
The 'Bitcoin Donations' and 'About Bitcoin Payments on Agora' FAQ
sections were saying overlapping things in two places. Combine them
into a single 'Bitcoin Donations on Agora' section, placed in the
higher slot (right after 'About Agora').
Agora's donation flow is on-chain only, so Lightning and zap items are
removed from the visible FAQ. The two IDs that other pages reference
via HelpTip (send-bitcoin-lightning in ZapDialog, what-are-zaps in
ProfileSettings) are kept in a new hidden 'Legacy' category so those
call sites don't break. HelpFAQSection skips hidden categories on the
default render but the per-ID lookup used by HelpTip still finds them.
Also adds a 'Back to Help' button at the bottom of both the Donor
Guide and Activist Guide pages so users don't have to scroll back up
to the header to navigate out.
The FAQ accordion was carrying a lot of generic Nostr-client content
(profile field formats, app-store availability, Mastodon/Bluesky
comparisons, marketing copy) that wasn't relevant to Agora's core: on-
chain Bitcoin donations to activists.
Restructure into four focused categories:
- 'About Agora' (formerly 'Getting Started') — what Agora is, what
Nostr is, key management, cost.
- 'Bitcoin Donations' — how sending works, the wallet, zaps,
censorship resistance.
- 'Network & Safety' — relays, Blossom, reporting, profile fields.
- 'About Bitcoin Payments on Agora' (formerly 'About Agora') — the
design-rationale Q&A added in the previous commit (why not
Lightning / silent payments / rotating addresses).
All FAQ item IDs referenced by HelpTip on other pages are preserved
(connect-wallet, fyp, profile-fields, what-are-zaps, vs-mastodon-
bluesky, send-bitcoin-onchain, send-bitcoin-lightning, what-is-nostr,
what-are-relays, what-are-blossom, report-content, censorship-
resistance) — their content has been rewritten to be relevant to
Agora's donation flow without breaking the callers.
Also moves the 'Need help? Meet Team Soapbox' follow-pack card from
the top of the page to the bottom, after the FAQ.
Help page now opens with an amber disclaimer that Agora is recommended
only for above-ground activism, followed by two large buttons routing to
new /help/donors and /help/activists guide pages.
The guides cover how on-chain donations work on Agora, why they're
publicly visible on the Bitcoin blockchain and Nostr, and the main paths
for protecting donor privacy or cashing out privately (non-KYC purchase,
coinjoin, Lightning swaps via Boltz, peer-to-peer exchanges like Bisq
and RoboSats). Each tradeoff section is rendered as Pros/Cons bullets.
Also adds an 'About Agora' FAQ category to the existing accordion
covering the design rationale for not using Lightning, silent payments,
or server-rotated addresses.
The inline-markup renderer used by FAQ answers is extracted to
src/lib/helpMarkup.tsx so it can be reused by the guide pages.
Drop the destructive treatment from the disclaimer on campaign donation
surfaces — donating isn't itself dangerous, just publicly traceable, so
red + alert icon + a hard checkbox gate overstated the risk.
Add a 'soft' tone to BitcoinPublicDisclaimer (amber, no icon, no role=
alert) and an includeCashOutAdvice flag so the popover can omit the 'or
cash out at an exchange' line — relevant for the wallet (donor holds
sats) but not for a campaign donor sending money away.
The wallet's Send dialog keeps the destructive variant with the
acknowledgement checkbox unchanged.
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).
Removes NIP-58 badge-award membership validation from Agora's
organization model. Authorization collapses to two roles:
- Founder = author of the kind 34550 event (only the founder can edit
organization metadata, enforced by replaceable-event semantics).
- Moderators = `p` tags with role "moderator" on that event (can hide
content via kind 1984 content-bans; cannot edit the org).
There is no "member" tier any more. The kind 8 / kind 30009 chain
that previously gated discussion access, the members-only feed
filter, the avatar-stack member count, and member-ban moderation
actions are all gone.
What changes:
- `useCommunityMembers` returns `{ founderPubkey, moderatorPubkeys }`
read directly from the parsed community event. The kind 8 badge
query, `resolveMembership`, `isAuthorizedAward`, and the rank-1
member tier are removed. The hook still queries kind 1984 events
scoped to the org so content-bans and soft reports keep working.
- `applyCommunityModerationToEvents` keeps content-ban filtering for
founder/mods. `resolveCommunityModeration` is simplified to a
single pass — only founder/moderators can publish moderation
actions, and the parsed report classification drops the
`member-ban` action since wholesale member bans no longer exist.
- `BanConfirmDialog` drops `mode="member"`. Only event-level content
bans remain. `NoteMoreMenu` drops the "Ban from community"
affordance accordingly.
- `ParsedCommunity` loses `memberBadgeATag` and
`memberBadgeRelayHint`. `parseCommunityEvent` no longer reads the
`['a', '30009:…', '', 'member']` tag. `CreateCommunityPage` no
longer mints a "Member of <org>" badge or attaches the member-badge
tag, and on edit it strips any pre-existing member-badge tag so
legacy wiring doesn't linger.
- The "Voices from everywhere" cross-organization activity feed is
deleted from the Organize page. It duplicated per-org activity (now
served by the official-activity shelves on each org detail page)
and was the only consumer of `useCommunityActivityFeed`.
`useFollowingFeed` drops its community-feed leg for the same
reason. `useMyCommunities`, `useMembersOnlyFilter`, and
`MembersOnlyToggle` go with it.
- `CommunityDetailPage` loses the MembersOnlyToggle in the hero, the
"Add members" and "Edit badge" overflow-menu items, and the
per-member ban affordance in the members dialog. The avatar stack
now renders founder + moderators with a "Founder + N moderators"
label and the dialog title becomes "Leadership".
- Deleted: `AddMemberDialog`, `CommunityBadgePanel` (which exported
`CommunityBadgeEditorDialog`), `useCommunityActivityFeed`,
`useMyCommunities`, `useMembersOnlyFilter`, `MembersOnlyToggle`,
plus three already-unused legacy components (`CommunityChatPanel`,
`CommunityPulsePanel`, `CreateCommunityDialog`) and
`useCommunityChatMessages`. `PersonSearch` is extracted from the
deleted `AddMemberDialog` into its own file so the create-campaign
and create-community forms keep their member-picker UI.
The standalone NIP-58 badge tooling (`BadgesPage`, `GiveBadgeDialog`,
`useBadgeFeed`, etc.) is untouched — it's a separate feature surface
from organization membership and continues to work.
Out of scope: file/symbol renames (Community* → Organization*).
That's the next commit.
Updates the Organize page (/communities) for the organization-first
direction:
- All user-visible "Community" copy becomes "Organization" — page
title, hero subtitle, section headers, empty states, logged-out
prompts, members-only filter messaging, and the create-organization
CTA. The route, file name, and internal symbols are unchanged for
this commit; the codebase-wide rename is the next pass.
- "My organizations" replaces "My communities". Wired to
`useManageableOrganizations` instead of `useMyCommunities`, so the
shelf reflects the same trust model used for implicit org tagging in
the create flows — organizations the user either founded (author of
the kind 34550 event) or is listed as a moderator on (`p` tag with
role "moderator"). The badge-award member-validation path is no
longer surfaced here.
- "Featured organizations" replaces "Discover communities". Backed by
a new `useFeaturedOrganizations` hook with a hardcoded list of
curator-approved kind 34550 event IDs in
`FEATURED_ORGANIZATION_EVENT_IDS`. Pinning by event ID locks the
card to a specific revision; bumping a featured org means swapping
in a newer ID. This is intentionally a stopgap until a configurable
featuring mechanism (AppConfig field, NIP-51 list, etc.) lands.
- The hero stat ticker still rotates donations / orgs / countries, but
the "orgs" entry now counts featured organizations instead of all
discoverable communities.
`useMyCommunities` and `useDiscoverCommunities` stay in place for now
because `useCommunityActivityFeed` and `DiscoverPage` still depend on
them. The badge-award removal pass will follow.
Restructures the org detail page body to match the rhythm already
established on /campaigns/:naddr and /pledges/:naddr:
- Container widens from `max-w-3xl` to `max-w-6xl` and the hero gets
the same `sm:aspect-[21/9]` treatment so it doesn't feel cramped at
the wider viewport width.
- The tab strip is removed entirely. Activity was the only visible tab
and the Pulse / Chat triggers were already hidden. With one section
left there's no reason to keep the `<Tabs>` wrapper or its plumbing
(`activeTab`, `setActiveTab`, `fabAvailable`).
- Below the hero: the existing Donate / Share action row, then the
official-activity shelves, then a new pledge-style engagement card
(stats counters + `<PostActionBar>`), then a NIP-22 comments section.
- No funding progress bar — an organization isn't a fundraising target
itself. Campaigns continue to provide that for fundraising.
- Comments render in the same `rounded-2xl bg-card border` frame the
pledge page uses, with the same "No comments yet" dashed empty
card. The legacy interleaved "initiatives + discussion" feed is
gone — official campaigns / pledges / events now live in the
shelves, and the comments section is purely NIP-22 replies.
- Adds `useEventStats`, `InteractionsModal`, `NoteMoreMenu`, and a
separate `replyOpen` slot for the engagement bar's Reply button
(the FAB's "New post" item keeps its own `composeOpen` slot so the
two entry points don't interleave state).
- Removes the now-unused `<CommunityChatPanel>`, `<CommunityPulsePanel>`,
`<ComposeBox>`, `<NoteCard>`, and `<FeedCard>` imports, along with
the `useCommunityGoals` / `useCommunityActions` / `useCommunityEvents`
hooks and the chain of derived state (`moderatedGoals`, `activeGoals`,
`pastGoals`, `eventItems`, `actionEvents`, `activeInitiatives`,
`pastInitiatives`, `activityItems`) that fed the old feed. Those
components still exist in the codebase for now; commit 4 will prune
the badge-award member runtime separately.
The FAB is now always available (single-column page) and routes
`New campaign` / `New pledge` to their dedicated create pages with
`?org=<naddr>`. `New event` still opens the in-page calendar dialog
since there's no dedicated create page for that yet.
The org detail page now surfaces three horizontally-scrolling shelves
above the activity feed:
- Campaigns (kind 30223)
- Pledges (kind 36639)
- Upcoming events (NIP-52 kinds 31922 / 31923)
All three shelves are powered by the useOrganization* hooks added in
5b5e8fe8, which author-filter to founder + moderators before querying
by the org's uppercase `A` root-scope tag. Anyone can publish an
event with an org's `A` tag, so the author filter is the actual
trust boundary that decides what counts as "official" activity for
that organization.
Each shelf is suppressed entirely when it has nothing to show, so an
org with no campaigns/pledges/events keeps the discussion feed at the
top of the viewport.
The activity-tab FAB now routes campaign and pledge creation to the
dedicated create pages with `?org=<naddr>` in the query string,
closing the loop with the implicit-tagging change from 8bef15a3. The
in-page `CreateGoalDialog` and `CreateActionDialog` are removed —
zap goals are being deprecated in favor of campaigns, and pledges now
go through the dedicated create page. The calendar-event dialog stays
in-page since there's no dedicated create page yet; it already emits
the uppercase `A` tag.
Pulse and Chat tab triggers are hidden from the tab strip while the
organization-first redesign is in progress. The corresponding
`<TabsContent>` panels are left intact so the code paths stay
verified — only the trigger affordances are suppressed.
The stats row had a `pb-2` and the PostActionBar received a `pt-3`
className when stats were present — leftover spacing from when a
horizontal divider sat between them. With the divider removed the
padding became an unjustified gap above the action bar.
Drop both so the action bar sits flush against the stats row with
even top/bottom spacing inside the engagement card, matching the
no-divider look the campaign details page already has when stats
are absent.
Restore the `pt-3 border-t border-border/60` divider/padding
that separates engagement counts from the action bar, identical
to the campaign details page. The earlier `pt-3` without the
border left dead space; with the border back, the two pages
share the same visual rhythm.
Pledge cards render their cover image with a built-in fallback:
when `action.image` is unset or fails to load, they fall back to
`DEFAULT_COVER_IMAGE`. The detail-page hero only handled the
unset case (with a gradient + icon) and never recovered from a
broken URL.
Mirror the card pattern in the hero: render an `<img>` with an
`onError` handler that swaps in `DEFAULT_COVER_IMAGE` on load
failure, so pledges without a cover (or with a dead one) still
look intentional instead of blank.
Remove visual clutter from the pledge detail page:
- Drop the "Pledge" badge and description preview from the hero
overlay so the cover image and title carry the framing.
- Remove the divider between engagement counts and the action bar.
- Drop the "Remaining" and "Stored as sats" tiles from the
funding card — donors only need funded vs. pledged totals.
The hero cover image is unchanged; it sources `action.image`
sanitized by `sanitizeUrl`, which falls back to the gradient
placeholder only when the event has no `image` tag.
Pledges are now open-ended by default — drop the optional start
date input and stop publishing the legacy `start` tag. The kind
36639 `created_at` already marks when the pledge becomes active.
Hide the built-in cover image templates so the upload area is the
only path for cover art, encouraging pledgers to supply their own
visuals. The thumbnail strip remains available via the
`templates` prop on `CoverImageField` for other surfaces.
Rename the description heading from "Story" to "Description"
to avoid implying a narrative expectation, and label the optional
tag input as "Recommended" to nudge categorization.
Mirror the same changes in `CreateActionDialog` (the community
scoped variant) and mark `start` as legacy in `NIP.md`.
Reverts the user-controlled OrganizationSelector added in b3997ec5.
Selecting an organization from inside a create form was the wrong
affordance: if a user starts a pledge or campaign from outside any
organization, the publication is implicitly under their own identity,
and if they start it from inside an organization, the org tag is
already implied by where the create flow was launched.
CreateCampaignPage and CreateActionPage now read `?org=<naddr|aTag>`
from the URL instead of rendering a selector field. When the param is
present, useManageableOrganizations checks whether the current user is
the founder or a moderator of that org; if so, the form emits the
`A` / `K` / `P` tags on publish. If not, the param is silently
dropped (so a stale or copy-pasted link can't forge an org-tagged
event), and a small note explains the publication is going under the
user's account.
OrganizationContextChip is a tiny shared component that surfaces the
resolved org as a non-interactive chip under the form title. The
organization detail page CTAs (next commit) will populate `?org=`
when launching the create flow from inside an org.
OrganizationSelector.tsx is removed — no other call sites.
Adds an optional Organization selector to the create-campaign and
create-pledge forms. Only NIP-72 communities where the current user
is the founder or a listed moderator are offered, so the resulting
event's uppercase `A` root-scope tag lines up with the trust filter
applied by useOrganizationCampaigns / useOrganizationPledges.
Technically anyone could publish a kind 30223 or 36639 with another
org's `A` tag outside the Agora client. Restricting the selector
inside the client is the first line of defense; the author-filter in
the org-detail queries (next commits) is the actual security boundary.
Changes:
- useManageableOrganizations queries kind 34550 events the user
founded (`authors`) or is moderator-tagged on (`#p`), then keeps
only the ones where they're founder OR moderator.
- OrganizationSelector renders those orgs in a popover combobox with
Founder / Moderator badges, plus a 'No organization' option.
- CreateCampaignPage and CreateActionPage gain a new optional 'Publish
under organization' field. On publish, the form emits
`A: 34550:<pubkey>:<d>` plus the `K` and `P` companion tags.
- CreateCampaignPage hydrates the selector from an existing campaign's
`A` tag when editing.
Existing campaigns and pledges without an `A` tag continue to work
unchanged.