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

@molecule/api-content

v1.0.5

Published

Content core interface: read a directory of front-matter markdown files into typed records (front matter, body, slug, path, draft), validating loudly; bond a provider for the parsing

Readme

@molecule/api-content

Content core interface for molecule.dev: a directory of front-matter files (markdown posts, docs pages, changelog entries) read into typed records. Defines the ContentProvider contract and the record shape; bond packages (e.g. @molecule/api-content-markdown) do the parsing. Application and build code calls readContentDirectory() and never parses a file itself.

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

import { readContentDirectory, setProvider } from '@molecule/api-content'
import { provider as markdown } from '@molecule/api-content-markdown'

setProvider(markdown) // once, at startup (bonds.ts) or in a build script

const posts = await readContentDirectory('content/posts', {
  requiredFields: ['title', 'date', 'description'],
})
// → [{ slug, path, frontMatter, body, draft: false, date, title }, …] newest first

Type

core

Installation

npm install @molecule/api-content @molecule/api-bond @molecule/api-i18n

API

Interfaces

ContentRecord

One content file, parsed. The shape every content provider returns, whatever the on-disk format (markdown with YAML front matter today).

interface ContentRecord {
  /**
   * URL-safe identifier: lowercase letters, digits and hyphens, from the
   * front matter's `slug` when present, else the file name without its
   * extension. Unique within one `readDirectory` call.
   */
  slug: string
  /** The file's path as given to the provider (absolute when the directory was). */
  path: string
  /** The parsed front matter as a plain object (never null; `{}` when the file has none). */
  frontMatter: Record<string, unknown>
  /** The body after the front matter, with the leading blank line removed. */
  body: string
  /** `true` when the front matter says `draft: true`. */
  draft: boolean
  /**
   * The front matter's `date` normalized to an ISO-8601 string when present
   * and valid; `undefined` when the file has no date.
   */
  date?: string
  /** The front matter's `title` when it is a string. */
  title?: string
}

ContentReadOptions

Options for parse and readDirectory.

interface ContentReadOptions {
  /** Include records whose front matter says `draft: true`. Defaults to `false`. */
  includeDrafts?: boolean
  /**
   * Front-matter fields every record must carry (non-empty). A file missing
   * one fails loudly with a `ContentValidationError`; nothing is skipped
   * silently. Defaults to `[]`.
   */
  requiredFields?: string[]
}

ContentSource

What parse reads: the file's source and the path it came from (for errors and record.path).

interface ContentSource {
  /** The file's full text. */
  source: string
  /** Where it came from; used in error messages and `record.path`. */
  path: string
}

ContentValidationError

The error every provider raises for a malformed file: a missing closing front-matter fence, invalid YAML, front matter that is not a mapping, a required field missing or empty, an invalid slug or date, two files with the same slug. Identified by code, never by class, so any provider's error is caught the same way (isContentValidationError).

interface ContentValidationError extends Error {
  /** Always `'CONTENT_VALIDATION'`. */
  code: 'CONTENT_VALIDATION'
  /** The offending file's path. */
  path: string
  /** What was wrong, in one sentence. */
  reason: string
  /** The 1-based line in the file when known. */
  line?: number
}

ContentProvider

Content provider interface. Bond packages implement it against one on-disk format; application and build code reads records and never parses files.

interface ContentProvider {
  /** Provider name identifier. */
  readonly name: string
  /**
   * Parses one file's source into a record.
   *
   * @param input - The file's source and path.
   * @param options - Validation options.
   * @returns The record.
   * @throws {ContentValidationError} When the file is malformed.
   */
  parse(input: ContentSource, options?: ContentReadOptions): ContentRecord
  /**
   * Reads every content file under a directory into records, newest first
   * (by `date`, then by `slug`), drafts excluded unless asked for.
   *
   * @param dir - The directory to read.
   * @param options - Validation and filtering options.
   * @returns The records.
   * @throws {ContentValidationError} On the first malformed file, or a duplicate slug.
   */
  readDirectory(dir: string, options?: ContentReadOptions): Promise<ContentRecord[]>
}

Functions

setProvider(provider)

Registers a content provider as the active singleton. Called by bond packages during application startup, or by a build script.

function setProvider(provider: ContentProvider): void
  • provider — The content provider implementation to bond.

getProvider()

Retrieves the bonded content provider, throwing if none is configured.

function getProvider(): ContentProvider

Returns: The bonded content provider.

hasProvider()

Checks whether a content provider is currently bonded.

function hasProvider(): boolean

Returns: true if a content provider is bonded.

parseContent(input, options)

Parses one file's source into a record through the bonded provider.

function parseContent(input: ContentSource, options?: ContentReadOptions): ContentRecord
  • input — The file's source and path.
  • options — Validation options.

Returns: The record.

readContentDirectory(dir, options)

Reads every content file under a directory through the bonded provider.

function readContentDirectory(dir: string, options?: ContentReadOptions): Promise<ContentRecord[]>
  • dir — The directory to read.
  • options — Validation and filtering options.

Returns: The records, newest first, drafts excluded unless asked for.

isContentValidationError(error)

Whether an error is a content validation error, from any provider.

function isContentValidationError(error: unknown): error is ContentValidationError
  • error — The caught value.

Returns: true when it carries code: 'CONTENT_VALIDATION'.

Available Providers

| Provider | Package | | -------------- | -------------------------------- | | Markdown files | @molecule/api-content-markdown |

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-i18n ^1.0.1

Runtime Dependencies

  • @molecule/api-bond

  • @molecule/api-i18n

  • Validation fails loudly, never silently. A file with an unclosed front-matter fence, invalid YAML, a front matter that is not a mapping, a missing required field, an invalid slug or date, or a slug another file already uses throws a ContentValidationError naming the file (and the line when known). A build that swallows that error ships a site with a post missing; catch it only to report it. Check the shape with isContentValidationError(err), never instanceof, so every provider's error is caught the same way.

  • Drafts are excluded by default. readDirectory drops records whose front matter says draft: true unless includeDrafts is set, so a production build cannot publish a draft by forgetting a filter.

  • Slugs are the URL. slug comes from the front matter when present, else the file name without its extension, and must be lowercase letters, digits and hyphens. Two files with the same slug are an error, not a last-one-wins.

  • Order is newest first by date, then by slug, so an index page can take the records as they come.

  • This package is server-side. Read content in a build step or an API route; never import it from client components.