-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Content Layer #982
Content Layer #982
Conversation
@ascorbic can we define a schema when fetching data from a remote URL? |
@krishna-santosh yes. You can either define it at the top level (inside the |
Multiple entries per file is great — but how about multiple files per entry? There are many cases where an entry has a The ability to store multiple files part of the same entry would be great! Alternatively, storing other Markdown (Markdoc/MDX) fields in the frontmatter (we do this with Keystatic's Apologies if this is not the right place for this feedback 🤗 |
Let me know if this is the wrong place for this, but I wanted to provide feedback on what I feel would be important for the success of this layer from a CMS perspective: Dependancy Tracking
Function Support
|
@joelvarty yes, we'd love to do dependency tracking at some point. We are in a good place to do that, but it's not in scope for this version. The data is read-only at runtime, and even though it's implemented as files on disk it's loaded as a virtual module, so it's all handled by rollup and works on serverless runtimes. I haven't tested it with Cloudflare yet though, so we'll need to ensure that works. |
@ascorbic It sounds like we would need to do a |
@joelvarty Yes, there's no way to update a deployed site without a build. Locally you can sync by running |
@ascorbic there is no chance of exporting globalContentLayer right? I am generally doing SSG, but am currently using an instance of |
@Suven No (and please don't try: you will break things), but I will be exposing a refresh method in |
I have a proposed addition to the RFC, which I'd welcome feedback on. Integration support for content layerThe is a proposal to add support for syncing the content layer to integrations. It would allow integrations to trigger a sync during dev, optionally of just certain loaders. It would also allow them to pass metadata such as a webhook body to the loader Use cases
APIAdds a async syncContent(options: {
loaders?: Array<string>,
context?: Record<string, any>
})
UsageThis shows an integration that creates a refresh webhook endpoint: export default function() {
return {
name: '@astrojs/my-integration',
hooks: {
'astro:server:setup': async ({ server, refreshContent }) => {
server.middlewares.use('/_refresh', async (req, res) => {
if(req.method !== 'POST') {
res.statusCode = 405
res.end('Method Not Allowed');
return
}
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', async () => {
try {
const webhookBody = JSON.parse(body);
await refreshContent({
// Include the parsed request body. `webhookBody` is an arbitrary name
context: { webhookBody },
// Only refresh a particular loader
loaders: ['my-loader']
});
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Content refreshed successfully' }));
} catch (error) {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Failed to refresh content' }));
}
});
});
}
}
}
} Inside the loader: import { type Loader } from "astro/loaders"
export function myLoader(): Loader {
return {
name: "my-loader",
load: async ({ store, logger, syncContext, meta }) => {
if(syncContext?.webhookBody?.action) {
logger.info("Received incoming webhook")
// do something with the webhook body
}
// this is a normal sync...
}
}
} QuestionsHow should we handle the case where a sync is already in progress? Should it be queued? Should it be skipped? |
Outside of you using |
That proposal sounds great! Regarding your question: I guess triggering a sync while syncing is very likely in CMS-Preview-contexts as the user is continuously making changes. In those I guess the user is only interested in the latest version of his change and this, cancelling the current sync and starting a new one would make sense. |
The virtual module API is a lot of overhead if you're not working with files on a file system. I'm writing a loader for the Notion REST API and it feels weird to make a virtual module per API call. After chatting with folks on the Discord I get the impression virtual modules isn't design for this use case. From an ease-of-loader-implementation perspective a function that can use dynamic imports feels much simpler. I don't know if that makes it harder to optimize the file loader use case. |
This comment has been minimized.
This comment has been minimized.
Maybe I'm doing something wrong, but references don't seem to work with this API. Is this correct? Is this something that will be implemented down the line? Is there any way I can help out? |
This comment has been minimized.
This comment has been minimized.
I'm wondering if the render also works for remote MDX, if not, how can I implement my own loader to correctly render our remote MDX content from APIs |
They should work in the same way as existing collections. If you can't get the working, can you ask in Discord |
@ascorbic what happens if there's a conflict between the schema the loader is providing and the schema the user provides in |
@matthewp the user-defined config will override any loader-defined one |
I've added a section on integration support to the RFC, and have a PR with an implementation. |
Tiny feedback on the Content Layer loader API, not sure if it's on purpose or not in this context: if you throw an |
I've made a few small changes to the RFC, with the only API change being that the type for the data store is now There will be follow-up RFCs for future features, particularly the libSQL backend. |
Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com>
Some user with a lot of content recently asked about it on Discord, if I recall correctly: how about making the loaders generator functions that yield entries, rather than async functions that have to return entire collections? Edit: actually, anything that returns an AsyncIterable would do the trick? |
The comment on the built-in file loader example is:
So, a data structure that may already have some other unique identifier, must also have an
with 3 properties with the same value. |
@hfournier that's an interesting idea. I'm not sure about having it as a second argument, but it is something I'll look at |
This is now included in Astro 5 beta |
Not sure if this is still the right place to give feedback - I've followed a link from docs - as Astro 5 beta recently came out, but I've tried out this API and my page styles were afterwards rendered somehow broken. I have the latest Astro v4 release Does this have something to do with Looking forward for this API. |
@jurajkapsz can you open an issue on the main astro repo please. I'm investigating styles with MDX in content layer at the moment, and it would be helpful if you had a minimal reproduction of the problem |
@ascorbic OK, will do, atm I am doing some tests on my side to better understand what happened and to eventually write a more precise bug report. I've noticed that what visually broke pages after switching to the new Content Layer API render was a different final order of processed CSS styles, which changed style cascade, making eg CSS BEM modifiers unusable. I happen to have certain style definitions in one component and modifying style definition of given component in another component. I'd say it is correct to have it that way, but I give it a second thought; anyhow it worked before, and the final styles where somehow in correct order. |
Summary
Creates a successor to content collections with expanded use cases, including remote data sources and improved performance.
Links