@cedros/data-react
v0.1.8
Published
React components, page templates, and Next.js integration for cedros-data
Readme
@cedros/data-react
@cedros/data-react is the frontend companion package for cedros-data.
It provides:
- a cedros-login
AdminShellplugin (cedrosDataPlugin) - reusable admin primitives/components
- reusable site layout components
- page templates for core/content/legal routes
- GitBook-style docs rendering with markdown support
Install
cd ui
npm installBuild and test
npm run check
npm run build
npm test
npm run test:packagedPackaging smoke:
npm pack --dry-runnow runsprepack, which rebuildsdist/and verifies every exported JS/CSS/types file before the tarball is assembled
Package exports
@cedros/data-reactCedrosDataProvider,useCedrosDataTheme,useCedrosDataThemeOptionalCmsContent,getOrCreateVisitorId,sanitizeCmsHtml,renderCmsMarkdown- theme/page/content types
@cedros/data-react/servergeneratePageMetadata,buildPageMetadatafetchBlogPost,listContentSlugs,listBlogSlugs,listLearnPathIdsloadSitemapEntries- all accept
ServerFetchOptionswith optionalapiKey(falls back toCEDROS_X_API_KEYenv)
@cedros/data-react/admincedrosDataPlugin- section IDs/groups/types
- admin components/primitives
@cedros/data-react/site-templates- site shell/layout components
- page templates (blog, docs, home, contact, legal, not-found, dashboard)
- blog features:
BlogSearchInput,FilterDimensionChips,BookmarkButton TipWidget,SOL_CURRENCY,USDC_CURRENCYContentPaywall- routing/content helpers
@cedros/data-react/admin/styles.css@cedros/data-react/site-templates/styles.css
Runtime packaging note:
- the published JS entrypoints are side-effect-free so they stay importable in Node/SSR
- import
@cedros/data-react/admin/styles.cssand/or@cedros/data-react/site-templates/styles.cssexplicitly in browser apps that need the packaged styles
Publish surface:
- npm tarballs intentionally include only
dist/,README.md, andCHANGELOG.md - source files, tests, examples, and local task notes stay out of the published package
AdminShell integration
import { AdminShell, cedrosLoginPlugin } from "@cedros/login-react";
import { cedrosDataPlugin } from "@cedros/data-react/admin";
<AdminShell
plugins={[cedrosLoginPlugin, cedrosDataPlugin]}
hostContext={{
cedrosLogin: {
user,
getAccessToken,
serverUrl: "http://localhost:8080"
},
org: { orgId: "11111111-1111-1111-1111-111111111111", role: "owner", permissions: [] },
custom: {
cedrosData: {
serverUrl: "http://localhost:8080"
}
}
}}
/>;Plugin context behavior:
- resolves
serverUrlfromcustom.cedrosData.serverUrlorcedrosLogin.serverUrl - forwards bearer token from
cedrosLogin.getAccessToken() - forwards
x-cedros-org-idwhenhostContext.org.orgIdis present
Admin sections
Content:
pagesnavigationsite-settingslayout— nav width, link position/style, footer widthtippingmonetization
Data model:
collectionsschema-designercontract-verifycustom-data
Operations:
data-opshistory
Theme system (CedrosDataProvider)
CedrosDataProvider matches the theme API used by cedros-login and cedros-pay:
import { CedrosDataProvider } from "@cedros/data-react";
<CedrosDataProvider
theme="dark"
themeOverrides={{
"--cedros-background": "#292524",
"--cedros-foreground": "#f5f5f4",
"--cedros-border": "#44403c",
}}
>
<SiteLayout ... />
</CedrosDataProvider>Props:
theme—'light'|'dark'(default:'light')themeOverrides— typedCedrosDataThemeOverrideswith 13 tokens + open-ended[key: string]unstyled— disables all default className/style (for custom design systems)
Hook:
import { useCedrosDataTheme } from "@cedros/data-react";
const { mode, isDark, className, style, unstyled } = useCedrosDataTheme();Also exports useCedrosDataThemeOptional() which returns null outside a provider.
The provider applies className (.cedros-dark) and inline style overrides on the same element so overrides always win via CSS specificity — matching cedros-pay/login behavior.
Styling and dark mode
- All component styles use
var(--cedros-*, fallback)— no hardcoded colors, even in dark mode. - Admin UIs use tokenized variables aligned with cedros-login/cedros-pay conventions.
- Dark mode responds to both:
.cedros-dark.cedros-admin--dark
- Direct import option:
import "@cedros/data-react/admin/styles.css";Site templates and components
Layouts/navigation:
SiteLayout— acceptslayout?: SiteLayoutOptionsfor nav/footer configurationTopNav— acceptslayout?: NavLayoutOptionsSiteFooter— acceptslayout?: FooterLayoutOptionsDashboardShell
Layout options
Layout preferences are managed via the admin "Layout" section (stored as site_settings/layout). Pass them to SiteLayout:
<SiteLayout
siteTitle="My Site"
navigation={navItems}
layout={{
nav: {
width: "full", // "contained" (default) | "full"
linkPosition: "center", // "right" (default) | "center"
linkStyle: "text", // "pill" (default) | "text"
},
footer: {
width: "full", // "contained" (default) | "full"
},
}}
>
{children}
</SiteLayout>- width: "full" — logo and actions stretch to viewport edges
- linkPosition: "center" — nav links centered between brand and right slot
- linkStyle: "text" — plain text links instead of pill buttons
Core page templates:
HomePageTemplateContactPageTemplateLegalPageTemplateNotFoundTemplateDashboardOverviewTemplate
Blog templates:
BlogIndexTemplate— supports search, category/tag filters, bookmarks, and generic filter dimensionsBlogPostTemplate— supports tipping, paywall, and bookmarks
Blog interactive features:
BlogSearchInput— CMD+K keyboard shortcut, debounced client-side searchFilterDimensionChips— generic dimension-based tag filtering (replaces category/tag dropdowns)BookmarkButton— per-post bookmark toggle (state managed by consumer)ContentPaywall— metered/locked/preview paywall with purchase flow viaPaywallPayClient
Tipping:
TipWidget— self-configuring tip widget with currency selection, preset amounts, and send flowSOL_CURRENCY,USDC_CURRENCY— predefined currency constants
Docs templates:
DocsIndexTemplateDocArticleTemplate(GitBook-style left nav + right TOC)- both accept
headlessto skip the built-inSiteLayout, orrenderLayout={(content) => ...}to wrap the docs UI in an existing app shell
Content rendering and helpers:
MarkdownContentBreadcrumbsContentPaginationwithActiveRouteStatefetchDocEntrybuildDocsSidebarSectionsbuildDocsTreebuildHierarchicalDocsSidebarSectionsbuildDocsPrevNextwithActiveDocsSidebarprepareBlogIndexprepareDocsIndexcollectFilterValuescollectDimensionValuesmatchesFilterDimensionsbuildContentListHref
Tipping (TipWidget)
TipWidget delegates payment to @cedros/trade-react and supports two modes:
Self-configuring — fetches config from your cedros-data server:
<TipWidget dataServerUrl="https://your-data-server.com" />Manual — provide recipient directly (skips config fetch):
<TipWidget recipient="SomeWalletAddress" currencies={[SOL_CURRENCY]} />With per-post recipient override:
<TipWidget recipient={post.tipRecipient} />The widget auto-detects browser wallets (Phantom, Solflare) for signing. To use a custom signer:
<TipWidget
recipient="..."
senderAddress={walletAddress}
signTransaction={async (base64Tx) => signedBase64Tx}
/>Optional peer dependency
Tipping requires @cedros/trade-react at runtime:
npm install @cedros/trade-reactBrowser wallet auto-signing also requires @solana/web3.js for transaction deserialization. If not installed, provide a signTransaction prop instead.
BlogPostTemplate tipping integration
<BlogPostTemplate
tipping={{
enabled: true,
dataServerUrl: "https://your-data-server.com",
// OR provide recipient directly:
// recipient: "WalletAddress",
// currencies: [SOL_CURRENCY, USDC_CURRENCY],
// presets: { SOL: [0.01, 0.05, 0.1], USDC: [1, 5, 10] },
}}
{...otherProps}
/>Paywall (ContentPaywall)
BlogPostTemplate supports metered/locked/preview paywalls:
<BlogPostTemplate
paywall={{
mode: "preview", // "free" | "preview" | "locked"
previewParagraphs: 3,
price: { amount: 5, currency: "USDC", label: "$5" },
unlocked: false,
payClient: myPaywallClient,
remainingFreeReads: 2, // optional metering
}}
{...otherProps}
/>Modes:
free— full content, no paywallpreview— shows first N paragraphs + purchase promptlocked— no content shown, purchase prompt only
When remainingFreeReads > 0, metered users see full content with a remaining-reads banner.
Markdown and HTML behavior
Docs/blog templates default to bodyMarkdown.
bodyHtml remains compatibility fallback and is only rendered when:
allowUnsafeHtmlFallback={true}
This keeps markdown as the safe default and avoids unsafe HTML rendering by default.
Docs search helpers also inspect optional bodyMarkdown, bodyText, bodyHtml, and searchText fields on docs entries, so callers can opt into body/full-text matching without changing the query API.
Server helpers and API key
@cedros/data-react/server provides Next.js data-fetching helpers that call cedros-data directly:
import { generatePageMetadata, loadSitemapEntries, fetchBlogPost } from "@cedros/data-react/server";
// All helpers accept ServerFetchOptions:
const meta = await generatePageMetadata("about", {
serverUrl: process.env.CEDROS_DATA_URL,
apiKey: process.env.CEDROS_X_API_KEY, // optional, sent as x-api-key header
});The API key resolves from (in order):
options.apiKeyif explicitly passedprocess.env.CEDROS_X_API_KEYenvironment variable- No header sent (unauthenticated — works with direct cedros-data access)
Environment variables for server URL resolution:
options.serverUrlif explicitly passedCEDROS_DATA_URLNEXT_PUBLIC_BACKEND_API_URL
Default page contract
The package exports the default page template contract used by server bootstrap:
homeaboutcontactdocsblogprivacy-policyterms-of-servicenot-found
Example
End-to-end markdown integration example:
examples/cedros-data-markdown-e2e.tsx- the example reads page records from
GET /admin/pagesand uses each record'sentry_key
See also:
CHANGELOG.md
