#content collection directory location
26 messages · Page 1 of 1 (latest)
Hi @hexed sphinx. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
-
With the new Content Layer API (Astro v5), collections can live anywhere in your project; you define them in src/content.config.ts and point a loader (e.g., glob or file) at their location. They are not required to be under src/content/. Also, collections with a loader are forbidden in src/content/ when legacy mode is enabled (Content collections guide and Built-in loaders; Legacy flags).
-
Legacy collections (v2–v4, type: 'content' or 'data') must be in src/content/. If you enable legacy.collections: true, those legacy collections continue to work only in src/content/ (Upgrade to v5 – Legacy; Legacy flags).
-
Starlight specifically expects docs and i18n content under src/content/docs/ and src/content/i18n/ via its loaders (Starlight project structure; Configure content collections).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@hexed sphinx Kapa.ai is still learning and improving, please let me know how I did by reacting below.
how would i define a loader and schema for
export interface Service {
id: string;
title: string;
description: string;
duration: number;
price: number;
category: string;
type?: string;
isOnline?: boolean;
isInPerson?: boolean;
image?: string;
}
in a services.json file like
[
{
"id": "service-1",
"title": "Initial Ayurvedic Consultation",
"description": "A comprehensive assessment of your constitution (prakruti), current imbalances (vikruti), and personalized wellness recommendations.",
"duration": 90,
"price": 150,
"isOnline": true,
"isInPerson": false,
"type": "ayurvedic",
"image": "https://images.unsplash.com/photo-1649972904349-6e44c42644a7"
},
{
"id": "service-2",
"title": "Follow-up Consultation",
"description": "Review your progress, address questions, and adjust recommendations as needed for your ongoing wellness journey.",
"duration": 45,
"price": 75,
"isOnline": true,
"isInPerson": false,
"type": "ayurvedic"
},
{
"id": "service-3",
"title": "Private Yoga Consultation",
"description": "Personalized therapeutic yoga practice designed specifically for your health concerns and wellness goals.",
"duration": 75,
"price": 130,
"isOnline": true,
"isInPerson": false,
"type": "yoga",
"image": "https://images.unsplash.com/photo-1518495973542-4542c06a5843"
},
{
"id": "service-5",
"title": "Marma Therapy Session",
"description": "Gentle pressure applied to specific vital energy points to release blockages and restore the flow of prana throughout the body.",
"duration": 60,
"price": 120,
"isOnline": false,
"isInPerson": true,
"type": "marma",
"image": "https://images.unsplash.com/photo-1721322800607-8c38375eef04"
}
]
@slow ruin how would i define a loader and schema for
export interface Service {
id: string;
title: string;
description: string;
duration: number;
price: number;
category: string;
type?: string;
isOnline?: boolean;
isInPerson?: boolean;
image?: string;
}
in a services.json file like
[
{
"id": "service-1",
"title": "Initial Ayurvedic Consultation",
"description": "A comprehensive assessment of your constitution (prakruti), current imbalances (vikruti), and personalized wellness recommendations.",
"duration": 90,
"price": 150,
"isOnline": true,
"isInPerson": false,
"type": "ayurvedic",
"image": "https://images.unsplash.com/photo-1649972904349-6e44c42644a7"
},
{
"id": "service-2",
"title": "Follow-up Consultation",
"description": "Review your progress, address questions, and adjust recommendations as needed for your ongoing wellness journey.",
"duration": 45,
"price": 75,
"isOnline": true,
"isInPerson": false,
"type": "ayurvedic"
},
{
"id": "service-3",
"title": "Private Yoga Consultation",
"description": "Personalized therapeutic yoga practice designed specifically for your health concerns and wellness goals.",
"duration": 75,
"price": 130,
"isOnline": true,
"isInPerson": false,
"type": "yoga",
"image": "https://images.unsplash.com/photo-1518495973542-4542c06a5843"
},
{
"id": "service-5",
"title": "Marma Therapy Session",
"description": "Gentle pressure applied to specific vital energy points to release blockages and restore the flow of prana throughout the body.",
"duration": 60,
"price": 120,
"isOnline": false,
"isInPerson": true,
"type": "marma",
"image": "https://images.unsplash.com/photo-1721322800607-8c38375eef04"
}
]
Let me check the knowledge base for you again. One moment! :books:
You can use the Content Layer API with the built-in file() loader and a Zod schema. Create src/content.config.ts:
import { defineCollection, z } from 'astro:content';
import { file } from 'astro/loaders';
const services = defineCollection({
loader: file('src/data/services.json'),
schema: z.object({
id: z.string(),
title: z.string(),
description: z.string(),
duration: z.number(),
price: z.number(),
category: z.string().optional(), // not present in your JSON; make optional if not used
type: z.string().optional(),
isOnline: z.boolean().optional(),
isInPerson: z.boolean().optional(),
image: z.string().url().optional(),
}),
});
export const collections = { services };
Notes:
- file() loads a single JSON/YAML/TOML file that contains an array of objects with unique id fields; no custom parser is needed for your example (file() loader, parser function).
- Schemas are defined with Zod via astro:content and validate/typify your entries when querying (Defining the collection schema, Imports from astro:content).
- Define collections in src/content.config.ts and export collections to register them (Defining Collections).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@hexed sphinx Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@slow ruin i want the services.json to be pulled from the /content directory outside of /src so it's not exposed to the client?
Let me check the knowledge base for you again. One moment! :books:
Yes. With Astro’s Content Layer API, you can load data from anywhere in your project, not just under src. Point the loader to your external path (e.g., ./content/services.json), and it won’t be bundled for the client—only the validated data you query is used at build time.
Example src/content.config.ts:
import { defineCollection, z } from 'astro:content';
import { file } from 'astro/loaders';
const services = defineCollection({
loader: file('./content/services.json'),
schema: z.object({
id: z.string(),
title: z.string(),
description: z.string(),
duration: z.number(),
price: z.number(),
category: z.string().optional(),
type: z.string().optional(),
isOnline: z.boolean().optional(),
isInPerson: z.boolean().optional(),
image: z.string().url().optional(),
}),
});
export const collections = { services };
- file() supports JSON and creates entries from a single file with unique id fields; no custom parser needed (file() loader, parser function).
- Collections are defined in src/content.config.ts, and loaders can target files anywhere on the filesystem (Defining Collections, Built-in loaders).
- Avoid using astro:content on the client; pass any needed data via props if you hydrate client components (astro:content client restriction).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@hexed sphinx Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@slow ruin great, is the a way to sync corresponding events in Cal.com when new services are pushed into the collection?
const url = 'https://api.cal.com/v2/event-types';
const options = {
method: 'POST',
headers: {
'cal-api-version': '<cal-api-version>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: '{}'
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'PATCH',
headers: {
'cal-api-version': '<cal-api-version>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: '{}'
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'DELETE',
headers: {'cal-api-version': '<cal-api-version>', Authorization: '<authorization>'},
body: undefined
};
const url = 'https://api.cal.com/v2/event-types';
const options = {
method: 'GET',
headers: {'cal-api-version': '<cal-api-version>'},
body: undefined
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'GET',
headers: {'cal-api-version': '<cal-api-version>', Authorization: '<authorization>'},
body: undefined
};
Let me check the knowledge base for you again. One moment! :books:
I’m sorry, but the knowledge sources don’t include any guidance on syncing a content collection with an external API like Cal.com or triggering web requests on collection changes. They describe how to define loaders and schemas, query collections, and use the Content Loader API, but not automations to create/update/delete external records when entries change (Content collections; Defining Collections; Loader types; LoaderContext and DataStore and).
What is documented:
- Content loaders run at build time; collections are updated during builds, not in real time. For live updates you’d use other fetching methods or on-demand rendering, not collections (When not to create a collection).
- You can build a custom loader that pulls data in, but the docs don’t specify pushing changes out to third-party APIs as part of the loader lifecycle (Building a custom loader).
- Deployments for CMS workflows can use webhooks to trigger rebuilds, but this is about rebuilding the site, not syncing to external services (Publishing your site → Rebuild on changes).
Given the docs, there isn’t an official, documented mechanism to push to Cal.com on collection changes. You would need to implement your own build-time or external process.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@hexed sphinx Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@slow ruin great, is the a way to sync corresponding events in Cal.com at build time after new services are pushed into the collection?
const url = 'https://api.cal.com/v2/event-types';
const options = {
method: 'POST',
headers: {
'cal-api-version': '<cal-api-version>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: '{}'
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'PATCH',
headers: {
'cal-api-version': '<cal-api-version>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: '{}'
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'DELETE',
headers: {'cal-api-version': '<cal-api-version>', Authorization: '<authorization>'},
body: undefined
};
const url = 'https://api.cal.com/v2/event-types';
const options = {
method: 'GET',
headers: {'cal-api-version': '<cal-api-version>'},
body: undefined
};
const url = 'https://api.cal.com/v2/event-types/{eventTypeId}';
const options = {
method: 'GET',
headers: {'cal-api-version': '<cal-api-version>', Authorization: '<authorization>'},
body: undefined
};
Let me check the knowledge base for you again. One moment! :books:
I’m sorry, but the knowledge sources don’t document any built-in way to sync content collection changes to an external API (like Cal.com) at build time. The docs cover defining loaders/schemas and running build/development commands, but not pushing changes out to third-party services during the build lifecycle (Content collections; Loader types; astro dev hotkeys; astro sync).
If you want to attempt this, the closest documented extension point is writing an Astro integration that runs a custom hook during the build (e.g., in astro:build:setup) where you could call external APIs, but the docs don’t provide a pattern specifically for syncing collections to external services (Building your own integration; astro:build:setup hook; Hooks overview; Custom hooks).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@hexed sphinx Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@slow ruin what about astro:server:setup which hook is best suited for syncing external objects with local content like services.json? services.json is the source of truth, external services like cal.com need to be updated to follow content defined in services.json
Let me check the knowledge base for you again. One moment! :books:
Short answer: use an Astro integration and run your sync during the build lifecycle, not the dev server hooks.
-
astro:server:setup is for dev-mode server middleware and dev toolbar messaging. It’s called only in astro dev before listen(), and is intended for Vite server customization and content refresh during development, not for production build syncs (e.g., Cal.com) (astro:server:setup). It also provides refreshContent for dev-only content updates (refreshContent() option).
-
For build-time syncing (services.json → Cal.com), prefer a build hook:
- astro:build:start or astro:build:setup to prepare and read your content, then call external APIs (astro:build:setup, Hooks).
- If you need the fully generated output first (rare), astro:build:generated/astro:build:done run after generation; you could still call APIs there, but docs recommend astro:build:done unless you specifically need pre-cleanup access (astro:build:generated).