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-articles

v0.2.3

Published

Markdoc article rendering components and layout for dbosoft sites

Readme

@dbosoft/nextjs-articles

Markdoc article rendering framework for dbosoft sites. Provides article page layouts, table of contents, prose styling, and a library of Markdoc tag components (callouts, steps, icons, etc.).

Installation

pnpm add @dbosoft/nextjs-articles

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

Peer Dependencies

react >=19, react-dom >=19, next >=16,
@heroicons/react >=2, @markdoc/markdoc >=0.4, clsx >=2

Dependencies

  • @dbosoft/nextjs-site-core (workspace) — for ArticlePageSEO, ResponsiveTable
  • @dbosoft/nextjs-site-marketing (workspace) — for CodeFence, TerminalFrame

Subpath Exports

| Import | Description | |--------|-------------| | ./components | Article rendering: ArticleInfo, ArticleProse, ArticleImage, ArticleTableOfContents, ArticleTableOfContentsWrapper | | ./markdoc | Markdoc tag components: Callout, Feature, SectionHeader, InlineIcon, Steps, Spacer, Divider | | ./layout | Page layouts: ArticlePage, CategorySlugPage, CategoryPage + helpers |

Setup

1. Tailwind Content Paths

Content paths for @dbosoft packages are handled automatically by resolveDbosoftContent() in your Tailwind config (see @dbosoft/nextjs-site-core setup).

2. Article Data Loader

The package does not load articles from the filesystem — that stays in your app. You provide a loader function:

// lib/articles-server.ts
export async function getArticleBySlug(slugArray: string[]): Promise<Article | null> {
  // Read markdown from filesystem, parse frontmatter, return article
}

The loader must return objects matching the ArticleData interface:

interface ArticleData {
  title: string
  subtitle?: string
  excerpt?: string
  author?: string
  publishDate: string
  readTime?: string
  category: string
  content: string  // raw markdown/markdoc content
}

3. Article Page Configuration

Create a shared config file with site-specific settings. Most Markdoc tags/nodes are built-in — you only need siteUrl and defaultAuthor:

// app/(default)/components/article-config.ts
import { siteConfig } from '@/lib/seo'
import type { ArticlePageConfig } from '@dbosoft/nextjs-articles/layout'

export const articleConfig: ArticlePageConfig = {
  siteUrl: siteConfig.url,
  defaultAuthor: 'dbosoft',
}

All standard tags (callout, steps, feature, terminal, etc.) and nodes (fence → CodeFence, table → ResponsiveTable) are pre-registered. You only need to add site-specific custom tags via config.components, config.tags, and config.nodes (see Customization).

4. Page Routes

Create thin wrapper components in your app:

// app/(default)/components/ArticlePage.tsx
import { ArticlePage as ArticlePageBase } from '@dbosoft/nextjs-articles/layout'
import { getArticleBySlug } from '@/lib/articles-server'
import { articleConfig } from './article-config'

export default async function ArticlePage({ category, slug, article }) {
  return (
    <ArticlePageBase
      category={category}
      slug={slug}
      article={article}
      articleLoader={getArticleBySlug}
      config={articleConfig}
    />
  )
}
// app/(default)/guides/[slug]/page.tsx
import CategorySlugPage from '../../components/CategorySlugPage'

export default async function GuidePage({ params }) {
  return (
    <CategorySlugPage
      category="guides"
      categoryTitle="Guides"
      params={await params}
    />
  )
}
// app/(default)/guides/page.tsx
import CategoryPage from '../components/CategoryPage'

export default function GuidesPage() {
  return (
    <CategoryPage
      category="guides"
      title="Guides"
      description="Step-by-step guides for setting up and using MaxBack."
      emptyMessage="No guides available yet."
    />
  )
}

Built-in Markdoc Tags

These tags are pre-registered in ArticlePage and available in all article markdown:

{% callout %} — Info/Warning/Success boxes

{% callout type="info" title="Note" %}
Important information here.
{% /callout %}

{% callout type="warning" title="Caution" %}
Be careful with this step.
{% /callout %}

Types: info, warning, success, tip, feature

{% sectionheader %} — Styled H2 with gradient accent

{% sectionheader id="installation" %}Installation{% /sectionheader %}

Auto-generates IDs for the table of contents.

{% feature %} — Feature list items

{% feature title="Automatic Backups" %}
Backups run on schedule with zero manual intervention.
{% /feature %}

{% steps %} — Numbered step-by-step instructions

{% steps title="Getting Started" %}
1. **Download** the installer from the downloads page.
2. **Install** using the setup wizard.
3. **Configure** the VSS Writer service.
{% /steps %}

{% image %} — Images with captions and zoom modal

{% image src="/images/dashboard.png" alt="Dashboard" caption="The MaxBack monitoring dashboard" width="800" height="600" /%}

Attributes: src, alt, width, height, caption, priority, sizes, maxWidth

{% icon %} — Inline icons

{% icon type="check" /%} Supported
{% icon type="cross" /%} Not supported

Types: check, cross, warning, info, arrow, lightning, sparkle

{% spacer %} / {% divider %}

{% spacer size="lg" /%}
{% divider style="dots" /%}

Spacer sizes: sm, md, lg. Divider styles: line, dots, fade.

{% terminal %} — Terminal/shell code block

{% terminal title="Install MaxBack" %}
```bash
msiexec /i maxback-setup.msi
```
{% /terminal %}

Code fences and tables

Code fences (```) automatically render with CodeFence (syntax-highlighted via Prism). Tables render with ResponsiveTable (mobile-friendly with data-label attributes). No custom tags needed — these are handled as built-in Markdoc node overrides.

{% article-info %} — Article metadata banner

{% article-info author="John Doe" publishDate="2025-01-15" readTime="5 min read" %}
A brief summary of this article.
{% /article-info %}

Customization

Adding Site-Specific Tags

Register custom tags via ArticlePageConfig.tags and their React components via ArticlePageConfig.components:

// article-config.ts
import PricingLink from '@/components/markdoc/PricingLink'

export const articleConfig: ArticlePageConfig = {
  components: {
    PricingLink,
    // ...other components
  },
  tags: {
    'pricing-link': {
      render: 'PricingLink',
      attributes: {
        plan: { type: String, required: true },
      },
      selfClosing: true,
    },
  },
}

Then use in markdown:

{% pricing-link plan="subscription" /%}

Site-specific tags/components are merged with built-ins. If a name collides, the site-specific version wins.

Overriding Built-in Components

To replace a built-in component (e.g., custom Callout styling), add it to config.components with the same key:

import CustomCallout from '@/components/CustomCallout'

export const articleConfig: ArticlePageConfig = {
  components: {
    Callout: CustomCallout,  // overrides built-in Callout
  },
}

CategoryPage with Custom Article Loaders

CategoryPage accepts an articlesLoader callback. This lets each site control how articles are fetched:

import { CategoryPage } from '@dbosoft/nextjs-articles/layout'
import type { ArticleListItem } from '@dbosoft/nextjs-articles/layout'

async function loadArticles(category: string): Promise<ArticleListItem[]> {
  // Fetch from CMS, filesystem, database, etc.
  return [
    { title: 'Article 1', slug: 'guides/article-1', publishDate: '2025-01-01' },
  ]
}

<CategoryPage
  category="guides"
  title="Guides"
  description="All guides"
  emptyMessage="No guides yet."
  articlesLoader={loadArticles}
  defaultAuthor="Your Team"
/>

generateCategoryMetadata

Helper for Next.js generateMetadata in category slug pages:

import { generateCategoryMetadata } from '@dbosoft/nextjs-articles/layout'
import { getArticleBySlug } from '@/lib/articles-server'

export async function generateMetadata({ params }) {
  const { slug } = await params
  return generateCategoryMetadata(
    'guides',
    'Guides',
    slug,
    getArticleBySlug,
    { siteName: 'MaxBack', defaultAuthor: 'dbosoft' }
  )
}

Prose Styling

ArticleProse applies Tailwind Typography (prose dark:prose-invert) with opinionated defaults for headings, code blocks, blockquotes, and tables. To override, wrap it and pass a className:

import { ArticleProse } from '@dbosoft/nextjs-articles/components'

<ArticleProse className="prose-headings:text-blue-900">
  {content}
</ArticleProse>

Table of Contents

ArticleTableOfContentsWrapper auto-extracts headings from the DOM (article h2[id], h3[id], h4[id]). It renders as a sticky sidebar on desktop and a collapsible dropdown on mobile. No configuration needed — just ensure your headings have id attributes (which SectionHeader does automatically).