Quickstart
From nothing to a published entry your site reads. Five steps.
Collections require the Pro plan.
1. Create an API key
In the dashboard, go to Settings -> Developer and create a key with the collection scopes you need:
collections:read- list and read collections and entriescollections:write- create and update collections and entries, set labelscollections:delete- delete collections and entries
The key (flg_...) is shown once. Export it:
export FLOGGY_API_KEY=flg_xxxxxxxxxxxxxxxxxx
2. Create a collection
Curl:
curl -X POST "https://floggy-api.pehcastro.workers.dev/api/collections" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"id": "landing-pages",
"schema": {
"title": "Landing pages",
"fields": [
{ "name": "slug", "type": "string" },
{ "name": "headline", "type": "string" },
{ "name": "body", "type": "richtext" }
],
"indexes": { "title": "headline", "slug": "slug" }
}
}'
CLI:
floggy collections create landing-pages --schema ./schema.json
3. Add an entry
curl -X POST "https://floggy-api.pehcastro.workers.dev/api/collections/landing-pages/entries" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"slug": "black-friday",
"headline": "40% off, this week only",
"body": "<p>Our biggest sale of the year.</p>"
}
}'
The response includes the entry id, its first version, and a labels object.
That entry is a draft. labels came back {}, no production label points at it, and step 5 will not find it. Writing an entry is not publishing it. Step 4 publishes.
4. Publish
Publishing means pointing the production label at a version. Three ways, pick one.
On create. Add label to the body in step 3 and you skip this step entirely:
curl -X POST "https://floggy-api.pehcastro.workers.dev/api/collections/landing-pages/entries" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": { "slug": "black-friday", "headline": "40% off, this week only" },
"label": "production"
}'
The response comes back with "labels": { "production": { "version": 1, "meta": null } }. Over the SDK this needs @floggy/cms 0.2.1 or newer; older versions drop the field, return 201, and leave you a draft with nothing to indicate it.
With the CLI, on an existing entry, by version:
floggy collections versions landing-pages <entryId>
floggy collections promote landing-pages <entryId> 1
Over REST, set the label directly:
curl -X PUT "https://floggy-api.pehcastro.workers.dev/api/collections/landing-pages/entries/<entryId>/labels/production" \
-H "Authorization: Bearer $FLOGGY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "version": "<version>" }'
Editing later works the same way. A PATCH writes a new version but leaves production on the old one, so an edit is invisible until you move the label again.
5. Fetch from your site
Read the published entry with the SDK. No writes, so a read-only key (or none, for public collections) is enough.
// app/[slug]/page.tsx
import { createClient } from "@floggy/cms";
const floggy = createClient({
project: "projecta",
key: process.env.FLOGGY_API_KEY,
});
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
// Default GET serves the `production` label.
const { entries } = await floggy.collections.entries.list("landing-pages", {
slug,
});
const page = entries[0];
if (!page) return null;
return (
<main>
<h1>{page.data.headline}</h1>
<div dangerouslySetInnerHTML={{ __html: page.data.body }} />
</main>
);
}
If entries comes back empty, the entry is still a draft. Go back to step 4.
That is the loop: write structured content, point production at it, read it back on your site. Write and publish are two operations, whether you do them in one call or two.
Next
- Schemas - design the shape, and use
indexesfor fast filtering. - Versioning and labels - drafts, rollback, and branch-like labels.
- A/B testing - ship two variants and promote the winner.