Getting Started
This guide gets you from install to a working query.
Install
bash
npm install piqit @piqit/resolvers zodpiqit is the core fluent query API. @piqit/resolvers provides resolver implementations such as fileMarkdown and staticContent.
First Resolver
typescript
import { fileMarkdown } from '@piqit/resolvers'
import { z } from 'zod'
export const posts = fileMarkdown({
base: 'content/posts',
path: '{year}/{slug}.md',
frontmatter: z.object({
title: z.string(),
status: z.enum(['draft', 'published']),
tags: z.array(z.string()).default([]),
}),
body: { html: true, headings: true },
})Option Details
base: base directory for content files.path: path pattern used for scan constraints andparams.*extraction.frontmatter: StandardSchema-compatible schema (Zod works out of the box).body: optional. Enableraw,html, and/orheadings.
First Query
typescript
import { piq } from 'piqit'
import { posts } from './posts-resolver'
const results = await piq
.from(posts)
.scan({ year: '2024' })
.filter({ status: 'published' })
.select('params.slug', 'frontmatter.title', 'body.html')
.exec()
// [{ slug: 'hello-world', title: 'Hello World', html: '<h1>...</h1>' }]Results are flat. The last path segment becomes the key (params.slug -> slug).
Query Steps
scan()narrows by path params (cheap).filter()narrows by frontmatter fields (reads metadata).select()declares returned fields and required resolver work.exec()runs query and returns all rows.
Common Variants
typescript
// Alias output keys
.select({
postSlug: 'params.slug',
postTitle: 'frontmatter.title',
})
// Stream API (currently resolves full result set first, then yields)
for await (const row of piq.from(posts).scan({}).select('params.slug').stream()) {
console.log(row.slug)
}
// Single result helpers
const maybePost = await piq
.from(posts)
.scan({ year: '2024', slug: 'hello-world' })
.select('params.slug', 'frontmatter.title')
.single()
.exec()