Experts Page
v1.0.0Added in 1.8.0
A Hire an Expert directory: search, filters and sort over certified consultants and agencies, profiles, proposal requests and a matcher.
The hero rises in once beside a drawn cluster of expert profile cards (an Elite agency with its rating, services and starting price, a Premier consultant tilted behind, and on wide screens a proposal-sent chip and a five-star review). The search bar filters the directory as you type; the Location and Budget selects set the region and price filters, Find experts (or Enter) scrolls to the directory, and the Popular chips pick one service. On desktop a sidebar holds the filters: service checkboxes with live counts, a two-thumb starting price slider, tier, region, language and industry chips (options with no matches are disabled) and an Available now switch; on phones and tablets a Filters button (with the active count) opens a full-height bottom sheet whose filters apply only on Show N experts. Active filters show as removable chips with Clear all; Sort picks Recommended, Highest rated or Price low to high; cards animate into place, eight show before Show more, and no match shows an empty state with Clear all. Any card (the whole card is one target) opens the profile: a large dialog on desktop and a bottom sheet on phones with the about text, packages with price ranges, case studies drawn as before and after boards, a rating breakdown and reviews, and a facts panel. Request a proposal swaps in a form (project type, budget, timeline, description, name, work email) that checks every field, shows the errors under them and focuses the first; Send spins while onRequest runs, a rejection shows an error, then a success view names who replies and when, and the card shows Request sent. The matcher asks three questions as big choice tiles with a progress bar and Back, then ranks the top three experts with animated match bars that open their profiles; Start over resets it. Steps, the Elite agencies rail (snap scrolling on phones), customer quotes, FAQ, the Become an Acme Expert band and the closing call follow. Reduced motion keeps everything still.
Built with
The sections this page is made of. In the full-screen preview, hold Alt to outline each one on the page.
Add to a project
npx wingo-ui@latest add experts-pagePro item: the CLI needs a Pro account. See plans
Usage
// app/(marketing)/experts/page.tsx
"use client"
import Link from "next/link"
import { ExpertsPage } from "@/components/templates/experts-page"
export default function ExpertsRoute() {
return (
<ExpertsPage
linkComponent={Link}
ctaTone="brand"
onRequest={async (expert, values) => {
const response = await fetch("/api/experts/requests", {
method: "POST",
body: JSON.stringify({ expertId: expert.id, ...values }),
})
if (!response.ok) throw new Error("Could not send the request")
}}
/>
)
}Props
designdefault"classic""classic" | "bold" | "minimal"The whole page's look. classic follows the layout props: a split hero with drawn profile cards over a dotted glow; bold: a pill header, a giant stage title on a gradient mesh, rounder cards, an inverted Elite panel, step cards, a quote wall, FAQ cards, a band and a wordmark footer; minimal: a transparent header, a centered quiet hero without cards, flat outlined cards, no gray bands and a simple footer. The *Props overrides still win.
expertsdefault"EXPERTS"Expert[]The directory: { id, name, kind, tagline, about, location, region, timeZone, languages, services, industries, startingPrice, rating, reviewCount, projects, responseHours, tier, availableNow, availability, contact, packages, caseStudies, reviews, ... }.
servicesdefault"EXPERT_SERVICES"ExpertOption[]Service filter options and matcher answers: { value, label, description? }.
industriesdefault"EXPERT_INDUSTRIES"ExpertOption[]Industry filter chips and matcher answers.
languagesdefault"EXPERT_LANGUAGES"ExpertOption[]Language filter chips; expert languages are these values.
regionsdefault"EXPERT_REGIONS"ExpertOption[]Region filter chips and the hero's Location select.
tiersdefault"EXPERT_TIERS"ExpertOption[]Elite, Premier and Certified, with their badge labels.
budgetsdefault"EXPERTS_BUDGETS"ExpertsBudgetOption[]The hero's Budget select and the matcher's budget answers: { value, label, min, max } in USD.
quickSearchesdefault"EXPERTS_QUICK_SEARCHES"ExpertsQuickSearch[]The Popular chips under the search bar: { label, service }.
proposalBudgetsdefault"EXPERTS_PROPOSAL_BUDGETS"ExpertOption[]The proposal form's budget ranges; empty drops the field.
timelinesdefault"EXPERTS_TIMELINES"ExpertOption[]The proposal form's timeline options; empty drops the field.
heroExpertsdefault"EXPERTS_HERO"string[]Expert ids drawn in the hero: [front card, back card, review].
stepsdefault"EXPERTS_STEPS"StepsSectionItem[]How hiring works: { icon?, title, description, meta? }.
testimonialsdefault"EXPERTS_TESTIMONIALS"Testimonial[]Customers who hired experts: { quote, name, role?, company?, companyIcon?, rating?, metric? }.
faqdefault"EXPERTS_FAQ"FaqItem[]{ question, answer } pairs about hiring an expert.
becomePerksdefault"EXPERTS_BECOME_PERKS"string[]The three lines in the Become an Acme Expert band.
labelsdefault"DEFAULT_EXPERTS_PAGE_LABELS"Partial<ExpertsPageLabels>Every visible string; the ones with numbers or names in them are functions.
hrefsdefault"DEFAULT_EXPERTS_PAGE_HREFS"Partial<ExpertsPageHrefs>{ directory, matcher, become, requirements, sales, privacy }.
querystringThe controlled search text; pair it with onQueryChange.
defaultQuerydefault""stringThe search text on load.
onQueryChange(query: string) => voidEvery keystroke in the search bar.
filtersExpertsFiltersThe controlled filters: { services, industries, languages, regions, tiers, budget: [min, max], availableNow }.
defaultFiltersPartial<ExpertsFilters>The filters on load, merged over DEFAULT_EXPERTS_FILTERS.
onFiltersChange(filters: ExpertsFilters) => voidAny filter changed (the phone sheet reports on Apply).
sort"recommended" | "rating" | "price"The controlled sort; pair it with onSortChange.
defaultSortdefault"recommended""recommended" | "rating" | "price"The sort on load: tier, rating and availability; highest rated; or price low to high.
onSortChange(sort: ExpertSort) => voidThe sort changed.
pageSizedefault8numberCards shown before Show more; 0 shows every match.
loadingdefaultfalsebooleanThe directory shows card skeletons.
onRequest(expert: Expert, values: ExpertProposalRequest) => (void | Promise<unknown>)A proposal request: { projectType, budget, timeline, description, name, email }. A promise keeps Send loading and a rejection shows an error. Without it the form waits 900 ms and shows the success view.
onExpertOpen(expert: Expert) => voidA profile was opened (analytics, a URL update).
showQuickSearchesdefaulttruebooleanThe Popular chips under the search bar.
showHeroCardsdefaulttruebooleanThe drawn profile cards in the hero (classic and bold).
showMatcherdefaulttruebooleanThe three-question matcher.
showStepsdefaulttruebooleanHow hiring works.
showElitedefaulttruebooleanThe featured Elite agencies.
showTestimonialsdefaulttruebooleanThe customer quotes.
showFaqdefaulttruebooleanThe FAQ.
showBecomedefaulttruebooleanThe Become an Acme Expert band linking to /partners.
showCtadefaulttruebooleanThe closing call to action.
stepsLayoutdefault"horizontal""horizontal" | "cards" | "vertical"How hiring works as a numbered row, numbered tiles or a timeline rail. Applies to the classic design.
testimonialsLayoutdefault"featured""featured" | "grid" | "carousel" | "marquee"Customer quotes as one big quote and two small, a grid, a swipeable rail or drifting rows. Applies to the classic design.
ctaVariantdefault"inverted""inverted" | "soft" | "split"The closing band: a solid band, a gray band, or copy beside the buttons. Applies to the classic design.
alternatedefaulttruebooleanGray bands on every other section. Applies to the classic and bold designs.
tonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"Accents: the hero glow, Elite badges, stars, rating bars, match bars, selected chips and checkboxes, the price slider.
ctaTonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"Find experts, Request a proposal, Send request, Apply in the filter sheet, the header's Get started and the closing band; brand is the marketing orange.
radiusdefault"md""none" | "sm" | "md" | "lg" | "full"The corners of the search bar fields, the sort select and the proposal form fields.
headerdefaulttruebooleanThe marketing header; off inside a site layout.
footerdefaulttruebooleanThe marketing footer with its newsletter form.
headerPropsPartial<MarketingHeaderProps>Passed to MarketingHeader.
footerPropsPartial<MarketingFooterProps>Passed to MarketingFooter.
stepsPropsPartial<StepsSectionProps>Overrides for the StepsSection.
testimonialsPropsPartial<TestimonialsSectionProps>Overrides for the TestimonialsSection.
faqPropsPartial<FaqSectionProps>Overrides for the FaqSection.
ctaPropsPartial<CtaSectionProps>Overrides for the CtaSection.
onSubscribe(email: string) => (void | Promise<unknown>)The footer newsletter; a rejected promise shows an error.
animateIndefaulttruebooleanThe hero rises in once and the profile cards tilt into place; false keeps the page still (thumbnails). Reduced motion always does.
localedefault"en-US"stringIntl locale for the USD prices, ratings, counts and review dates.
linkComponentdefault"<a>"(props: LinkComponentProps) => ReactNodeThe router link for every link on the page (next/link in an app).
classNamestringClasses for the root.
classNamesPartial<Record<ExpertsPageSlot, string>>Classes for header, hero, title, search, cluster, directory, sidebar, toolbar, chips, grid, card, profile, form, matcher, steps, elite, testimonials, faq, become, cta and footer.
Parts
EXPERTS_PAGE_SAMPLE
constantAll the sample content in one object: experts, filter options, budgets, quick searches, form options, hero ids, steps, testimonials, faq and perks.
EXPERTS
constantSixteen fictional experts: agencies like Brightside Ops, Northpeak Studio and Fieldwork Collective, and independents across four regions.
EXPERT_SERVICES
constantMigration, Automations, Team training, Custom integrations, Workspace setup and Reporting.
EXPERT_INDUSTRIES
constantSoftware, Agencies, Healthcare, Ecommerce, Finance and Nonprofits.
EXPERT_LANGUAGES
constantEight languages as { value, label }.
EXPERT_REGIONS
constantNorth America, Latin America, Europe and Asia Pacific.
EXPERT_TIERS
constantElite, Premier and Certified with what each means.
EXPERTS_BUDGETS
constantAny budget, under $2,500, $2,500 to $5,000 and $5,000 and up.
EXPERTS_QUICK_SEARCHES
constantThe four Popular chips.
EXPERTS_PROPOSAL_BUDGETS
constantThe proposal form's budget ranges.
EXPERTS_TIMELINES
constantThe proposal form's timelines.
EXPERTS_HERO
constantThe expert ids drawn in the hero.
EXPERTS_STEPS
constantTell us what you need, compare proposals, kick off with confidence.
EXPERTS_TESTIMONIALS
constantSix quotes from customers who hired experts.
EXPERTS_FAQ
constantSix questions about vetting, cost, fees, guarantees, security and retainers.
EXPERTS_BECOME_PERKS
constantThe perks listed in the Become an Acme Expert band.
EXPERTS_BUDGET_MAX
constant10000: the price slider's end, read as "and up".
EXPERTS_BUDGET_STEP
constant250: the price slider's step.
DEFAULT_EXPERTS_FILTERS
constantNo filters: every list empty, the full price range, availableNow false.
getExpertMatch
functionThe matcher's score: (expert, { service?, industry?, budget? }, budgets?) => a 40 to 98 match percentage.
getExpertRatingBreakdown
function(rating, count) => the review counts at 5, 4, 3, 2 and 1 stars, for the profile's bars.
DEFAULT_EXPERTS_PAGE_LABELS
constantThe English strings.
DEFAULT_EXPERTS_PAGE_HREFS
constantThe default link targets.
EXPERTS_PAGE_DESIGNS
constantThe design names, classic first: ["classic", "bold", "minimal"].
ExpertsPageProps
typeProps of ExpertsPage.
ExpertsPageDesign
type"classic" | "bold" | "minimal".
Expert
typeOne expert or agency in the directory.
ExpertTier
type"certified" | "premier" | "elite".
ExpertSort
type"recommended" | "rating" | "price".
ExpertsFilters
typeThe directory's filters.
ExpertProposalRequest
typeThe proposal form's values passed to onRequest.
ExpertsPageLabels
typeThe strings labels can override.
ExpertsPageHrefs
typeThe link targets hrefs can override.
Examples
Bold design
design="bold": a giant stage title on a gradient mesh, rounder cards, an inverted Elite panel, a quote wall and a wordmark footer.
Minimal design
design="minimal": a transparent header, a centered quiet hero, flat outlined cards, no gray bands and a simple footer.
Pre-filtered in brand orange
defaultFilters for migration experts available now, sorted by rating, with tone and ctaTone brand.
Loading directory
loading: the directory shows card skeletons while experts load.
Request service down
An onRequest that rejects: open a profile, request a proposal and send it to see the error while every value stays in place.
Dependencies
Files
- components/templates/experts-page.tsx
- components/templates/experts-page-data.ts