npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dbosoft/nextjs-site-core

v3.0.3

Published

Server-first site framework for dbosoft Next.js sites

Readme

@dbosoft/nextjs-site-core

Server-first site framework for dbosoft Next.js sites. Provides navigation, footer, SEO, analytics, theming, and shared UI components used across all dbosoft websites.

Installation

This is a workspace package — add "@dbosoft/nextjs-site-core": "workspace:*" to your package.json.

Required Dependencies

{
  "dependencies": {
    "@dbosoft/nextjs-site-core": "workspace:*",
    "@dbosoft/nextjs-site-marketing": "workspace:*",
    "@dbosoft/nextjs-plugin": "workspace:*",
    "@dbosoft/tailwind-config": "workspace:*",
    "@dbosoft/react-uicore": "workspace:*",
    "@dbosoft/nextjs-consent-manager": "workspace:*",
    "@dbosoft/web-types": "workspace:*",
    "@headlessui/react": "^2.2.1",
    "@heroicons/react": "^2.2.0",
    "clsx": "^2.1.0",
    "framer-motion": "^11.0.0",
    "next": "^16.0.0",
    "next-themes": "^0.4.4",
    "next-intl": "^4.8.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "sass": "^1.80.0",
    "fathom-client": "^3.7.0",
    "@vercel/speed-insights": "^1.1.0"
  },
  "devDependencies": {
    "tailwindcss": "^4.0.0",
    "@tailwindcss/forms": "^0.5.9",
    "@tailwindcss/typography": "^0.5.15"
  }
}

Subpath Exports

| Import | Description | |--------|-------------| | ./types | TypeScript interfaces: LinkItem, SiteCoreStaticConfig, CTALink, AuthConfig, FooterColumn, etc. | | ./server | Server components: HtmlShell, AppShell, HeadNav, HeadNavSSR, Footer | | ./client | Client components: HeadNavClient, NavigationProvider, PrimaryNav, SecondaryNav, MobileNavigation, Breadcrumb, Tracking | | ./navigation | Pure functions: generateNavigationStructure(), getBreadcrumbs(), generateFooterNavigation(), getQuickLinks() | | ./ui | Client UI: ThemeSelector, Avatar, FormInput, ResponsiveTable, AppLink, TabsClient | | ./ui/server | Server-only UI: Tabs, TabsContent | | ./seo | SEO: StructuredData, ProductPageSEO, FAQSchema, HowToSchema, PageAISchema, AIContent, generateSitemapEntries() | | ./analytics | Analytics: ConsentManagerLazy, Tracking | | ./page-navigation | Page-level navigation context | | ./hooks | React hooks: useIsVisible, useTypewriter, useScrollProgress | | ./i18n | i18n utilities: createRequestConfig(), localizeConfig(), LanguageSwitcher | | ./i18n/default-request | Default next-intl config (English-only, framework messages). Use when not opting into i18n. | | ./tailwind | Tailwind config preset | | ./css | Framework CSS (framework.css) |

Setup

1. Next.js Configuration

The site requires two Next.js plugins:

  • @dbosoft/nextjs-plugin — SVG component support, auto-discovers and transpiles @dbosoft packages
  • next-intl/plugin — Required by the framework for translations (even without multi-locale support)
// next.config.mjs
import createNextIntlPlugin from 'next-intl/plugin'
import withDbosoftPlugin from '@dbosoft/nextjs-plugin'

const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts')

/** @type {import('next').NextConfig} */
const nextConfig = {}

export default withNextIntl(
  withDbosoftPlugin({})(nextConfig)
)

2. i18n Request Config

For apps that don't need multi-locale support, create a one-line re-export of the default config:

// src/i18n/request.ts
export { default } from '@dbosoft/nextjs-site-core/i18n/default-request'

This loads the framework's built-in English translations (footer, nav, theme selector, etc.) without any app-level setup.

For apps that opt into full i18n, see Multi-locale i18n below.

3. TypeScript Configuration

Add @dbosoft/web-types to your tsconfig for global type declarations (SVG modules, etc.):

{
  "compilerOptions": {
    "types": ["@dbosoft/web-types"]
  }
}

4. Tailwind 4 Configuration

// tailwind.config.ts
import type { Config } from 'tailwindcss'
import nextjsConfig from '@dbosoft/tailwind-config/nextjs'
import { resolveDbosoftContent } from '@dbosoft/tailwind-config/resolve-content'

const config: Config = {
  presets: [nextjsConfig],
  content: [
    './src/**/*.{js,ts,jsx,tsx,mdx}',
    ...resolveDbosoftContent(),
  ],
  darkMode: 'selector',
}

export default config

5. Framework CSS (Tailwind 4)

/* src/app/css/style.css */
@import "tailwindcss";
@config "../../../tailwind.config.ts";

/* Framework: design tokens + framework utilities */
@import '@dbosoft/nextjs-site-core/css';

The @config path is relative from the CSS file to the tailwind config at the project root.

6. Root Layout

// src/app/layout.tsx
import './css/style.css'
import { HtmlShell, AppShell } from '@dbosoft/nextjs-site-core/server'
import { siteConfig } from '@/lib/site-core-config'

export default function AppLayout({ children }: { children: React.ReactNode }) {
  return (
    <HtmlShell>
      <AppShell config={siteConfig}>
        {children}
      </AppShell>
    </HtmlShell>
  )
}

7. Default Layout with Navigation

// src/app/(default)/layout.tsx
import { HeadNav } from '@dbosoft/nextjs-site-core/server'
import { siteConfig } from '@/lib/site-core-config'

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <>
      <HeadNav
        config={siteConfig}
        logoSlot={<span className="text-lg font-semibold">My Product</span>}
      />
      {children}
    </>
  )
}

8. Site Configuration

// src/lib/site-core-config.tsx
import { createSiteConfig, LinkType } from '@dbosoft/nextjs-site-core/types'

export const siteConfig = createSiteConfig({
  siteUrl: 'https://your-site.io',
  routes: { home: '/', docs: '/docs', pricing: '/pricing' },
  externalLinks: { dbosoft: 'https://www.dbosoft.eu' },
  footerColumns: [
    { id: 'get-started', label: 'Get Started', position: 'main', order: 1 },
  ],
  navGroups: [
    {
      id: 'get-started',
      name: 'Get Started',
      sections: [{ id: 'quick-start', title: 'Quick Start' }],
    },
  ],
  links: {
    home: { linkType: LinkType.Core, href: '/', title: 'Home', hideInFooter: true, hideInMainNav: true },
    pricing: { linkType: LinkType.Core, href: '/pricing', title: 'Pricing', footerCategory: 'get-started', navSection: 'quick-start' },
  },
  copyrightText: '(c) 2026 dbosoft GmbH',
  ctaLink: { key: 'pricing', label: 'Get Started' },
  headerLinks: [{ key: 'docs', label: 'Docs', href: '/docs' }],
})

Optional Features (Opt-in)

Authentication

Auth is fully pluggable — the framework has no auth library dependency. To add auth:

  1. Wrap your layout with your own SessionProvider (from your auth library)
  2. Pass an authSlot component to HeadNav that renders sign-in/sign-out UI
// Your auth UI component (client component)
function AuthUI({ variant }: { variant: 'desktop' | 'mobile' }) {
  // Use your auth library's hooks here (next-auth, custom, etc.)
  return variant === 'desktop' ? <DesktopAuth /> : <MobileAuth />
}

// In your layout
<HeadNav config={siteConfig} logoSlot={<Logo />} authSlot={AuthUI} />

The authSlot component receives a variant prop ('desktop' | 'mobile') and is rendered in the appropriate position in the header and mobile drawer.

Multi-locale i18n

Full i18n requires the following setup:

1. Define routing

// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing'

export const routing = defineRouting({
  locales: ['en-us', 'de-de'],
  defaultLocale: 'en-us',
  localePrefix: 'always',
})

2. Create request config with message loading

// src/i18n/request.ts
import { createRequestConfig } from '@dbosoft/nextjs-site-core/i18n'
import { routing } from './routing'

// App-specific messages
async function loadMessages(locale: string) {
  try {
    return (await import(`../../messages/${locale}.json`)).default
  } catch {
    return (await import('../../messages/en-us.json')).default
  }
}

export default createRequestConfig({
  routing,
  loadMessages,
  packages: [
    // Add message loaders from packages that ship translations:
    // loadDocsMessages, loadArticlesMessages, etc.
  ],
})

Messages are deep-merged in this order: framework messages > auto-discovered addon messages > package messages > app messages. The framework auto-discovers @dbosoft/* packages with a messages/ directory.

3. Create the locale proxy (Next.js 16)

Next.js 16 uses a proxy pattern instead of middleware.ts:

// src/proxy.ts
import createIntlMiddleware from 'next-intl/middleware'
import { type NextRequest } from 'next/server'
import { routing } from './i18n/routing'

const intlMiddleware = createIntlMiddleware(routing)

export function proxy(request: NextRequest) {
  return intlMiddleware(request)
}

export const config = {
  matcher: ['/', '/(de-de|en-us)/:path*'],
}

The matcher should list your locale prefixes explicitly.

4. Add [locale] route segment

// src/app/[locale]/layout.tsx
import type { ReactNode } from 'react'
import { HtmlShell, AppShell } from '@dbosoft/nextjs-site-core/server'
import { getMessages } from 'next-intl/server'
import { siteConfig } from '@/lib/site-core-config'
import { routing } from '@/i18n/routing'

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }))
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: ReactNode
  params: Promise<{ locale: string }>
}) {
  const { locale } = await params
  const messages = await getMessages()

  return (
    <HtmlShell locale={locale}>
      <AppShell config={siteConfig} messages={messages}>
        {children}
      </AppShell>
    </HtmlShell>
  )
}

Key points:

  • Call getMessages() server-side in the locale layout
  • Pass messages to AppShell — it wraps children with NextIntlClientProvider
  • Pass locale to HtmlShell for the <html lang> attribute
  • Use generateStaticParams() to pre-render all locale variants

5. Add i18n to site config

export const siteConfig: SiteCoreStaticConfig = {
  // ... other config
  i18n: {
    locales: ['en-us', 'de-de'],
    defaultLocale: 'en-us',
    localePrefix: 'always',
  },
}

This enables the locale selector in the navigation UI.

6. Per-locale message files

messages/
  en-us.json
  de-de.json

Architecture

Design Principles

  1. Server-first: Layout components have server + client pairs. Server components render static HTML (zero JS). Client components add interactivity only where needed.
  2. Static rendering by default: The framework never calls auth() in layouts. Pages stay statically renderable. Auth UI is handled client-side via useSession().
  3. Config via props: Server components receive typed config as props. Client components receive serializable config as props. No global singletons.
  4. Component slots for non-serializable content: Logos, icons, search, promos are passed as ReactNode slots — server-rendered at the app level, passed to framework components.

Config Type System

// Serializable — crosses server->client boundary as props
interface SiteCoreStaticConfig {
  siteUrl: string
  routes: Record<string, string>
  externalLinks: Record<string, string>
  linkRegistry: Record<string, LinkItem>
  navigationGroups: NavigationGroup[]
  footerColumns?: FooterColumn[]
  copyrightText?: string
  docsPathPrefix?: string
  ctaLink?: CTALink
  headerLinks?: HeaderLink[]
  i18n?: I18nConfig      // Optional — enables multi-locale support
  seo?: SiteSEOConfig    // Optional — SEO defaults
  auth?: AuthConfig      // Optional — enables SessionProvider + auth UI
}

interface AuthConfig {
  providerId: string
  profileUrl: string
}

Navigation Layers

+---------------------------------------------------------------+
| PRIMARY NAV (fixed, always-dark bg-black)                     |
|  [Logo]  [MegaMenu Groups...]     [CTA Button] [Links] [Auth]|
+---------------------------------------------------------------+
| SECONDARY NAV (sticky, themed)                                |
|  [SubLogo / Breadcrumb]  [Search?]      [Quick Links ->]      |
+---------------------------------------------------------------+

Server/Client Composition

HeadNav (server, no 'use client')
+-- Suspense fallback: HeadNavSSR (server, static HTML)
+-- Suspended: HeadNavClient ('use client', interactive)
    +-- NavigationProvider (scroll state)
    +-- PrimaryNav (mega menu, auth via config.auth)
    +-- SecondaryNav (scroll-aware breadcrumb)
    +-- Breadcrumb (path-based)
    +-- MobileNavigation (dialog)
    +-- ScrollbarCompensation

Theme Tokens

Semantic CSS class tokens that adapt to light/dark mode:

| Category | Classes | |----------|---------| | Backgrounds | bg-surface-base, bg-surface-raised, bg-section-alt, bg-card | | Text | text-content-primary, text-content-secondary, text-content-muted | | Borders | border-border | | Brand | text-primary-normal, text-primary-light, bg-primary-normal |