@pixygon/site
v0.4.1
Published
The Pixygon website scaffold: one provider stack (theme, SEO, consent-gated analytics, auth, error boundary), design-token themes, a disciplined image component and the pinned stack manifest every Pixygon Vite site shares.
Readme
@pixygon/site
The Pixygon website scaffold. Every Pixygon Vite site mounts the same provider stack,
the same consent gate, the same SEO component and the same image discipline — from
one package instead of seven divergent copies of theme.ts, SEO.tsx and
basicAnalytics.ts.
import { foundationTheme } from '@pixygon/site';
import { PixygonSite, PixygonSEO, PixygonImage } from '@pixygon/site/react';
const theme = foundationTheme(); // or brandTheme('lonnlyst') / createSiteTheme({...})
root.render(
<PixygonSite
theme={theme}
analytics={{ projectId: '…', appName: 'Pixygon', endpoint: 'https://api.pixygon.io/v1/analytics', ga4Id: 'G-…' }}
auth={{ apiUrl: 'https://api.pixygon.io', projectId: '…' }} // omit on sites without accounts
>
<App />
</PixygonSite>
);What <PixygonSite> mounts, outermost first: ErrorBoundary → HelmetProvider →
MUI ThemeProvider + CssBaseline → AnalyticsGate (three-state consent from
@pixygon/analytics, driven by this package's consent store) → AuthProvider →
BrowserRouter from react-router (router={false} if the app owns routing) → Suspense with
<PageLoader> → skip link, your app, <ConsentBanner>.
Consent
getConsent / subscribeConsent / acceptConsent / declineConsent / resetConsent
share one localStorage key across the estate. Undecided visitors are counted in
consent-free basic mode (page views + conversions, nothing stored on the device);
accepted starts the full SDK and GA4 (when ga4Id is set); declined stops
everything and wipes px_* storage and _ga cookies. useConsent() gives
components the live value. Register side effects with onConsentDecision.
Theme
createSiteTheme({ mode, primary, secondary, background, paper, fontFamily,
headingFamily, overrides }) is the whole theme surface. brandTheme(key) reads the
design canon (@pixygon/design/tokens.mjs, frozen at build time) for a brand;
foundationTheme() is the Pixygon master brand.
Images
<PixygonImage src width height alt [priority] [widths] [sizes]> — sized, lazy
unless priority, async-decoded, and served through a srcSet of -{w}.webp
variants when src is on a Pixygon CDN host (variants are made by pearl images).
variantUrl / srcSetFor are exported for CSS backgrounds.
Stack manifest
stack.json pins the versions every site should be on. pearl doctor diffs a
site's package.json against it.
Engine guide pages (GuidePage + prebuild.mjs)
The SEO engine (PixygonAPI /v1/seo/*) writes search-gap pages per product. Any site renders them with one route:
import { GuidePage } from '@pixygon/site/react';
import { seoPages } from '@/data/seoPages.generated'; // written by the prebuild step
<Route path="/guide/:slug" element={<GuidePage project="tastarium" siteUrl="https://tastarium.com" siteName="Tastarium" ogImage="https://tastarium.com/og.png" baked={seoPages} defaultCta={{ label: 'Start your library', to: '/register' }} strings={{ chip: 'Guide', faqHeading: 'FAQ' }} />} />and one script so the prerender and the sitemap see the pages without a network call:
"prebuild": "node node_modules/@pixygon/site/prebuild.mjs --project=tastarium --site=https://tastarium.com --out=src/data/seoPages.generated.ts"Then set profile.extra.seo.createPages = true on the product's Board so the weekly engine creates pages there.
