@silo-software/next
v0.4.3
Published
Next.js helpers for Silo sites
Readme
@silo-software/next
Next.js helpers for Silo sites. Builds on @silo-software/sdk.
@silo-software/next:createCmsServerClient, signed webhook verification and tag revalidation (verifyCmsWebhookRequest,handleCmsWebhookRevalidation,getCmsWebhookTags) andbuildCmsArticleMetadata.@silo-software/next/pdfjs:getCmsPdfJsAssetResponseserves the PDF.js worker, cmaps, fonts and wasm for@silo-software/react/reader;getCmsPdfJsTraceIncludesadds them tooutputFileTracingIncludesfor standalone builds.
@silo-software/next/auth provides createSiloAuth({ createClient, appUrl, accountUrl, onError? }) and normalizeReaderRedirectPath. Create one instance on the server, then export its start, callback, logout and session methods from GET/POST route handlers. appUrl must be the configured frontend origin. accountUrl (the publisher's company site) is optional: without it, sign-in uses the company site the Silo API names in the site shell (site.accountUrl). Logout is a same-origin POST that requests revocation of the linked originating session and redirects to / on the configured app URL; submit a form rather than using fetch. The instance also provides runRequiredReaderOperation, runOptionalReaderOperation, getReaderSession, getReaderAccessToken, readReaderTokens, and cookie helpers. Persist the returned tokens with applyReaderTokens in route handlers after a refresh. Server-component session reads do not refresh cookies.
@silo-software/next/request-guard exports guardRequest(request, siteUrl, maxBytes?) for same-origin JSON browser writes, with a default 64 KiB body limit. Signed server webhooks need their own authentication.
@silo-software/next/csp exports buildExternalSiteCsp({ apiOrigins?, mediaOrigins?, sources?, development?, reportUri? }) for cacheable public Next.js sites. sources is an array of CSP directive-to-source lists for site-specific integrations. It returns a CSP header and optional reporting headers. Inline scripts are allowed for static Next.js bootstrap code, so this does not provide nonce-level protection against injected scripts.
Reader IP is forwarded for campus access only when the site runs behind an edge
that overwrites a single trusted client-IP header. Vercel deployments
(VERCEL=1) use x-vercel-forwarded-for; another deployment must explicitly
set SILO_TRUSTED_CLIENT_IP_HEADER to cf-connecting-ip or
x-vercel-forwarded-for and ensure its edge overwrites that header and cannot
be bypassed. Invalid configuration, missing headers, chains and invalid IPs
produce no IP. This fails closed for campus-IP access without blocking free
content. Update the SDK and Next packages together.
Redirects in proxy.ts
import { NextResponse, type NextRequest } from 'next/server';
import { createSiloRedirects } from '@silo-software/next/redirects';
import { client } from './lib/silo';
const redirects = createSiloRedirects({ load: () => client.getRedirects(), revalidateSeconds: 60 });
export async function proxy(request: NextRequest) {
const match = await redirects.match(request.nextUrl.pathname);
if (match) return NextResponse.redirect(new URL(match.location, request.url), match.status);
return NextResponse.next();
}The list is cached in memory for 60 seconds by default. Exact matches take precedence; prefix matches use the longest matching path.
@silo-software/next/seo exports JsonLd and schema-dts types. @silo-software/next/csp also exports CSP fragments, reporting helpers and CspConfig.
Content and images
@silo-software/next/content renders and sanitizes stored Tiptap content on the server. @silo-software/next/image supplies Silo media URL helpers, @silo-software/next/image-loader provides the image loader, and @silo-software/next/html includes article HTML normalization helpers.
Route handlers
Create a route kit with site-specific dependencies and optional webhook settings:
import { createSiloRoutes } from '@silo-software/next/routes';
export const siloRoutes = createSiloRoutes({
auth, appUrl, createClient, buildArticleContentHtml,
webhookSecret: () => process.env.SILO_WEBHOOK_SECRET,
webhookSiteId: () => process.env.CMS_SITE_ID || undefined,
});Each route exports its methods in app/api/.../route.ts:
import { siloRoutes } from '@/lib/silo-routes';
export const { GET, POST } = siloRoutes.favorites;The kit provides:
favorites(GET, POST),articleReading(POST, PATCH),articleAccess,articleAudio,articleContent,articleSummary,pdfDownload, andsearch(GET).shareLinks(GET, POST, PUT),shareLinkResolve(GET),authorArticles,personArticles, andcompanyArticles(GET). Dynamic handlers accept Next.js's{ params }context.chat,chatMessages,chatStop,newsletterSubscribe,analytics, andrevalidate(POST).accountFavorites,accountRecentlyViewed, andaccountSubscriptionSummary(GET).recommendationFeed(GET),recommendationFeedbackandrecommendationProfile(GET, POST, DELETE),recommendationProfilePreviewandrecommendationPushSubscription(POST), andrecommendationSubscription(GET, PUT).
auth, appUrl, createClient, and buildArticleContentHtml are required. webhookSecret and webhookSiteId configure revalidation; defaultNewsletterId supplies the site's fallback newsletter. analytics supplies the batch mapper, optional secondary sink, disabled predicate, and collector configuration. entityArticles supplies the language, tagged client, and article presentation mapper. account supplies the site's language, page size, page loaders, and account-summary loader. Without these optional configurations, their corresponding routes use their unavailable or empty behavior.
rateLimit accepts a RateLimiter: an async function receiving { key, limit, windowMs } and returning { allowed, retryAfterSeconds? }. The migrated routes currently contain no rate-limit calls, so supplying this adapter does not introduce new limits. Hosts may implement it with their own shared rate-limit store.
@silo-software/next/server provides server session, account summary, request security, and origin-validation helpers. @silo-software/next/routes also exports share-link resolution and redirect helpers.
