Content Management
Proyecta’s CMS is your app’s primary data layer — not just blog posts and marketing copy, but the real records your app is built on. Collections are provisioned and seeded with real sample content before the UI exists, so your app ships wired to editable data from the first build.
Most Proyecta apps store their data in the built-in CMS. When you describe your app, Proyecta designs a data model, creates the collections it needs, and fills them with realistic sample content — all before a single page is built. Your pages then read that real, owner-editable content through typed hooks the AI wires up for you. For the big-picture story of how this fits together, see How your app’s data works.
You don’t have to think about any of this to get started — it happens automatically. This page explains what’s underneath so you can shape it.
Collections and singletons
Section titled “Collections and singletons”Content is organized into collections and singletons:
| Type | What it is | Examples |
|---|---|---|
| Collection | A content type with many entries — one schema, many rows. | posts, services, testimonials, catalogItems |
| Singleton | A content type with exactly one entry — global, one-off content. | businessInfo, seoSettings |
A collection is a shape; each entry is one item of that shape (one blog post, one service, one FAQ). A singleton holds a single editable record — your business identity, or the hero/section copy for a page.
What kinds of content
Section titled “What kinds of content”Proyecta ships ready-made collection designs — sensible fields, admin hints, and starter content — for the kinds of records real businesses keep: blog posts and articles, services, a product catalog, a food menu, testimonials and reviews, team members, a photo gallery, FAQs, events, locations, downloadable resources, job openings, courses, tours, and accommodation listings, among others.
You never pick from a menu. When you describe your app, Proyecta chooses the ones your brief calls for — your business type, the features you asked for, your language — and creates them, pre-filled with realistic sample content. If your app needs something none of them covers, Proyecta designs a custom collection with its own fields instead.
Because of that, your admin panel shows your app’s collections — not a fixed list. It builds itself from your app’s live content model, so whatever Proyecta created for you, built-in or custom, is exactly what you see and edit. Two Proyecta apps rarely have the same set, and that is by design.
Fields
Section titled “Fields”Every collection is made of typed fields. Field types are enforced end to end — the admin panel renders the right editor, and your pages get correctly-typed values.
| Field type | Use it for |
|---|---|
string |
Short one-line values — titles, names, addresses. |
text |
A paragraph of plain text. |
markdown |
Long-form rich text — article bodies, “about” copy. |
slug |
URL identifier, auto-derived from another field (e.g. the title). |
number |
Counts, ratings, durations. |
money |
A price or currency amount — shown and edited as money. |
boolean |
On/off flags. |
date |
Calendar dates. |
datetime |
Timestamps — publish dates, event start times. |
weeklyHours |
Opening hours for each day of the week. |
asset |
An image, video, or PDF (stored as a public URL). |
reference |
A link to an entry in another collection. |
enum |
A value from a fixed list of choices. |
array |
A list of strings — tags, phone numbers, zones. |
blocks |
Stackable content blocks — a page built from typed sections. |
json |
Structured data that doesn’t fit any of the types above. |
Entries, drafts, and publishing
Section titled “Entries, drafts, and publishing”An entry is one item in a collection. Every entry has a status:
- Draft — a work in progress; never shown on your live site.
- Published — live and visible to visitors.
- Archived — retired, kept out of the way.
Your public pages only ever see published entries — drafts and archived items are hidden automatically, so you can prepare content safely before it goes live.
Managing content (no code required)
Section titled “Managing content (no code required)”There are two ways to add and edit content — neither requires touching code:
- Ask the AI in chat. Just describe the change and it edits the right content for you:
"Add a testimonial from María González: 'Best service in town', 5 stars.""Change the tagline in Business Info to 'Café de especialidad en la Roma'.""Mark the last five contact-form submissions as read."
- Your app’s admin panel. Every published app gets a built-in, sign-in-protected admin panel where you (and staff you grant access to) manage content and form submissions directly — a spreadsheet-style editor per collection, plus the submissions inbox. It configures itself from your app’s live content model, so new collections appear there automatically. See Admin Panel.
Manage your CMS content through your app’s admin panel or the AI — an in-builder content editor is on the roadmap (see Coming soon). A realtime record browser for live-updating apps is coming soon.
How your app reads content
Section titled “How your app reads content”Your pages read content through a set of typed hooks in @/hooks/useContent — and the AI writes that wiring for you. You describe the page; Proyecta generates the components that call these hooks against your real collections. You rarely touch them yourself, but here’s what they do:
| Hook | What it does |
|---|---|
useCollection('posts') |
Lists a collection’s published entries (with optional filter/sort/limit). |
useEntry('posts', slug) |
Fetches one published entry by slug (detail pages). |
useSingleton('businessInfo') |
Reads a singleton (business info, page content). |
useFormSubmit('contactForm') |
Submits a form and reports validation errors. |
// A blog index — exactly the kind of code the AI generates for youimport { useCollection } from '@/hooks/useContent';
function BlogList() { const { data: posts, isLoading } = useCollection('posts', { sort: 'published_at:desc' }); if (isLoading) return <Spinner />; return posts?.map((post) => <PostCard key={post._id} post={post} />);}When Proyecta generates typed interfaces for your collections, the hooks become fully typed (useCollection<Post>('posts')), so your editor autocompletes every field. Reads are hydrated on first paint from a baked snapshot — pages render instantly and SEO-friendly, then refresh live in the background.
Forms are a first-class capability, not something the AI hand-builds. Drop in a form block and it renders the fields, validates input, submits, and shows a success state:
<FormBlock form="contactForm" />Forms come ready-made too — a contact form, a quote request, a booking form, an order form, a registration form — and Proyecta wires the right one into your pages. Submissions land in your app’s admin-panel inbox, and the owner is emailed when a new one arrives. See Forms for the full picture.
Localization
Section titled “Localization”Content can be translated into multiple locales. Fields marked as localized store a value per language, and the read hooks resolve them through a fallback chain (requested language → configured fallbacks → default) when you pass the visitor’s active locale:
const { data: posts } = useCollection('posts', { locale: 'es' });Single-language apps ignore locales entirely — there’s nothing to configure. For the broader translation story, see Internationalization.
Releases
Section titled “Releases”A release bundles several entries so they go live (or get unpublished) together — stage a coordinated content drop (a launch, a new product page, a FAQ refresh) and flip it all at once.
Note: Automatic timed publishing isn’t implemented yet. A release with a
scheduled_atdate entersscheduledstatus but must be published manually. Auto-publishing at the scheduled time is coming soon.
Common patterns (let the AI wire it up)
Section titled “Common patterns (let the AI wire it up)”You rarely write this by hand — describe what you want and Proyecta builds it against real collections:
"Build a blog. Each post has a title, cover image, rich-text body, category, and tags. Public routes at /blog and /blog/[slug], newest first.""Add an FAQ section the owner can edit, grouped by category.""Add a bookable services list with a request-a-quote form.""Make the site bilingual — English and Spanish — with a language switcher.""Seed the testimonials with five realistic reviews for a coffee shop."
Where your app’s data lives
Section titled “Where your app’s data lives”CMS is the default home for durable content and records. A few kinds of data live in purpose-built systems instead:
| Kind of data | Where it lives |
|---|---|
| Content & records (posts, services, listings, FAQs, catalog, bookings) | Proyecta CMS (this page) — the default |
| Realtime / behavior state (live chat, feeds, presence, game state) | Realtime store — coming soon |
| User accounts & sign-in | Auth |
| Products, orders, subscriptions, payments | Commerce |
| Uploaded files & media | Files & Media |
| Static assets baked into the build | the public/ directory in your project |
The CMS is the default. A realtime store for genuinely realtime behavior is coming soon; even then, durable content and the commerce catalog will still live in the CMS.
Coming soon
Section titled “Coming soon”- In-builder content editor — browse and edit your CMS collections directly from the builder dashboard (today: manage content via the admin panel or the AI).
- Rich-text WYSIWYG editor — visual editing for
markdownfields (today they’re edited as markdown). - Timed auto-publish — releases that go live automatically at their scheduled time.
- Live preview of content changes against your app.
- Content roles — separate editor permissions from developer permissions.