@boomspot/pro-ui
v0.2.1
Published
Shared Vagaro Pro React components for the incremental CMS migration
Readme
@boomspot/pro-ui
Shared React components for Sales_Pages_App and sales-marketing-pages-payloadcms during the CMS migration. The first component is Award Voting. Both adapters use the small Vagaro business icon.
Ownership
| Shared library | Each app | | --- | --- | | Layout, headings, nominee cards, icons | CMS queries, caching, generated CMS types | | Grouping and unique award anchors | Image rendering, optimization and focal points | | Accordion, mobile disclosure, scroll spy, deep links | Typeform integration, routing and localization | | Tailwind utility classes | Theme tokens, fonts, page padding, public image URLs |
The library accepts CMS-independent view data. The adapters map the existing program into that data and supply image/action React elements. Neither Payload nor Hygraph is a library dependency. React and React DOM are peers; the package does not bundle its own React.
award-voting is the server-compatible entry. award-voting/client contains the interactive navigation with its preserved use client directive. Server adapters compose image/action slots and invoke renderNavigation on the server; only serializable navigation groups cross into the client wrapper. Lenis stays in each app's client wrapper, so it uses the app's existing provider.
Develop and verify
pnpm install --frozen-lockfile
pnpm test
pnpm dev # watch and rebuild compiled ESM and declarationsThere is no bundler: TypeScript emits individual ESM modules and preserves client directives. The package exports built JavaScript and types, so consumers do not need transpilePackages for this package.
Install in both apps
The package is published publicly to npm under @boomspot. Consumers can install
it without an npm token or login.
# Sales_Pages_App
npm install --save-exact @boomspot/[email protected]
# sales-marketing-pages-payloadcms
pnpm add --save-exact @boomspot/[email protected]Commit each app's manifest and lockfile. For publishing, authenticate as an
account with package write access using npm login, then use pnpm release
(see Automated npm releases below). Published changes do not automatically update
either app. For unpublished local testing, pnpm pack creates a local tarball.
Register the Tailwind source
Both apps use Tailwind 4. Add a source directive to each existing global stylesheet; keep its current imports and theme declarations.
Sales_Pages_App/src/styles/globals.css:
@source "../../node_modules/@boomspot/pro-ui/dist"; sales-marketing-pages-payloadcms/src/app/(frontend)/globals.css:
@source "../../../node_modules/@boomspot/pro-ui/dist";Tailwind excludes dependencies from automatic detection. These paths are relative to the stylesheet, as described in the Tailwind source detection documentation.
The components use the hosts' existing primary, charcoal, and font-instrument-serif tokens and default spacing/breakpoints. No global reset or font is shipped. SVG icons are inline. frameSrc must point to the host's existing nominee frame image; an npm package's assets do not automatically become public URLs.
Apply the prepared adapters
These files are proposed replacements; neither app has been edited by this project.
| File here | Destination in its app |
| --- | --- |
| examples/sales-pages-app/IconicVoting.tsx | src/components/surveys/IconicVoting.tsx |
| examples/sales-pages-app/IconicVotingNav.tsx | src/components/surveys/IconicVotingNav.tsx |
| examples/payloadcms/Component.tsx | src/blocks/pro/AwardVoting/Component.tsx |
| examples/payloadcms/Nav.client.tsx | src/blocks/pro/AwardVoting/Nav.client.tsx |
The legacy adapter preserves fetchProgram, DEFAULT_PROGRAM_KEY, toSlug, and the exported CMS types because IconicNominations also uses that module. It preserves the legacy anchor normalization and switches nominee business links to the small icon. After applying it, remove the old IconicAwardSection.tsx and IconicNomineeCard.tsx once you confirm no remaining imports; their voting rendering is now in this package.
The Payload adapter preserves block padding, section anchors, localized links, Typeform decisions, Media rendering and crop settings. No CMS schema changes are needed.
Validate adapter types without modifying either app:
node scripts/check-adapters.mjs legacy /absolute/path/to/Sales_Pages_App
node scripts/check-adapters.mjs payload /absolute/path/to/sales-marketing-pages-payloadcmsThis checks the replacement files against each app's installed types and dependencies; it is not a full app build. After installing and applying, run each app's checks and review the actual award page on desktop/mobile, including images, a Typeform vote, a normal vote link, and a direct #award URL.
Add another shared component
- Define view props in the library without importing CMS types or app aliases.
- Implement the shared markup and styles here. Put hooks/browser APIs in an explicitly marked client module.
- Map each CMS's fields in a small server adapter. Use React element slots for app-specific images, links, forms and rich text.
- Add a package subpath export, verify it, and release a new version for both apps.
Award Voting usage:
import { AwardVoting } from '@boomspot/pro-ui/award-voting'
<AwardVoting
frameSrc="/award-voting/nominee-frame.png"
categories={[{
label: 'Hair',
group: 'Industry',
awards: [{
title: 'Barber of the Year',
action: <YourVoteAction />,
nominees: [{
name: 'Alex',
image: <YourImage />,
businessLink: 'https://www.vagaro.com/example',
}],
}],
}]}
/>A single voting block keeps existing unprefixed award hashes by default. For multiple voting blocks on one page, give every instance a distinct anchorPrefix, such as iconic-2026- and iconic-2027-. The shared model applies it to both section IDs and navigation URLs. Navigation disclosure IDs are unique automatically; custom idPrefix values must also be unique.
Local component preview
Run pnpm preview and open http://127.0.0.1:3030/.
The preview imports local src/ components directly, so source edits reload the page without publishing. Switch between Award Voting and Iconic Nominations. Edit preview/fixtures.tsx for sample categories, nominees, descriptions, images and actions; edit preview/styles.css for the preview host's theme.
This is an isolated client-rendered visual playground with local sample content and demo dialogs. It does not query or modify Payload and does not submit votes. It is not a substitute for checking server rendering, Media optimization, or Typeform in the consuming Next.js app. pnpm preview:build builds the standalone preview separately from the npm package.
Iconic Nominations (0.2.0)
Import IconicNominations, NominationArrow and NOMINATION_LINK_CLASSES from
@boomspot/pro-ui/iconic-nominations. Provide categories shaped as
{ id, label, cards }, where cards have id, heading, paragraph, image
and action. Images and actions are React elements composed by the host adapter.
Empty categories are omitted. Optional heading, id, and className props
control the section heading, anchor and host spacing.
import { IconicNominations } from '@boomspot/pro-ui/iconic-nominations'
<IconicNominations
heading="Nominate your business"
categories={[{
id: 'hair',
label: 'Hair',
cards: [{
id: 'stylist',
heading: 'Stylist of the Year',
paragraph: 'Recognizing outstanding work.',
image: <YourImage />,
action: <YourApplicationLink />,
}],
}]}
/>Category IDs must be stable, unique URL hashes. all is reserved; prefix IDs
when rendering multiple nominations blocks on one page. A category with a null
ID/label appears only under View All.
For Lenis, pass a server-side renderTabs={panels => <YourClientTabs categories={panels} />}
callback. That client wrapper imports IconicNominationsClient from
@boomspot/pro-ui/iconic-nominations/client and constructs a stable scrollTo
callback locally. It receives the root HTMLElement and should jump immediately
with the host's header offset. The default navigation uses native scrolling.
Client props also support allLabel and navigationLabel.
The Payload block config, generated CMS types, Media rendering, localized links
and Typeform remain in the consuming app. This release does not register a
Payload block automatically. The existing Tailwind @source covers both exports.
Automated npm releases
Authenticate once with npm login, then run from this repository:
pnpm release --dry-run # tests and pack/publish preview; no version change or upload
pnpm release # patch bump, tests/build, pack and public publish
pnpm release minor # minor bump for new components/features
pnpm release major # major bump
pnpm release current # publish the current version without bumping (e.g. retry)Tests run before any version change. The script publishes an exact tarball with public access to npm and leaves the terminal connected for npm browser/2FA authentication. A dry run uses the current version even if a bump argument is provided, and skips npm authentication and publishing entirely. It lists the archive contents and displays the intended publish command.
If publishing fails after the bump, the new version remains in package.json.
Check whether npm accepted the release before retrying pnpm release current;
never reuse a version that is already published. Git commits, tags and pushes
are separate actions. After success, commit the version change and update each
consuming app to the new version.
See npm publish for the underlying publishing and access options.
