skriplet
v0.1.0
Published
Lightweight headless CMS powered by markdown files
Downloads
12
Maintainers
Readme
skriplet
Lightweight headless CMS powered by markdown files. Drop .md files into a folder, get structured data and a clean JSON API back. No database, no dashboard, no config.
Install
bun add skriplet
# npm install skriplet
# pnpm add skriplet
# yarn add skripletRequires Node.js 18+.
How It Works
Skriplet reads a content/ directory from your project root. Each subdirectory is a collection, each .md file inside it is an item, and the filename becomes the slug.
content/
blog/
hello-world.md → slug: "hello-world"
second-post.md → slug: "second-post"
docs/
introduction.md → slug: "introduction"YAML frontmatter in each file becomes structured data:
---
title: Hello World
date: 2026-01-15
tags: [intro, welcome]
published: true
---
Your markdown content goes here.API
getCollections(contentDir?)
List all collections with item counts.
import { getCollections } from 'skriplet'
const collections = await getCollections()
// [{ name: 'blog', count: 3 }, { name: 'docs', count: 2 }]getCollection(name, contentDir?)
Get all items in a collection, sorted alphabetically by slug.
import { getCollection } from 'skriplet'
const collection = await getCollection('blog')
// {
// name: 'blog',
// count: 2,
// items: [
// {
// slug: 'hello-world',
// collection: 'blog',
// data: { title: 'Hello World', date: '2026-01-15', published: true },
// content: 'Your markdown content goes here.',
// raw: '---\ntitle: Hello World\n...'
// }
// ]
// }Returns null if the collection doesn't exist.
getItem(collection, slug, contentDir?)
Get a single item by collection name and slug.
import { getItem } from 'skriplet'
const item = await getItem('blog', 'hello-world')
// {
// slug: 'hello-world',
// collection: 'blog',
// data: { title: 'Hello World', ... },
// content: 'Your markdown content goes here.',
// raw: '---\ntitle: Hello World\n...'
// }Returns null if the item doesn't exist.
parseFrontmatter(raw)
Parse a raw markdown string with YAML frontmatter. Useful if you're reading files yourself.
import { parseFrontmatter } from 'skriplet'
const { data, content } = parseFrontmatter(`---
title: My Post
published: true
tags: [a, b]
---
Body content here.
`)
// data → { title: 'My Post', published: true, tags: ['a', 'b'] }
// content → 'Body content here.'Supports strings, numbers, booleans, null, and inline arrays. No external dependencies.
Custom Content Directory
All functions accept an optional contentDir path as the last argument:
import path from 'path'
import { getCollections } from 'skriplet'
const collections = await getCollections(path.join(process.cwd(), 'my-content'))TypeScript
Full types are included — no @types package needed.
import type { ContentItem, Collection, CollectionMeta } from 'skriplet'| Type | Description |
|---|---|
| CollectionMeta | { name: string, count: number } |
| Collection | CollectionMeta & { items: ContentItem[] } |
| ContentItem | { slug, collection, data, content, raw } |
Usage with Next.js
// app/blog/page.tsx (Server Component)
import { getCollection } from 'skriplet'
export default async function BlogPage() {
const collection = await getCollection('blog')
return (
<ul>
{collection?.items.map(post => (
<li key={post.slug}>{post.data.title as string}</li>
))}
</ul>
)
}Usage with Astro
---
import { getCollection } from 'skriplet'
const collection = await getCollection('blog')
---
{collection?.items.map(post => <h2>{post.data.title}</h2>)}License
MIT
