Terminology reference: every term, how we use it, and why
Terminology reference: every term, how we use it, and why
Organizations can customize language across the app so labels match their mission (e.g. "Need" → "Request", "Area" → "Region"). The terminology service (lib/services/terminologyService.ts) loads these from the Organization model and exposes them as OrganizationTerminology. Singular terms are stored in the DB; plurals are derived automatically.
Entity terms (singular + plural)
These label things in the system. We store the singular in the DB; the service derives the plural (e.g. "Need" → "Needs").
area termArea "Area" Geographic/service regions (e.g. "North County") Nav, org pages, volunteer signup ("your area"), emails, coordinator dashboard ("your assigned areas"), need cards, area discovery/filters Orgs may say "Region", "Zone", "County", etc. need termNeed "Need" A posted request for help (family need) Admin nav "Needs", needs tables/pages, emails ("a need", "needs completed"), need cards, filters, coordinator dashboard "Recent Needs" Orgs may say "Request", "Ask", "Opportunity". volunteer termVolunteer "Volunteer" Community members who sign up to get notifications and claim needs Admin nav "Volunteers", volunteers table/pages, reports; public/emails: "Become a Volunteer", claim emails ("a volunteer has stepped forward"), welcome email, need cards ("X volunteers needed"), impact stats Matches how the org refers to this role in public and admin. caseWorker termCaseWorker "Case Worker" Staff who post needs and coordinate (User role: case_worker) Admin nav "Case Workers" link, coordinator dashboard ("Case Workers" stat, "Top Performing Case Workers"), case worker welcome email Orgs may say "Family Advocate", "Coordinator", etc. category termCategory "Category" Need categories (e.g. Food, Housing) Category filters, settings, reports Orgs may use different category names. story termStory "Story" Success story / outcome after a need is completed Stories feature, story-related copy Orgs may say "Outcome", "Impact Story". donation termDonation "Donation" In-kind or monetary donation offers Admin nav "Offers" (donation.plural), offer/donation flows, emails Orgs may say "Offer", "Gift", "Contribution".Action terms (single label, no plural)
These label actions or buttons (one word or short phrase).
termBrowse termBrowse "Browse" Browsing/listing content Emails ("Browse available needs"), buttons ("Browse Open Needs") Orgs may say "View", "Explore", "See". termJoinUs termJoinUs "Join Us" Sign-up / get-involved CTA Homepage hero, CTAs, volunteer signup entry points Orgs may say "Get Involved", "Sign Up", "Join Our Community". termDonate termDonate "Donate" Donation action Donation flows, buttons, emails Matches org language for giving. termClaim termClaim "Claim" Action to claim a need (volunteer says "I'll help") Emails ("Claim this need", "claimed"), buttons ("Claim This Need"), welcome copy Orgs may say "Respond", "Help", "Sign Up". termSubmit termSubmit "Submit" Submitting a form (e.g. need, offer) Form buttons, confirmation copy Keeps button/action language consistent. termRespond termRespond "Respond" Responding to a need or message Emails, instructions Orgs may prefer "Reply", "Answer".Status terms (single label)
These label states of a need or entity (e.g. in tables, filters, emails).
termActive termActive "Active" Active/subscribed state (e.g. active volunteers, active needs) Admin dashboard ("Active Needs"), stats, filters Orgs may say "Open", "Current", "Live". termAvailable termAvailable "Available" Available to be claimed "Available needs", filters, emails Orgs may say "Open", "Unclaimed". termClaimed termClaimed "Claimed" Need has been claimed by a volunteer Status chips, emails ("Need Claimed"), filters Orgs may say "Matched", "In Progress". termCompleted termCompleted "Completed" Need has been fulfilled Status chips, dashboard ("Completed Needs"), filters, emails Orgs may say "Fulfilled", "Done", "Closed".Descriptive terms (single label)
These label concepts or sections in the UI and emails.
termServiceAreas termServiceAreas "Service Areas" The set of areas a volunteer can choose Volunteer signup, profile, "Service Areas" sections Orgs may say "Coverage Areas", "Regions", "Zones". termCommunity termCommunity "Community" The broader community (volunteers + org) Volunteer signup ("Join our community of volunteers"), emails, empty states Orgs may say "Network", "Neighborhood", "Family". termImpact termImpact "Impact" Impact / outcomes / results Reports, impact sections, homepage Orgs may say "Outcomes", "Results", "Stories".How we use them in code
- Server (e.g. admin layout, page components):
TerminologyService.getTerminologyForOrganization(organizationId) returns full terminology; pass terminology as a prop where needed. - Client components:
Receive terminology?: OrganizationTerminology and use e.g. terminology?.need.plural, terminology?.volunteer.singular. Use .toLowerCase() when the word is mid-sentence (e.g. "your assigned areas"). - Emails:
Email builders get terminology (often as terms) and interpolate it into subject, body, and button text so every email respects org language. - Defaults:
When there's no org (e.g. logged-out or error state), use TerminologyService.getDefaultTerminology() so the UI still has consistent labels.
Why we have terminology at all
- Brand and mission – Different orgs use different words ("Need" vs "Request", "Volunteer" vs "Neighbor").
- One source of truth – Admin sets labels once in Settings → Language; the same terms appear in admin UI, public pages, and emails.
- Consistency – Nav, tables, emails, and CTAs all use the same singular/plural and action/status labels for that org.
See also: docs/terminology-helper-vs-volunteer.md in the repo for the distinction between caseWorker (staff) and volunteer (community).
Ensuring terms are used everywhere (no hardcoding)
To keep language consistent and customizable, user-facing labels for the entities, actions, and statuses above must come from the terminology service (or its defaults), not from string literals in code.
Where terminology comes from
Admin layout Fetched in app/admin/layout.tsx; passed to AdminHeader and AdminNavigation. Layout does not pass terminology to {children}. Admin pages Each page that renders labels must call TerminologyService.getTerminologyForOrganization(organizationId) (or getDefaultTerminology() when there is no org). Pass terminology as a prop to any client component that shows entity/action/status labels. Public/org pages ([orgSlug]) Fetch in the page or in app/[orgSlug]/layout.tsx and pass to client components. Same: explicit prop. Emails Email builders receive terms from the email pipeline; use it in subject, body, and button text. Builders already receive terms; ensure every user-facing string uses it.Auditing for hardcoded terms
Search for literal strings that match the default values in the tables above. Not every hit is wrong (e.g. defaults in terminologyService.ts, placeholders in language settings, test data), but any user-facing label in app UI or emails should use terminology.
Automated check: Run npm run check:terminology (or ./scripts/check-terminology.sh). It scans app/, components/, and lib/email/ for likely hardcoded default terms, excludes known-good files (terminology service, language settings UI, Cypress, scripts, docs), and ignores lines that already use terminology or terms. Requires ripgrep (rg). Add to CI or run locally before PRs.