Build your job board
Turn the public Board API into jobs, content, candidate, and employer experiences.
A
JThis section takes you from a public jobs catalog to a complete custom job board. Each guide produces one working product surface and makes the boundary clear: Cavuno owns the data and business rules; your application owns the routes, interface, and deployment.
Before you start
Complete Set up the SDK by hand and export one shared board client. You also need:
- A
pk_…board key. The SDK useshttps://api.cavuno.comby default. - A public origin such as
https://jobs.example.comfor canonical URLs. - A server-owned session before calling anything under
board.me.
Do not assume every board enables every surface. Load the context once and use its flags to decide which routes and navigation items exist:
12345678910111213const context = await board.context();const routes = {alerts: context.features.jobAlerts,candidateAccount: context.features.candidates,employerAccount: context.features.employers,blog: context.features.blog,publicJobPosting: context.features.publicJobSubmission,candidatePaywall: context.features.candidatePaywall,talent:context.talentDirectoryVisibility === 'public' ||context.talentDirectoryVisibility === 'employers_only',};
features.talentDirectory is only true for a public directory. Use talentDirectoryVisibility when deciding whether to link /talent; an employers_only directory should lead anonymous visitors to an employer sign-in or upsell.
Choose a build sequence
- Build jobs and search, then companies. These public reads establish routing, pagination, error handling, and caching.
- Add blog and salaries only when you have content to publish.
- Add candidate accounts and talent, then applications.
- Add job alerts and messaging.
- Add employer self-service and job posting and checkout.
- Add candidate paywalls last, after authenticated sessions and protected rendering are correct.
Keep public and private reads separate
Public catalog pages can be cached. Candidate and employer responses cannot. On a server-rendered app, keep the shared client stateless and pass the viewer’s access token per request:
1234567const applications = await board.me.applications.list({ limit: 20 },{cache: 'no-store',headers: { authorization: `Bearer ${accessToken}` },},);
Never place an access token in a public environment variable, shared cache key, or module-scoped SDK storage.
Verify each surface
For every guide, verify the same four things before moving on:
- The enabled route returns real board data.
- A disabled feature is removed from navigation and cannot be reached through your UI.
- A missing resource becomes your framework’s 404, while other
BoardApiErrorvalues remain visible to logging and support. - Authenticated responses use
cache: 'no-store'and cannot cross user sessions.
Start with jobs and search.
Jobs and search
Build paginated job discovery, faceted search, canonical details, and related jobs.
Companies
Build company directories, market pages, profiles, and company-specific job lists.
Blog
Build post indexes, article pages, archives, search, and related-content navigation.
Salaries
Build indexable salary hubs and title, skill, company, and location detail pages.
Candidate accounts and talent
Build candidate profiles and resume import, then expose the permitted talent directory.
Applications
Build guest and signed-in apply flows, resume upload, history, editing, and withdrawal.
Job alerts
Build double-opt-in email alerts and signed-in alert management without mixing token models.
Messaging
Build a polled candidate-employer inbox with read state, editing, moderation, and blocks.
Employer self-service
Let approved employers claim companies, manage jobs, and review applicants.
Job posting and checkout
Build public plan selection, job submission, reusable billing, invoices, and checkout.
Candidate paywalls
Build candidate offer selection, embedded checkout, entitlement checks, and billing management.