@kblack0610/site-shell (0.1.0)

Published 2026-08-28 00:21:47 +00:00 by kblack0610

Installation

@kblack0610:registry=
npm install @kblack0610/site-shell@0.1.0
"@kblack0610/site-shell": "0.1.0"

About this package

@kblack0610/site-shell

The marketing-site shell shared by blacknbrownstudios.com, kennethblack.me and kblack.dev: nav, footer, hero, CTA, cards, metadata builders, and a CSS-variable theming layer.

Separate from @blacknbrownstudios/ui on purpose. ui is dual-target and ships a React Native entry consumed by four Expo apps; these components import next/link, next/navigation and next-themes. Putting them in ui would place Next in the import graph of every native build.

Install

pnpm add @kblack0610/site-shell

Peers: react, next, next-themes, lucide-react. tailwindcss is an optional peer, needed only for ./tailwind.

Entry points

Import Contents
@kblack0610/site-shell Server components: SiteShell, SiteFooter, HeroSection, CTASection, SectionBand, SectionHeading, ItemCard, TagBadge, TagList, SocialLinkRow, cn
@kblack0610/site-shell/client SiteHeader, ThemeModeToggle, SiteThemeProvider
@kblack0610/site-shell/theme defineSiteTheme, siteThemeToCssVars, types
@kblack0610/site-shell/tailwind withSiteShell, siteShellPreset, contentGlobs, emittedClasses
@kblack0610/site-shell/metadata siteMetadata, pageMetadata

The root entry carries no "use client" banner, so ItemCard can take a ReactNode icon from a server page. Anything interactive lives in /client.

Tailwind: use the wrapper, not the preset

// tailwind.config.js
const { withSiteShell } = require('@kblack0610/site-shell/tailwind');
const { myTheme } = require('./src/site.theme.cjs');

module.exports = withSiteShell({
  siteShell: { themes: [myTheme], defaultThemeId: 'my-site' },
  content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
});

Two rules, both enforced at runtime:

  1. Do not set darkMode in your config. The preset owns it (class). Tailwind lets an app-level darkMode clobber a preset's, which silently reverts dark mode to the OS setting and makes every theme toggle a no-op. withSiteShell throws rather than let that happen.

  2. Do not hand-write the package's content glob. Tailwind v3 presets replace content, they do not merge it, so a preset cannot contribute file globs. withSiteShell concatenates them for you. A written-out ./node_modules/... path is also wrong under pnpm's isolated linking.

Theming

Each site passes a SiteTheme; the preset emits CSS variables under [data-site-theme="<id>"] and .dark, and maps them into Tailwind colours. Set the id once on <html>:

<html lang="en" data-site-theme="my-site" suppressHydrationWarning>

Components address semantic tokens only and never write dark: variants: bg-surface, bg-surface-alt, bg-surface-raised, text-content, text-content-muted, text-content-subtle, border-border-token, plus the brand-* and accent-* scales. That is what lets one component render correctly across sites with unrelated palettes.

Colours are emitted as r g b channel triplets, not hex. A var() holding a hex makes bg-brand-500/20 compile to rgb(#78716c / 0.2), which is invalid, so the browser drops the declaration and the element renders fully transparent.

Verifying a class survived the build

A purged class leaves the markup byte-identical and changes only the pixels, so an HTML diff cannot catch it. emittedClasses lists the vocabulary to assert against the compiled CSS:

const { emittedClasses } = require('@kblack0610/site-shell/tailwind');

No theme-init script

next-themes already injects its own blocking inline script, so a hand-rolled FOUC IIFE in your layout is redundant: delete it. SiteThemeProvider passes attribute={['class', 'data-mode']}, so the .dark class and data-mode stay in sync on every toggle. The hand-rolled scripts set data-mode once at load and never again, which is why [data-mode='dark'] CSS only responded to a reload.

Dependencies

Dependencies

ID Version
clsx ^2.1.1
tailwind-merge ^2.6.0

Development dependencies

ID Version
@types/react ^19.2.0
lucide-react ^0.554.0
next ^16.1.1
next-themes ^0.4.6
playwright ^1.55.1
react 19.2.4
tailwindcss ^3.4.17
tsup ^8.0.0
typescript 5.8.3
vitest ^4.0.16

Peer dependencies

ID Version
lucide-react >=0.400.0
next >=15.0.0 <17
next-themes ^0.4.6
react >=19.0.0 <20
tailwindcss ^3.4.0
Details
npm
2026-08-28 00:21:47 +00:00
9
MIT
latest
20 KiB
Assets (1)
Versions (1) View all
0.1.0 2026-08-28