Caisy
caisy is a headless CMS designed for speed and scalability, empowering developers
You are a front-end or full-stack developer specializing in delivering performant web applications powered by modern headless CMS solutions. You leverage caisy to manage structured content, ensuring rapid content delivery and a smooth developer experience within a composable architecture. ## Key Points * **Use Environments:** Structure your caisy project with different environments (development, staging, production) to manage content workflows and ensure proper testing before content goes live. * **Secure API Keys:** Always use read-only API keys for client-side applications. Keep your master/write API keys secure and use them only in backend contexts or build processes. * **Model Content Logically:** Design your content models in caisy to be modular and reusable. Avoid monolithic models that try to contain everything; instead, compose smaller, focused models. ## Quick Example ```bash npm install @caisy/sdk-js graphql # or yarn add @caisy/sdk-js graphql ```
skilldb get cms-services-skills/CaisyFull skill: 250 linesYou are a front-end or full-stack developer specializing in delivering performant web applications powered by modern headless CMS solutions. You leverage caisy to manage structured content, ensuring rapid content delivery and a smooth developer experience within a composable architecture.
Core Philosophy
caisy is built from the ground up to be an API-first headless CMS with a strong emphasis on developer experience and performance. Its core philosophy revolves around providing a blazingly fast GraphQL API, robust content modeling capabilities, and an intuitive authoring experience, all without compromising on scalability. It's designed for modern web applications that demand speed, flexibility, and a streamlined development workflow.
You choose caisy when your project requires a CMS that integrates seamlessly into a JAMstack, serverless, or microservices architecture. It excels in scenarios where content needs to be delivered globally with low latency, where developers prefer working with GraphQL for precise data fetching, and where content editors require a powerful yet user-friendly interface. caisy encourages a composable approach, allowing you to pair it with your preferred front-end framework, search solutions, and other services.
The platform's GraphQL-native approach means that every content model and field type is immediately available through a highly optimized GraphQL endpoint. This eliminates the need for complex API configurations, allowing you to focus on building your application rather than wrestling with API schemas. caisy's global CDN ensures that your content is always delivered quickly, regardless of your users' location.
Setup
To integrate caisy into your web application, you typically use its JavaScript SDK for fetching content.
First, install the SDK:
npm install @caisy/sdk-js graphql
# or
yarn add @caisy/sdk-js graphql
Next, initialize the SDK with your Project ID and an API key. You obtain these from your caisy project settings in the dashboard. For client-side applications, ensure you use a read-only API key.
// src/lib/caisy.ts
import { CaisySDK } from '@caisy/sdk-js';
// Environment variables are recommended for API keys and project IDs
const CAISY_PROJECT_ID = process.env.NEXT_PUBLIC_CAISY_PROJECT_ID || '';
const CAISY_API_KEY = process.env.NEXT_PUBLIC_CAISY_API_KEY || '';
if (!CAISY_PROJECT_ID || !CAISY_API_KEY) {
console.warn('CAISY_PROJECT_ID or CAISY_API_KEY is not set. Caisy SDK will not function.');
}
export const caisySDK = new CaisySDK({
projectID: CAISY_PROJECT_ID,
accessToken: CAISY_API_KEY,
// Optional: Set locale if your project uses multiple languages
// locale: 'en_US',
});
Now you can import caisySDK and use it to query your content.
Key Techniques
1. Fetching a Single Content Entry by Slug
You often need to retrieve a specific page or article based on its unique slug. caisy's GraphQL API makes this straightforward.
// src/pages/[slug].tsx (example for Next.js)
import { caisySDK } from '../lib/caisy';
import { HomePageDocument } from '../../generated/graphql'; // Assuming GraphQL codegen
interface PageProps {
page: any; // Type this more specifically based on your content model
}
export async function getStaticProps({ params }: { params: { slug: string } }) {
try {
const { Homepage } = await caisySDK.Homepage({
// Use the query generated by GraphQL Codegen
slug: params.slug,
locale: 'en_US', // Specify locale if applicable
});
if (!Homepage || Homepage.length === 0) {
return { notFound: true };
}
return {
props: {
page: Homepage[0],
},
revalidate: 60, // Revalidate every 60 seconds
};
} catch (error) {
console.error('Error fetching page:', error);
return { notFound: true };
}
}
const PageDetail: React.FC<PageProps> = ({ page }) => {
if (!page) return <div>Loading...</div>; // Or handle notFound
return (
<div>
<h1>{page.title}</h1>
<div dangerouslySetInnerHTML={{ __html: page.content.json }} />
{/* Render other fields */}
</div>
);
};
export default PageDetail;
2. Fetching Multiple Entries with Filtering and Pagination
For listings, blogs, or collections, you'll need to fetch multiple items, often with filtering, sorting, and pagination.
// src/components/BlogList.tsx
import React, { useEffect, useState } from 'react';
import { caisySDK } from '../lib/caisy';
import { AllBlogPostsDocument } from '../../generated/graphql';
interface BlogPost {
_meta: { id: string };
title: string;
slug: string;
excerpt?: string;
}
const BlogList: React.FC = () => {
const [posts, setPosts] = useState<BlogPost[]>([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const postsPerPage = 10;
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
try {
const { allBlogPost } = await caisySDK.AllBlogPosts({
locale: 'en_US',
first: postsPerPage,
skip: (currentPage - 1) * postsPerPage,
// Example filter:
// where: {
// category: {
// title: {
// contains: 'Technology'
// }
// }
// },
sort: {
_meta: {
createdAt: 'DESC',
},
},
});
setPosts(allBlogPost?.edges?.map(edge => edge?.node as BlogPost) || []);
} catch (error) {
console.error('Error fetching blog posts:', error);
} finally {
setLoading(false);
}
};
fetchPosts();
}, [currentPage]);
if (loading) return <div>Loading posts...</div>;
return (
<div>
{posts.map((post) => (
<article key={post._meta.id}>
<h2><a href={`/blog/${post.slug}`}>{post.title}</a></h2>
<p>{post.excerpt}</p>
</article>
))}
<button onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))} disabled={currentPage === 1}>Previous</button>
<span> Page {currentPage} </span>
<button onClick={() => setCurrentPage(prev => prev + 1)} disabled={posts.length < postsPerPage}>Next</button>
</div>
);
};
export default BlogList;
3. Handling Assets (Images and Files)
caisy manages assets and provides optimized URLs. You can access these URLs and transformation options directly through the SDK.
// When querying a content entry that has an asset field, e.g., 'mainImage'
// Assume BlogPost has a field `mainImage` of type Asset
interface BlogPost {
title: string;
mainImage?: {
src?: string;
description?: string;
width?: number;
height?: number;
// Caisy provides advanced image transformation options directly in the URL
// You can also construct these manually if needed
};
}
// In your component or utility function:
const renderImage = (imageAsset: BlogPost['mainImage']) => {
if (!imageAsset?.src) return null;
// Example of using caisy's image transformation parameters
// You can append these to the src URL
const optimizedSrc = `${imageAsset.src}?fm=webp&q=75&w=800`; // Format webp, quality 75, width 800
return (
<img
src={optimizedSrc}
alt={imageAsset.description || ''}
width={imageAsset.width}
height={imageAsset.height}
loading="lazy"
/>
);
};
// In your React component's render method:
const BlogPostDetail: React.FC<{ post: BlogPost }> = ({ post }) => {
return (
<article>
<h1>{post.title}</h1>
{post.mainImage && renderImage(post.mainImage)}
{/* ... rest of your content */}
</article>
);
};
Best Practices
- Utilize GraphQL Fragments: For complex content models, define reusable GraphQL fragments to keep your queries clean, maintainable, and prevent redundant field definitions across multiple queries.
- Implement Client-Side Caching: Combine the caisy SDK with a client-side caching library (e.g., Apollo Client, React Query, SWR) to minimize redundant network requests and improve perceived performance.
- Optimize Image Delivery: Always use caisy's built-in image transformation parameters (
w,h,fm,q) to serve optimized images (e.g., WebP, lower quality for thumbnails) directly from the CDN. - Leverage Webhooks for Real-Time Updates: Configure webhooks in caisy to trigger build processes (e.g., for static site generators) or invalidate caches whenever content is published or updated, ensuring your site always shows the latest content.
- Use Environments: Structure your caisy project with different environments (development, staging, production) to manage content workflows and ensure proper testing before content goes live.
- Secure API Keys: Always use read-only API keys for client-side applications. Keep your master/write API keys secure and use them only in backend contexts or build processes.
- Model Content Logically: Design your content models in caisy to be modular and reusable. Avoid monolithic models that try to contain everything; instead, compose smaller, focused models.
Anti-Patterns
- Over-fetching Data. Requesting
*or all fields when you only need a few. Only specify the exact fields your component requires in your GraphQL queries to minimize payload size and improve API response times. - Hardcoding Content IDs/Slugs. Avoid embedding specific content IDs or slugs directly in your code. Instead, fetch content dynamically based on routes or use environment variables/configuration for frequently referenced items.
- Exposing Master API Keys. Never include your caisy master API key (with write permissions) in client-side code. This is a severe security risk. Use read-only API keys for public-facing applications.
- Ignoring Asset Optimization. Displaying original, large image files directly from caisy's asset URLs without applying transformations. Always optimize images for web delivery using caisy's transformation parameters to improve page load speed.
- Monolithic Queries. Writing extremely long and complex GraphQL queries for an entire page in a single request. Break down your queries using fragments and fetch data closer to where it's used, especially for components.
Install this skill directly: skilldb add cms-services-skills
Related Skills
Builder Io
Builder.io is a Visual Headless CMS and API that empowers developers to integrate
Contentful
Build with Contentful for headless content management. Use this skill when the
Cosmic
Integrate Cosmic as your headless content management system, providing
Directus
Build with Directus for database-first content management. Use this skill
Ghost
Integrate Ghost as a powerful headless CMS or a full-featured publishing platform.
Hygraph
Build with Hygraph (formerly GraphCMS) as a GraphQL-native headless CMS.