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

@sleekcms/client

v3.1.1

Published

Official SleekCMS content client for Node 18+ and browser

Readme

@sleekcms/client

Official JavaScript/TypeScript client for SleekCMS - a headless CMS that lets you manage content and deliver it via API.

Sign in at sleekcms.com, create your content models, add your content, then grab your site token and use this library to integrate content in your apps.

Installation

From NPM

npm install @sleekcms/client

From CDN (Browser)

Include the library directly in your HTML from a CDN:

<!-- From unpkg -->
<script src="https://unpkg.com/@sleekcms/client"></script>

<!-- From jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/@sleekcms/client"></script>

<!-- Specific version -->
<script src="https://unpkg.com/@sleekcms/[email protected]"></script>

The library is available globally as SleekCMS:

<script src="https://unpkg.com/@sleekcms/client"></script>
<script>
  // Use the sync client
  SleekCMS.createSyncClient({
    siteToken: 'your-site-token',
    env: 'latest'
  }).then(client => {
    const page = client.getPage('/about');
    console.log(page);
  });

  // Or use the async client
  const client = SleekCMS.createAsyncClient({
    siteToken: 'your-site-token'
  });
  
  client.getPage('/pricing').then(page => {
    console.log(page);
  });
</script>

Quick Start

import { createSyncClient } from '@sleekcms/client';

const client = await createSyncClient({
  siteToken: 'your-site-token',
  env: 'latest'
});

// Get a page
const page = client.getPage('/about');

// Get all blog posts
const posts = client.getPages('/blog');

// Get an entry
const footer = client.getEntry('footer');

Sync vs Async Clients

Sync Client (Recommended for SSG)

createSyncClient() fetches all content upfront and returns a client with synchronous methods. Best for static site generation where you build once and want instant access to content.

// Async initialization, sync usage
const client = await createSyncClient({
  siteToken: 'your-site-token'
});

// All methods return data immediately (no await)
const page = client.getPage('/pricing');
const slugs = client.getSlugs('/blog');

Use when:

  • Building static sites (Next.js SSG, Astro, 11ty)
  • You need all content at build time
  • You want predictable performance

Async Client (Recommended for SSR)

createAsyncClient() fetches content on-demand. Best for server-side rendering where you want fresh content per request without loading everything.

const client = createAsyncClient({
  siteToken: 'your-site-token',
  resolveEnv: true  // optional: resolve env to version tag to invalidate CDN cache if required
});

// All methods are async
const page = await client.getPage('/pricing');
const posts = await client.getPages('/blog');

Use when:

  • Server-side rendering (Next.js SSR, SvelteKit, Remix)
  • You only need specific content per request
  • You want the latest content on each request

Configuration

| Option | Type | Default | Description | |--------|------|---------|-------------| | siteToken | string | required | Your site token from SleekCMS | | env | string | 'latest' | Environment/alias name | | resolveEnv | boolean | false | Env is an alias to version. This flag resolves env to version tag, so as to bypass CDN cache. Add's some latency.| | lang | string | - | Language code for internationalized content | | cache | SyncCacheAdapter \| AsyncCacheAdapter | In-memory cache | Custom cache adapter for storing fetched content | | cacheMinutes | number | - | Cache expiration time in minutes. If not set, cache never expires |

Internationalization Example:

// Fetch Spanish content
const client = await createSyncClient({
  siteToken: 'your-site-token',
  lang: 'es'
});

const page = client.getPage('/about');
// Returns Spanish version of the page

Caching

The client includes built-in caching support to improve performance and reduce API calls. By default, an in-memory cache is used, but you can provide your own cache adapter.

Default In-Memory Cache

const client = await createSyncClient({
  siteToken: 'your-site-token'
});
// Uses built-in memory cache automatically

Using localStorage

const client = await createSyncClient({
  siteToken: 'your-site-token',
  cache: localStorage,  // Use browser's localStorage
  cacheMinutes: 60*24      // Cache expires after 1 day
});

Cache Adapter Interface

Any object with getItem and setItem methods works as a cache adapter:

// Synchronous cache adapter
interface SyncCacheAdapter {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
}

// Asynchronous cache adapter
interface AsyncCacheAdapter {
  getItem(key: string): Promise<string | null>;
  setItem(key: string, value: string): Promise<void>;
}

Cache Expiration

Use cacheMinutes to set when cached content expires:

const client = await createSyncClient({
  siteToken: 'your-site-token',
  cache: localStorage,
  cacheMinutes: 60*24  // Cache expires after 1 day
});

If cacheMinutes is not set, cached content never expires (until cleared manually).

API Reference

getContent(search?)

Get all content or use a JMESPath search/query to filter it.

// Get everything
const content = client.getContent();

// Get only pages using JMESPath
const pages = client.getContent('pages');

// Get config title
const title = client.getContent('config.title');

getPages(path)

Get all pages that start with a specific path.

const posts = client.getPages('/blog');
const products = client.getPages('/shop/products');

getPage(path)

Get a single page by exact path. Returns null if not found.

const about = client.getPage('/about');
const post = client.getPage('/blog/hello-world');

getEntry(handle)

Get an entry by handle. Entries can be single objects or arrays.

const header = client.getEntry('header');
const team = client.getEntry('team-members'); // could be an array

getSlugs(path)

Extract slugs from pages under a path. Useful for static site generation.

const slugs = client.getSlugs('/blog');
// ['hello-world', 'nextjs-tips', 'typescript-guide']

getImage(name)

Get an image by name.

const logo = client.getImage('logo');
// { url: 'https://...', alt: '...', ... }

getOptions(name)

Get a option set (array of label/value pairs).

const categories = client.getOptions('categories');
// [{ label: 'Tech', value: 'tech' }, ...]

Framework Examples

Next.js App Router (SSG)

// app/blog/page.tsx
import { createSyncClient } from '@sleekcms/client';

export default async function BlogPage() {
  const client = await createSyncClient({
    siteToken: process.env.SLEEKCMS_SITE_TOKEN!
  });

  const posts = client.getPages('/blog');

  return (
    <div>
      {posts?.map((post) => (
        <article key={post._path}>
          <h2>{post.title}</h2>
        </article>
      ))}
    </div>
  );
}

Generate Static Paths

// app/blog/[slug]/page.tsx
import { createSyncClient } from '@sleekcms/client';

export async function generateStaticParams() {
  const client = await createSyncClient({
    siteToken: process.env.SLEEKCMS_SITE_TOKEN!
  });

  const slugs = client.getSlugs('/blog');

  return slugs.map((slug) => ({ slug }));
}

export default async function Post({ params }: { params: { slug: string } }) {
  const client = await createSyncClient({
    siteToken: process.env.SLEEKCMS_SITE_TOKEN!
  });

  const post = client.getPage(`/blog/${params.slug}`);

  return <h1>{post?.title}</h1>;
}

SvelteKit (SSR)

// +page.server.ts
import { createAsyncClient } from '@sleekcms/client';

const client = createAsyncClient({
  siteToken: process.env.SLEEKCMS_SITE_TOKEN,
  resolveEnv: true
});

export async function load() {
  const posts = await client.getPages('/blog');
  return { posts };
}

Astro

---
// src/pages/blog/index.astro
import { createSyncClient } from '@sleekcms/client';

const client = await createSyncClient({
  siteToken: import.meta.env.SLEEKCMS_SITE_TOKEN
});

const posts = client.getPages('/blog');
---

<div>
  {posts?.map((post) => (
    <article>
      <h2>{post.title}</h2>
    </article>
  ))}
</div>

TypeScript

The client is fully typed:

import type { 
  SleekClient, 
  SleekAsyncClient,
  Page,
  Entry,
  Image,
  Options 
} from '@sleekcms/client';

License

MIT