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

@luciodale/docs-ui-kit

v0.3.38

Published

Astro component library for documentation sites. Dark theme, orange accent.

Readme

@luciodale/docs-ui-kit

Astro component library for building documentation sites. Dark theme, orange accent, Tailwind CSS v4. Ships source .astro files and pre-compiled Tailwind utilities — your Astro project processes the components, the CSS works everywhere without @source hacks.

Install

npm install @luciodale/docs-ui-kit

Peer dependency: astro >= 5.

Runtime dependency: shiki (build-time syntax highlighting in Astro frontmatter).

Setup in your Astro project

1. CSS

Create a global CSS file and import the theme + pre-compiled utilities:

/* src/styles/global.css */
@import "tailwindcss";
@import "@luciodale/docs-ui-kit/styles.css";
@import "@luciodale/docs-ui-kit/utilities.css";
  • styles.css — Tailwind v4 @theme tokens (colors, fonts), base body styles (background: black; color: white), and custom utilities like .liquid-glass-border
  • utilities.css — Pre-compiled Tailwind utility classes used by all components (navbar, sidebar, code blocks, etc.). Ships with the package so you don't need @source directives pointing into node_modules

Then import this CSS in your base layout's frontmatter (not a <style> tag):

---
import "../styles/global.css";
---

2. Fonts

The theme uses Work Sans (body) and JetBrains Mono (code). Load them in your base layout's <head>:

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />

3. SiteConfig

Define a config object that drives all layout components:

// src/config.ts
import type { SiteConfig } from "@luciodale/docs-ui-kit/types/config";

export const siteConfig: SiteConfig = {
  title: "my-library",
  description: "A short description of your library.",
  siteUrl: "https://my-library-docs.pages.dev",
  installCommand: "npm install my-library",
  githubUrl: "https://github.com/you/my-library",
  author: "Your Name",
  // Optional:
  // logoSrc: "/logo.svg",
  // logoAlt: "My Library logo",
  // ogImage: "/og.png",
  // faviconSrc: "/favicon.ico",
  // twitterHandle: "@you",
  // copyright: "Your Name",
  socialLinks: {
    github: "https://github.com/you",
    // linkedin: "https://linkedin.com/in/you",
  },
  navLinks: [
    { href: "/docs/getting-started", label: "Docs" },
    { href: "/demo/basic", label: "Demo" },
  ],
  sidebarSections: [
    {
      title: "Getting Started",
      links: [
        { href: "/docs/getting-started", label: "Introduction" },
        { href: "/docs/configuration", label: "Configuration" },
      ],
    },
    {
      title: "Demos",
      links: [
        { href: "/demo/basic", label: "Basic" },
      ],
    },
  ],
};

Types

SiteConfig

import type { SiteConfig } from "@luciodale/docs-ui-kit/types/config";

| Field | Type | Required | Description | |---|---|---|---| | title | string | Yes | Site/library name. Shown in navbar, footer, SEO. | | description | string | Yes | Default meta description. Fallback for pages without their own. | | siteUrl | string | Yes | Canonical base URL (e.g. https://docs.example.com). Used by SEO + sitemap. | | installCommand | string | Yes | Shown in HeroSection with copy button. | | githubUrl | string | Yes | Links to the repo from navbar. | | socialLinks | { github: string; linkedin?: string } | Yes | Footer social icons. | | navLinks | Array<{ href: string; label: string }> | Yes | Top navbar links. Active state based on currentPath.startsWith(href). | | sidebarSections | Array<{ title: string; links: NavLink[] }> | Yes | Left sidebar groups. Also shown in mobile menu. | | author | string | No | Used in SEO meta tags and JSON-LD structured data. | | logoSrc | string | No | Image URL for navbar/footer. Falls back to title text. | | logoAlt | string | No | Alt text for logo. Falls back to title. | | ogImage | string | No | Path to default Open Graph image (1200x630). | | faviconSrc | string | No | Path to favicon. | | twitterHandle | string | No | @handle for Twitter Card meta tags. | | copyright | string | No | Footer copyright text. Falls back to title. |

PropsTableRow

import type { PropsTableRow } from "@luciodale/docs-ui-kit/types/props";

| Field | Type | Required | Description | |---|---|---|---| | name | string | Yes | Prop name. | | type | string | Yes | Type annotation string. | | description | string | Yes | What the prop does. | | defaultValue | string | No | Default value. Shows "—" if omitted. | | required | boolean | No | Shows red asterisk if true. |

Components

All components are imported from @luciodale/docs-ui-kit/components/<Name>.astro.

Layout Components

DocsLayout

Three-column layout: left sidebar + content + right table of contents. Used for docs and demo pages.

---
import DocsLayout from "@luciodale/docs-ui-kit/components/DocsLayout.astro";
---

<DocsLayout config={siteConfig} currentPath={Astro.url.pathname}>
  <!-- page content -->
</DocsLayout>

| Prop | Type | Required | Description | |---|---|---|---| | config | SiteConfig | Yes | Site configuration object. | | currentPath | string | Yes | Current URL pathname. Used for active link highlighting. |

Includes: Navbar (sticky, blur backdrop), Sidebar (sticky, collapsible sections, hidden on mobile), TableOfContents (auto-built from ContentSection components, hidden below xl breakpoint), Footer.

PageLayout

Simple layout without sidebars. Used for landing/home pages.

---
import PageLayout from "@luciodale/docs-ui-kit/components/PageLayout.astro";
---

<PageLayout config={siteConfig} currentPath="/">
  <!-- page content -->
</PageLayout>

Same props as DocsLayout. Includes: Navbar, Footer. No sidebar or TOC.

Content Components

ContentSection

Wraps a content section with an <h2> heading. Automatically registers in the right-side TableOfContents — no manual TOC config needed.

---
import ContentSection from "@luciodale/docs-ui-kit/components/ContentSection.astro";
---

<ContentSection label="Installation">
  <p>Install the package...</p>
</ContentSection>

<ContentSection label="Quick Start">
  <p>Create a manager...</p>
</ContentSection>

| Prop | Type | Required | Description | |---|---|---|---| | label | string | Yes | Section heading text. Also appears in the TOC. | | id | string | No | Custom anchor ID. Auto-generated from label if omitted (slugified). |

Renders: <section id="..." data-toc-label="..."><h2>...</h2><slot /></section> with scroll-mt-24 for smooth anchor scrolling past the sticky navbar.

SectionHeading

Standalone <h2> heading without TOC registration. Use when you want a heading that does NOT appear in the table of contents.

---
import SectionHeading from "@luciodale/docs-ui-kit/components/SectionHeading.astro";
---

<SectionHeading>My Heading</SectionHeading>
<SectionHeading class="text-xl">Smaller Heading</SectionHeading>

| Prop | Type | Required | Description | |---|---|---|---| | class | string | No | Additional CSS classes. |

CodeBlock

Syntax-highlighted code block with copy button. Highlighting happens at build time via Shiki (zero client JS for highlighting). Uses vitesse-dark theme.

---
import CodeBlock from "@luciodale/docs-ui-kit/components/CodeBlock.astro";
---

<CodeBlock code="npm install my-lib" language="bash" filename="terminal" />

<CodeBlock
  code={`const x: string = "hello";
console.log(x);`}
  language="tsx"
  filename="example.ts"
/>

| Prop | Type | Required | Description | |---|---|---|---| | code | string | Yes | The source code string. Leading/trailing whitespace is trimmed. | | language | string | No | Shiki language ID. Default: "tsx". | | filename | string | No | Shown in the header bar. Falls back to language. |

PropsTable

Renders a styled table for documenting component props or API options.

---
import PropsTable from "@luciodale/docs-ui-kit/components/PropsTable.astro";
import type { PropsTableRow } from "@luciodale/docs-ui-kit/types/props";

const rows: PropsTableRow[] = [
  { name: "url", type: "string", required: true, description: "WebSocket server URL." },
  { name: "debug", type: "boolean", defaultValue: "false", description: "Enable debug logging." },
];
---

<PropsTable title="Manager Options" rows={rows} />

| Prop | Type | Required | Description | |---|---|---|---| | title | string | No | Optional heading above the table. | | rows | Array<PropsTableRow> | Yes | Table data. See PropsTableRow type above. |

HeroSection

Landing page hero with title, description, install command (with copy button), and optional extra content via slot.

---
import HeroSection from "@luciodale/docs-ui-kit/components/HeroSection.astro";
---

<HeroSection
  title="my-library"
  description="A short tagline."
  installCommand="npm install my-library"
>
  <!-- Optional: extra content below the install command -->
  <div class="flex gap-4">
    <a href="/docs" class="rounded-lg bg-accent px-5 py-2.5 text-sm text-white">Get Started</a>
  </div>
</HeroSection>

| Prop | Type | Required | Description | |---|---|---|---| | title | string | Yes | Main heading (h1). | | description | string | Yes | Subtitle paragraph. | | installCommand | string | Yes | Shell command. Copy button copies this string. | | logoSrc | string | No | Logo image above the title. | | logoAlt | string | No | Alt text for logo. |

Callout

Info, warning, tip, or danger admonition boxes for calling out important information.

---
import Callout from "@luciodale/docs-ui-kit/components/Callout.astro";
---

<Callout type="info">This API is stable and ready for production.</Callout>
<Callout type="warning">This feature requires React 18+.</Callout>
<Callout type="tip" title="Performance">Use ref-counted subscriptions to avoid duplicate connections.</Callout>
<Callout type="danger">Calling dispose() is irreversible.</Callout>

| Prop | Type | Required | Description | |---|---|---|---| | type | "info" \| "warning" \| "tip" \| "danger" | No | Default: "info". Controls color and icon. | | title | string | No | Heading text. Defaults: "Note", "Warning", "Tip", "Danger". |

Renders a left-bordered aside with icon, title, and slot content. Supports links (<a>) and inline code (<code>) in the body.

FeatureList

Highlighted feature list with colored dots and keywords. Designed for landing pages and feature summaries.

---
import FeatureList from "@luciodale/docs-ui-kit/components/FeatureList.astro";
---

<FeatureList features={[
  { highlight: "Type-safe", description: "Full TypeScript support out of the box" },
  { highlight: "Lightweight", description: "Zero runtime overhead", color: "green" },
  { highlight: "Dark theme", description: "Built for modern documentation sites" },
]} />

<!-- Or set a global color for all items -->
<FeatureList
  color="cyan"
  features={[
    { highlight: "Fast", description: "Build-time syntax highlighting via Shiki" },
    { highlight: "Searchable", description: "Full-text search powered by Pagefind" },
  ]}
/>

| Prop | Type | Required | Description | |---|---|---|---| | features | Array<FeatureItem> | Yes | List of feature items (see below). | | color | FeatureColor | No | Default: "accent". Global color for all items. Overridden by per-item color. |

FeatureItem:

| Field | Type | Required | Description | |---|---|---|---| | highlight | string | Yes | Colored keyword/phrase. Rendered in bold with the active color. | | description | string | No | Text after the highlight, separated by an em dash. | | color | FeatureColor | No | Per-item color override. |

FeatureColor: "accent" | "blue" | "green" | "purple" | "yellow" | "cyan"

PackageInfo

Displays npm version, license, GitHub stars, and a bundlephobia link. Data is fetched at build time from the npm registry and GitHub API (3s timeout, graceful fallback).

---
import PackageInfo from "@luciodale/docs-ui-kit/components/PackageInfo.astro";
---

<PackageInfo packageName="@luciodale/react-socket" githubRepo="luciodale/react-socket" />

| Prop | Type | Required | Description | |---|---|---|---| | packageName | string | Yes | npm package name. Used to fetch version + license from registry. | | githubRepo | string | No | GitHub owner/repo. Used to fetch star count. If omitted, stars badge is hidden. |

Renders a row of styled badges: version (accent color, links to npm), license, GitHub stars (links to repo), bundlephobia link.

Search

SearchModal

Full-text search powered by Pagefind. Renders a search trigger button (for Navbar) + a dialog modal. Includes Cmd+K / Ctrl+K keyboard shortcut.

The component is automatically included in the Navbar — no manual placement needed. It loads Pagefind dynamically at runtime from /_pagefind/pagefind.js.

Consumer setup:

After building your Astro site, run Pagefind to generate the search index:

astro build && bunx pagefind --site dist/client

Or for static output:

astro build && bunx pagefind --site dist

Add this to your package.json scripts:

{
  "scripts": {
    "build": "astro build && bunx pagefind --site dist/client"
  }
}

How it works:

  • Desktop: compact search button with "Search" label + Cmd+K badge, placed between nav links and GitHub icon
  • Mobile: small search icon button next to the hamburger menu
  • Cmd+K / Ctrl+K opens a centered modal dialog with backdrop blur
  • Pagefind sub_results are flattened so each result links to a specific page section (anchor), not just the page
  • Results show section title, parent page name, and highlighted excerpt (up to 10 results)
  • Clicking a result navigates to the page + section anchor and closes the modal
  • Search input is debounced (150ms)
  • If Pagefind is not indexed, shows a helpful setup message

No additional imports needed — SearchModal is included by DocsLayout and PageLayout via the Navbar.

SEO Component

SEO

Renders all meta tags, Open Graph, Twitter Cards, JSON-LD structured data, and breadcrumbs. Place in <head>.

---
import SEO from "@luciodale/docs-ui-kit/components/SEO.astro";
---

<head>
  <SEO
    config={siteConfig}
    title="Getting Started"
    description="How to install and configure the library."
    currentPath={Astro.url.pathname}
    type="article"
  />
</head>

| Prop | Type | Required | Description | |---|---|---|---| | config | SiteConfig | Yes | Site configuration. Provides siteUrl, author, ogImage, etc. | | title | string | Yes | Page title. On / it's used as-is; elsewhere formatted as Title \| SiteName. | | description | string | No | Page description. Falls back to config.description. | | currentPath | string | Yes | URL pathname. Used for canonical URL and breadcrumbs. | | type | "website" \| "article" | No | Default: "website". Use "article" for docs pages (generates TechArticle JSON-LD). | | publishedDate | string | No | ISO date string for article:published_time. | | modifiedDate | string | No | ISO date string for article:modified_time. | | noindex | boolean | No | Default: false. Set true to add noindex, nofollow. |

What it renders:

  • <title> with smart formatting
  • <meta name="description">, <meta name="author">, <meta name="robots">
  • <link rel="canonical"> (absolute URL from siteUrl + currentPath)
  • <link rel="icon"> (if faviconSrc set)
  • Open Graph: og:type, og:url, og:title, og:description, og:site_name, og:locale, og:image (with dimensions + alt)
  • Twitter Card: twitter:card, twitter:title, twitter:description, twitter:image, twitter:site, twitter:creator
  • Article meta: article:published_time, article:modified_time, article:author
  • <meta name="theme-color" content="#000000">, <meta name="color-scheme" content="dark">
  • JSON-LD WebSite schema (on homepage) or TechArticle schema (on article pages)
  • JSON-LD BreadcrumbList auto-generated from URL path segments (on non-root pages)

Icon Components

GithubIcon / LinkedInIcon

SVG icon components. Used internally by Navbar and Footer, but exported for custom use.

---
import GithubIcon from "@luciodale/docs-ui-kit/components/GithubIcon.astro";
import LinkedInIcon from "@luciodale/docs-ui-kit/components/LinkedInIcon.astro";
---

<GithubIcon class="w-6 text-white" />
<LinkedInIcon class="w-6 text-white/50" />

| Prop | Type | Required | Description | |---|---|---|---| | class | string | No | CSS classes. Default: "w-5 text-white". |

Typical page structure

Base layout (create in your project)

---
// src/layouts/Base.astro
import SEO from "@luciodale/docs-ui-kit/components/SEO.astro";
import { siteConfig } from "../config";
import "../styles/global.css";

type Props = { title: string; description?: string; type?: "website" | "article" };

const { title, description, type = "website" } = Astro.props;
---

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- fonts -->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
    <link rel="sitemap" href="/sitemap-index.xml" />
    <SEO config={siteConfig} title={title} description={description} currentPath={Astro.url.pathname} type={type} />
  </head>
  <body>
    <slot />
  </body>
</html>

Docs layout wrapper (create in your project)

---
// src/layouts/DocsPage.astro
import DocsLayout from "@luciodale/docs-ui-kit/components/DocsLayout.astro";
import { siteConfig } from "../config";
import Base from "./Base.astro";

type Props = { title: string; description?: string };

const { title, description } = Astro.props;
---

<Base title={title} description={description} type="article">
  <DocsLayout config={siteConfig} currentPath={Astro.url.pathname}>
    <slot />
  </DocsLayout>
</Base>

Home page

---
// src/pages/index.astro
import PageLayout from "@luciodale/docs-ui-kit/components/PageLayout.astro";
import HeroSection from "@luciodale/docs-ui-kit/components/HeroSection.astro";
import FeatureList from "@luciodale/docs-ui-kit/components/FeatureList.astro";
import { siteConfig } from "../config";
import Base from "../layouts/Base.astro";

export const prerender = true;
---

<Base title={siteConfig.title}>
  <PageLayout config={siteConfig} currentPath="/">
    <HeroSection
      title={siteConfig.title}
      description={siteConfig.description}
      installCommand={siteConfig.installCommand}
    >
      <FeatureList features={[
        { highlight: "Type-safe", description: "Full TypeScript support" },
        { highlight: "Lightweight", description: "Zero runtime dependencies", color: "green" },
        { highlight: "Fast", description: "Build-time syntax highlighting", color: "cyan" },
      ]} />
    </HeroSection>
  </PageLayout>
</Base>

Docs page

---
// src/pages/docs/getting-started.astro
import CodeBlock from "@luciodale/docs-ui-kit/components/CodeBlock.astro";
import ContentSection from "@luciodale/docs-ui-kit/components/ContentSection.astro";
import DocsPage from "../../layouts/DocsPage.astro";

export const prerender = true;
---

<DocsPage title="Getting Started" description="Learn how to install and use the library.">
  <ContentSection label="Installation">
    <CodeBlock code="npm install my-library" language="bash" filename="terminal" />
  </ContentSection>

  <ContentSection label="Quick Start">
    <p class="text-white/60 mb-4">Create an instance:</p>
    <CodeBlock code={`import { MyLib } from "my-library";\nconst lib = new MyLib();`} language="tsx" filename="app.ts" />
  </ContentSection>
</DocsPage>

Each ContentSection automatically appears in the right-side table of contents. No manual TOC array needed.

Demo page with React island

---
// src/pages/demo/basic.astro
import ContentSection from "@luciodale/docs-ui-kit/components/ContentSection.astro";
import { MyDemo } from "../../components/MyDemo"; // React component
import DocsPage from "../../layouts/DocsPage.astro";

export const prerender = true;
---

<DocsPage title="Basic Demo" description="Live interactive demo.">
  <ContentSection label="Demo">
    <MyDemo client:load />
  </ContentSection>
</DocsPage>

React islands require @astrojs/react in your Astro project. The docs-ui-kit itself has zero React dependency.

OG Image Generator

Generate a 1200x630 Open Graph preview image for link sharing (Slack, Twitter, Discord, etc.). Reads public/logo.svg for the logo and installCommand from src/config.ts for the npm package name. Outputs public/og-image.png.

bun run og-image <path-to-docs-site>

Example from the docs-ui-kit root:

bun run og-image ../react-socket/packages/docs

Then set ogImage in the docs site config:

export const siteConfig: SiteConfig = {
  // ...
  ogImage: "/og-image.png",
};

The SEO component picks up ogImage and renders og:image, og:image:width, og:image:height, and twitter:image tags automatically.

Color palette

Defined in theme.css via Tailwind v4 @theme tokens:

| Token | Value | Usage | |---|---|---| | --color-accent | #ef4723 | Primary accent. Links, active indicators, buttons. Tailwind: text-accent, bg-accent, border-accent. | | --color-accent-hover | #d63d1f | Hover state for accent. Tailwind: bg-accent-hover. | | --color-primary | #42170c | Deep brown. Available but rarely used directly. | | --color-secondary | #6b7280 | Gray. | | --color-surface | #f9fafb | Light surface (for light-mode contexts). | | --color-border | #e5e7eb | Light border. | | --color-muted | #848d9f | Muted text. |

Body: background: black, color: white. All components use white/ opacity variants for text hierarchy (text-white/70 body text, text-white/60 secondary, text-white/40 labels, text-white/30 decorative).

Responsive behavior

| Breakpoint | Left Sidebar | Content | Right TOC | Mobile Menu | |---|---|---|---|---| | < md (mobile) | Hidden | Full width | Hidden | Hamburger → slide-in from right | | mdxl | Visible (256px) | Flex | Hidden | N/A | | >= xl | Visible (256px) | Flex | Visible (176px) | N/A |

View Transitions compatibility

All client-side scripts (<script> in components) re-initialize on the astro:after-swap event, so everything works with Astro View Transitions out of the box.

License

MIT