kantan-cms
v1.1.1
Published
Official TypeScript library for the Kantan CMS API, with first-class Astro support
Maintainers
Readme
Kantan CMS Library
Official TypeScript library for the Kantan CMS API. Supports both browser and Node.js environments.
Installation
npm install kantan-cmsEntry Points
| Import | Environment | Use for |
| --- | --- | --- |
| kantan-cms/astro | Build-time (Node/Vite) | Astro content helpers — getRecords, getRecord, createClient, … |
| kantan-cms/astro/client | Browser | Astro form submission by collection id — getFormToken, submitForm |
| kantan-cms/nextjs/server | Node.js | Full API client with caching (KantanCms) |
| kantan-cms/nextjs/client | Browser | Form utilities only |
| kantan-cms | Node.js | Alias of nextjs/server (default/back-compat) |
| kantan-cms/server · kantan-cms/client | — | Deprecated aliases of nextjs/server · nextjs/client |
There is also a CLI (npx kantan-cms) for Astro projects — see
Astro quickstart.
Astro quickstart
npm install kantan-cms
npx kantan-cms init # scaffold kantan.config.mjs, src/content/config.ts, .env.example
# fill in .env (KANTAN_API_KEY, KANTAN_PROJECT_ID) and your collection ids
npx kantan-cms sync-content # pull records into src/content/<collection>/*.mdThen consume the synced markdown with Astro's native getCollection(), or fetch live in
frontmatter with kantan-cms/astro. Full guide: docs/how_astro.md.
Import Options (Next.js / generic)
This library provides separate entry points for different environments:
Browser/Client-Side
The client export provides browser-safe form utilities without Node.js dependencies:
import { getFormToken, submitForm } from "kantan-cms/client";
// Get form token
const { token } = await getFormToken("collection-id");
// Submit form data
await submitForm("collection-id", {
token,
data: {
name: "John Doe",
email: "[email protected]"
}
});Note: For full API access (collections, records, schemas, etc.) in the browser, use your server as a proxy or use the server version in a Node.js environment.
Server-Side (Node.js with Caching)
Use the full-featured client with file system caching support:
import { KantanCms } from "kantan-cms/server";
const kantan = new KantanCms({
apiKey: "your-api-key",
projectId: "your-project-id",
baseUrl: "https://api.kantan-cms.com", // optional
useCache: true, // Enable caching (Node.js only)
cachePath: "/tmp/my-cache", // Optional cache directory
clearCacheAtInit: true // Optional: clear cache on initialization
});Default Import (Node.js with Caching)
The default import uses the server version:
import { KantanCms } from "kantan-cms";
const kantan = new KantanCms({
apiKey: "your-api-key",
projectId: "your-project-id"
});
// List all collections
const { collections } = await kantan.getCollections({
pageSize: 10,
pageNum: 1
});
console.log(collections);Authentication
You need two credentials to use the Kantan CMS API:
- API Key - Your authentication key
- Project ID - Your project identifier
Both are passed via HTTP headers (X-API-Key and X-Project-Id) and are automatically added by the library.
API Reference
Collections
List Collections
Get a paginated list of collections in your project.
const response = await kantan.listCollections({
pageSize: 10, // optional, default: 10
pageNum: 1, // optional, default: 1
resp: "minimal" // optional
});
// Or use the alias
const response = await kantan.getCollections({ pageSize: 20 });Count Collections
Get the total number of collections.
const { count } = await kantan.countCollections();
console.log(`Total collections: ${count}`);Get Collection
Get a specific collection by ID.
const { collection } = await kantan.getCollection("collection-uuid");
console.log(collection.name, collection.type);Records
List Records
Get all records in a collection with pagination.
const { records } = await kantan.listRecords("collection-uuid", {
pageSize: 20,
pageNum: 1
});
records.forEach(record => {
console.log(record.id, record);
});Get Record
Get a specific record by ID.
const { record } = await kantan.getRecord(
"collection-uuid",
"record-uuid"
);
console.log(record);Count Records
Get the total number of records in a collection.
const { count } = await kantan.countRecords("collection-uuid");
console.log(`Total records: ${count}`);Schemas
Get Schema Type
Get the schema type structure for a collection. Returns a mapping of custom field keys to their respective types.
const { schema_item } = await kantan.getSchemaType("collection-uuid");
// Example output: { "title": "string", "price": "number", "published": "boolean" }
console.log(schema_item);Forms
Get Form Token
Get a form submission token for a specific collection.
const { token } = await kantan.getFormToken("collection-uuid");
console.log(`Form token: ${token}`);Submit Form
Submit data to a form-type collection.
const result = await kantan.submitForm("collection-uuid", {
data: {
name: "John Doe",
email: "[email protected]",
message: "Hello from the API!"
},
token: "your-form-token" // obtained from getFormToken()
});API Key Validation
Validate API Key
Check if your API key is valid.
const { status } = await kantan.validateApiKey();
if (status === 200) {
console.log("API key is valid!");
}Hosting
Generate Presigned URL
Generate a presigned URL for uploading a zip file for hosting.
const { presigned_zip } = await kantan.generatePresignedUrl();
console.log(`Upload URL: ${presigned_zip.url}`);Update Hosting Status
Update the hosting status for your project.
await kantan.updateHostingStatus({
hosting: {
status: "host_complete",
status_message: "Deployment successful"
}
});Available hosting statuses:
host_errorpreview_errorhost_completepreview_completewaitingrunningerror
TypeScript Support
This library is written in TypeScript and includes full type definitions. All API responses are fully typed.
import {
KantanCms,
Collection,
Record,
CollectionType,
HostingStatus
} from "kantan-cms";
const kantan = new KantanCms({
apiKey: process.env.KANTAN_API_KEY!,
projectId: process.env.KANTAN_PROJECT_ID!
});
// Full type inference
const { collections } = await kantan.getCollections();
collections.forEach((collection: Collection) => {
console.log(collection.name);
});Error Handling
The library throws KantanCmsError for API errors.
import { KantanCms, KantanCmsError } from "kantan-cms";
try {
const { collection } = await kantan.getCollection("invalid-uuid");
} catch (error) {
if (error instanceof KantanCmsError) {
console.error(`API Error (${error.statusCode}): ${error.message}`);
console.error("Response:", error.response);
} else {
console.error("Unexpected error:", error);
}
}Advanced Usage
Custom Base URL
If you're using a custom deployment or proxy:
const kantan = new KantanCms({
apiKey: "your-api-key",
projectId: "your-project-id",
baseUrl: "https://custom-api.example.com"
});Environment Support
Browser Usage
The /client export provides form utilities that work in browsers without Node.js dependencies:
// ✅ Browser-safe form functions
import { getFormToken, submitForm } from "kantan-cms/client";The client version:
- ✅ No Node.js dependencies (no
fs,path, etc.) - ✅ Smaller bundle size
- ✅ Works in all modern browsers
- ✅ Perfect for form submissions
- ❌ No full API access (use server as proxy for collections, records, etc.)
Node.js Usage
For full API access, use the server version:
// ✅ Full API with caching
import { KantaenCms } from "kantan-cms/server";
// ✅ Or the default import (same as server)
import { KantanCms } from "kantan-cms";The server version includes:
- ✅ Full API access (collections, records, schemas, hosting, etc.)
- ✅ File system caching support
- ✅ Cache management methods
- ✅ Form functions
Framework-Specific Examples
Next.js
Server-side API Route:
// app/api/collections/route.ts
import { KantanCms } from "kantan-cms/server";
export async function GET() {
const kantan = new KantanCms({
apiKey: process.env.KANTAN_API_KEY!,
projectId: process.env.KANTAN_PROJECT_ID!,
useCache: true
});
const { collections } = await kantan.getCollections();
return Response.json({ collections });
}Client-side Form:
// app/contact/page.tsx
"use client"
import { getFormToken, submitForm } from "kantan-cms/client";
import { useState } from "react";
export default function ContactPage() {
const [submitted, setSubmitted] = useState(false);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const { token } = await getFormToken("form-collection-id");
await submitForm("form-collection-id", {
token,
data: {
name: formData.get("name"),
email: formData.get("email"),
message: formData.get("message")
}
});
setSubmitted(true);
}
return (
<form onSubmit={handleSubmit}>
{/* form fields */}
</form>
);
}React (Vite/CRA)
// src/components/ContactForm.tsx
import { getFormToken, submitForm } from "kantan-cms/client";
export function ContactForm() {
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const { token } = await getFormToken("form-collection-id");
await submitForm("form-collection-id", {
token,
data: { /* form data */ }
});
}
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}Pagination Helper
Example of paginating through all records:
async function getAllRecords(collectionId: string) {
const allRecords = [];
let pageNum = 1;
const pageSize = 100;
while (true) {
const { records } = await kantan.listRecords(collectionId, {
pageSize,
pageNum
});
if (records.length === 0) break;
allRecords.push(...records);
pageNum++;
if (records.length < pageSize) break; // Last page
}
return allRecords;
}Collection Types
Collections in Kantan CMS can be one of the following types:
custom- Custom content collectionsblog- Blog post collectionsmedia- Media asset collectionsform- Form submission collectionsdict- Dictionary/key-value collections
Requirements
- Node.js >= 18.0.0
- Modern browsers with fetch API support
CommonJS vs ESM
This library supports both CommonJS and ES Modules:
// ESM
import { KantanCms } from "kantan-cms";
// CommonJS
const { KantanCms } = require("kantan-cms");Examples
Blog Integration
// Get all blog posts
const { records: posts } = await kantan.listRecords("blog-collection-id", {
pageSize: 50
});
posts.forEach(post => {
console.log(`${post.title} - ${post.created_at}`);
});Form Submission Flow
// 1. Get form token
const { token } = await kantan.getFormToken("form-collection-id");
// 2. Submit form data
await kantan.submitForm("form-collection-id", {
token,
data: {
fullName: "Jane Smith",
email: "[email protected]",
inquiry: "Product question"
}
});Media Gallery
// Get media collection
const { records: mediaItems } = await kantan.listRecords("media-collection-id");
mediaItems.forEach(item => {
console.log(`${item.filename}: ${item.url}`);
});License
MIT
Support
For issues and questions:
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
