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

@simplerdevelopment/sdk

v0.1.0

Published

TypeScript SDK for the SimplerDevelopment platform

Readme

@simplerdevelopment/sdk

TypeScript client for the SimplerDevelopment REST v1 read surface. Use it to fetch published content, products, branding, and navigation from a SimplerDevelopment-powered site — suitable for headless renderers, static-site generators, and server-side data fetching.

Install

npm install @simplerdevelopment/sdk
# or
bun add @simplerdevelopment/sdk

Quick start

import { SimplerDevelopment } from '@simplerdevelopment/sdk';

const client = new SimplerDevelopment({
  siteId: 42,           // numeric site ID from the portal
  apiKey: 'sd_live_…', // portal-issued API key (optional for public endpoints)
});

// List published posts
const { data: posts, pagination } = await client.posts.list({ limit: 10, postType: 'blog' });

// Fetch a single post by slug
const post = await client.posts.get('my-first-post');

// Get site branding (no API key required)
const { branding, cssVars } = await client.branding.get();

// List products filtered by category
const { data: products } = await client.products.list({ category: 'apparel', sort: 'price_asc' });

Authentication

API keys are prefixed sd_live_ and are issued in the portal under Settings → API Keys.

Pass the key as apiKey in the constructor. The SDK sends it as the X-Api-Key header on every request. Omitting the key still works for the four public endpoints: config, branding, navigation, and blocks.

const client = new SimplerDevelopment({ siteId: 42, apiKey: 'sd_live_…' });

Rate limit: 60 requests / minute per key + site. On a 429 response the SDK throws a RateLimitError whose .retryAfter property contains the wait in seconds.

Configuration

| Option | Type | Required | Default | Description | |---|---|---|---|---| | siteId | number | Yes | — | Numeric ID of the site to query | | apiKey | string | No | — | sd_live_ API key; omit for unauthenticated calls | | baseUrl | string | No | https://simplerdevelopment.com | Override for self-hosted or preview deployments | | fetch | typeof globalThis.fetch | No | globalThis.fetch | Custom fetch implementation (useful in Node < 18 or test mocking) |

Resources and methods

client.config

client.config.get(): Promise<SiteConfig>

Returns the full site bundle: metadata, branding, CSS vars, navigation tree, and storeEnabled flag.

client.branding

client.branding.get(): Promise<{ branding: Branding; cssVars: string }>

Returns the brand color palette, logo URLs, typography settings, and a pre-built CSS custom-property string.

client.navigation

client.navigation.get(): Promise<NavItem[]>

Returns the navigation menu as a nested tree (NavItem.children).

client.posts

client.posts.list(params?: ListPostsParams): Promise<{ data: PostSummary[]; pagination: ... }>
client.posts.get(slug: string): Promise<Post>

list supports limit, offset, postType, category (slug), tag (slug), and search. get returns the full post including content, categories, tags, and SEO fields.

client.pages

client.pages.list(params?: { limit?: number; offset?: number; search?: string }): Promise<{ data: PostSummary[]; pagination: ... }>

Equivalent to posts.list filtered to postType = "page".

client.categories

client.categories.list(): Promise<Category[]>

Returns all categories sorted alphabetically.

client.tags

client.tags.list(): Promise<Tag[]>

Returns all tags sorted alphabetically.

client.media

client.media.list(params?: ListMediaParams): Promise<{ data: MediaItem[]; pagination: ... }>

Supports limit, offset, and mimeType (prefix match, e.g. image/).

client.products

client.products.list(params?: ListProductsParams): Promise<{ data: Product[]; pagination: ... }>
client.products.get(slug: string): Promise<ProductDetail>

list supports category (slug), search, sort (newest | price_asc | price_desc | featured), page, and limit. get returns full product detail including images, options, variants, and bulk pricing.

client.productCategories

client.productCategories.list(): Promise<ProductCategory[]>

Returns all active product categories with live product counts.

client.blocks

client.blocks.list(): Promise<BlockDefinition[]>

Returns the full block catalog — types, display names, categories, and input schemas. No API key required.

Error handling

All errors extend SDKError (which extends Error).

import { NotFoundError, UnauthorizedError, RateLimitError, SDKError } from '@simplerdevelopment/sdk';

try {
  const post = await client.posts.get('unknown-slug');
} catch (err) {
  if (err instanceof NotFoundError) {
    // 404 — resource does not exist
  } else if (err instanceof UnauthorizedError) {
    // 401 — invalid or missing API key
  } else if (err instanceof RateLimitError) {
    // 429 — rate limited; wait err.retryAfter seconds
    console.log(`Retry after ${err.retryAfter}s`);
  } else if (err instanceof SDKError) {
    // any other HTTP error; err.status is the HTTP status code
  }
}

Which API surface does this cover?

This SDK wraps the REST v1 surface only (/api/v1/sites/{siteId}/…). It covers all 13 read-only endpoints in that surface.

Other API surfaces — the Portal internal API, the Public (unauthenticated) API, and the MCP tool surface — are not covered. See docs/agents/api-index.md for a description of all four surfaces.

Limitations

  • Read-only. The REST v1 surface itself exposes no write operations; this SDK mirrors that constraint.
  • Site-scoped. One SimplerDevelopment instance is bound to one siteId. Instantiate multiple clients to query multiple sites.
  • No streaming. All methods resolve a single Promise; there is no streaming or SSE support.
  • No caching. Caching (ISR, SWR, etc.) is the responsibility of the calling application.