Content, Search & Events (content.ts)
Reference for global content operations — versioning, structure management, global search, query-param filtering, real-time events, and GraphQL.
On this page
The Content API manages the structural and cross-collection aspects of SveltyCMS. It handles content versioning, global search, real-time event streams (SSE), and serves as the gateway for the GraphQL API.
⚡ Quick Reference
| Feature | HTTP Endpoint | Method | Permission Required |
|---|---|---|---|
| Get Version | /api/content/version |
GET |
Public |
| Get Structure | /api/content-structure |
GET |
collection:read |
| Global Search | /api/search |
GET |
collection:read |
| SSE Events | /api/content/events |
GET |
collection:read |
| SSE (alias) | /api/events |
GET |
collection:read |
| GraphQL API | /api/graphql |
POST |
manage:system |
1. Structure & Versioning
Content Versioning
SveltyCMS maintains a global version counter that increments on every structural or content change. Use this to trigger cache invalidation in external apps.
Endpoint: GET /api/content/version
Content Structure
Retrieve or modify the tree-like structure of your collections and folders.
- GET: Returns the full hierarchy of content nodes.
- POST: Used for reordering nodes (action:
reorderContentStructure) or force-refreshing the collection registry (action:refresh).
2. Global Search
Search across multiple collections simultaneously using the unified search engine.
Endpoint: GET /api/search?q=query_text
Parameters:
type: Comma-separated list of collections (default: all).status: filter by status (default:published).page/limit: Standard pagination.
2b. Collection List Query Params (SSR + entry-list)
Per-collection view mode lists are driven by URL query parameters on the admin collection route
(/(app)/[language]/[...collection]). The page loader parses params, whitelists field names
against the collection schema, then loads via CollectionService (L1/L2 SWR).
| Param | Purpose | Client source |
|---|---|---|
search |
In-collection full-text search (searchable schema fields + system ids) | TableFilter / globalSearchValue |
page / pageSize |
Pagination | TablePagination |
sort / order |
Sort field + asc | desc |
Header click |
filter_{fieldName} |
Per-column filter value | createSmartFilter / SmartFilterRow |
edit |
Entry id for edit-mode load (full multilingual row) | Mode / URL |
Parsing & security
// +page.server.ts
import { parseCollectionListQuery } from "@utils/collection-query-filters";
const listQuery = parseCollectionListQuery(url.searchParams, currentCollection);
// listQuery.filter → only schema-allowed keys (whitelist)
// listQuery.queryHash → stable hash for cache keys
await collectionService.getCollectionData({
collection: currentCollection,
page: listQuery.page,
pageSize: listQuery.pageSize,
sort: listQuery.sort,
filter: listQuery.filter, // { field: { contains: "value" } }
search: listQuery.search,
// ...
});
| Rule | Detail |
|---|---|
| Never trust client field names | whitelistFilterParams drops unknown keys before the DB layer |
| Operator shape | Adapter-agnostic { contains: string } today; range ops can extend without changing URL prefixes |
| Tenant isolation | CollectionService injects tenantId into the final filter when multi-tenant is enabled |
| Cache | Keys include query:{hash} so each filter/search combination is a distinct L1/L2 entry; mutations call invalidateCollection(id) |
Global search vs column filters
| Mode | Scope | Param | Backend |
|---|---|---|---|
| Global search (cross-collection) | Many collections | GET /api/search?q= |
Unified search engine |
| In-collection search | One collection list | ?search= |
QueryBuilder .search() on schema fields |
| Column filters | One field | ?filter_{name}= |
QueryBuilder .where({ field: { contains } }) |
UI: entry-list · Platform: collection-filtering · Cache: cache-system
3. Real-Time Events (SSE)
SveltyCMS broadcasts structural content changes using Server-Sent Events (SSE). Authenticated admin sessions connect to receive normalized update payloads; the CMS admin UI uses this to refresh the content tree without a full page reload.
Primary endpoint: GET /api/content/events
Alias: GET /api/events
Permission: collection:read (session cookie required)
Wire format
Internal eventBus events (e.g. content:update) are normalized before streaming:
{
"type": "content_update",
"event": "content:update",
"version": 1718457600000,
"tenantId": "all",
"timestamp": 1718457600123
}
Tenant-scoped subscribers only receive events where tenantId matches their context, or where tenantId is "all" (broadcast).
Client integration
The built-in admin client (content-sse.svelte.ts) listens for type: "content_update" and calls contentSystem.refresh(), which fetches the latest structure from GET /api/content-structure?action=getStructure and syncs the reactive store.
const events = new EventSource("/api/content/events", { withCredentials: true });
events.onmessage = (e) => {
const data = JSON.parse(e.data);
if (data.type === "content_update") {
// Refetch structure or invalidate SvelteKit loaders
console.log(`Content tree changed (v${data.version})`);
}
};
4. GraphQL API
While GraphQL is the primary mechanism for structured querying, we have separated its reference into its own dedicated documentation page.
For comprehensive details on schema definitions, mutations, queries, and subscriptions, please see:
Related Documents
- Collections Reference (collections.ts)
- entry-list / createSmartFilter
- Cache System (L1/L2, SWR, prefix invalidation)
- Data Operations — content import/sync must invalidate collection caches
- Media Management (media.ts)
- System Reference (system.ts)