Content Management
A headless CMS with collections, entries, locales, and scheduled releases. Manage content from the Content panel or the SDK.
Proyecta has a full headless CMS. It’s schema-first: you define collections (structured content types), then create entries that conform to each collection’s fields. Entries can be localized and grouped into scheduled releases.
The Content panel
Section titled “The Content panel”Content can be managed via the SDK or by asking the AI. The Content API has four resource types:
| Tab | What it’s for |
|---|---|
| Collections | Define and manage content schemas (e.g., “Blog Post”, “FAQ”, “Product Spec”) |
| Entries | Browse, create, edit, publish, and delete entries within a collection |
| Locales | Add and manage language/region locales for translated content |
| Releases | Schedule groups of entries to go live (or get unpublished) at the same time |
Click a collection in the Collections tab to jump to its entries. The Entries tab lets you create, edit, publish, and delete individual content items.
You can also manage everything programmatically via the SDK (proyecta.content).
Concepts
Section titled “Concepts”| Concept | What it is |
|---|---|
| Collection | A schema — the shape of one type of content (e.g. “Blog Post”, “FAQ”, “Product Spec”) |
| Field | A typed slot in a collection (e.g. title: string, body: rich_text, coverImage: asset) |
| Entry | A single instance of a collection (one blog post, one FAQ item) |
| Asset | An uploaded media file referenceable from entries |
| Locale | A language/region the content is translated into |
| Release | A group of entries scheduled to go live (or get unpublished) at the same time |
Quickstart
Section titled “Quickstart”import Proyecta from '@proyecta-ai/sdk';
const proyecta = new Proyecta({ apiKey: process.env.PROYECTA_API_KEY });
// 1. Define a collectionconst blog = await proyecta.content.collections.create({ name: 'Blog Post', // fields are defined per the Field type — title, body, coverImage, etc.});
// 2. Create an entryconst post = await proyecta.content.entries.create({ collection_id: blog.id, data: { title: 'Hello, world', body: 'My very first post.', },});
// 3. Publish itawait proyecta.content.entries.publish(post.id, {});Collections
Section titled “Collections”// Browse collectionsfor await (const collection of proyecta.content.collections.list()) { console.log(collection.name);}
// Update a collection schemaawait proyecta.content.collections.update(blog.id, { /* ... */ });
// Delete a collectionawait proyecta.content.collections.delete(blog.id);Entries
Section titled “Entries”Entries are the actual content rows. Each entry belongs to a collection and carries data matching that collection’s fields.
// Browse entriesfor await (const entry of proyecta.content.entries.list({ collection_id: blog.id })) { console.log(entry);}
// Update an entryawait proyecta.content.entries.update(post.id, { data: { title: 'Updated title' } });
// Publish an entryawait proyecta.content.entries.publish(post.id, {});
// Delete an entryawait proyecta.content.entries.delete(post.id);Assets
Section titled “Assets”Asset uploads are first-class — use them to attach images, videos, or PDFs to your entries:
// Browse assetsfor await (const asset of proyecta.content.assets.list()) { console.log(asset);}
// Upload, update, or delete via assets.create / assets.update / assets.deleteFor chat-driven file uploads (drag-into-builder), see Files & Media.
Localization
Section titled “Localization”Content can be translated into multiple locales. Each locale is a record managed via proyecta.content.locales:
await proyecta.content.locales.create({ /* code, name, etc. */});
for await (const locale of proyecta.content.locales.list()) { console.log(locale);}When you fetch entries, you can request a specific locale’s translation. See Internationalization for the broader i18n picture.
Releases (scheduled publishing)
Section titled “Releases (scheduled publishing)”A release is a bundle of entries that go live (or get unpublished) at the same time. This lets you stage a coordinated content drop — a marketing launch, a new product page, a FAQ refresh — and have everything flip atomically.
// Schedule a release for next Mondayawait proyecta.content.releases.schedule({ /* release id, scheduled_at, items: [{ entry_id, action: 'publish' | 'unpublish' }] */});
// Update a releaseawait proyecta.content.releases.update(releaseId, { /* ... */ });
// Browse releasesfor await (const release of proyecta.content.releases.list()) { console.log(release);}Common patterns (let the AI wire it up)
Section titled “Common patterns (let the AI wire it up)”"Build a blog using the Proyecta Content API. Collection 'Blog Post' with fields: title, slug, excerpt, body (rich text), coverImage (asset), author. Public route at /blog and /blog/[slug].""Create an FAQ collection in Proyecta Content. Build an admin page where I can add/edit FAQs and a public /faq page.""Set up a multi-language landing page using Proyecta Content with English and Spanish locales.""Schedule a release of three blog posts to go live next Monday at 9am."
When to use Content vs Database
Section titled “When to use Content vs Database”| Use case | Use this |
|---|---|
| Editorial content (posts, FAQs, marketing copy) — needs publish/draft states, scheduling, localization | Content API |
| App data (users, orders, line items) — needs query speed, transactions, real-time | Database |
| Static assets in code | public/ directory in your project |
| User-uploaded files | Files & Media |
Coming soon
Section titled “Coming soon”- Rich-text entry editor — full WYSIWYG editing for
rich_textfields in the Content panel - Live preview of content changes against your app
- Content roles — separate editor permissions from developer permissions