
Security News
MCP Community Begins Work on Official MCP Metaregistry
The MCP community is launching an official registry to standardize AI tool discovery and let agents dynamically find and install MCP servers.
composably
Advanced tools
Composably is a build-time content processing and integration plugin for Vite and SvelteKit. It enhances the build process by automatically discovering, parsing, validating, and transforming content from files (like Markdown and YAML) into structured data
Composably is a build-time content processing and integration plugin for Vite and SvelteKit. It enhances the build process by automatically discovering, parsing, validating, and transforming content from files (like Markdown and YAML) into structured data readily consumable by Svelte components, ensuring type safety along the way.
The content is analyzed before SvelteKit processes components (or do anything really), this makes it possible to inject virtual components from content, which is useful if you want to use components in your markdown (without making markdown components).
This effectively makes SvelteKit a Static Site Generator much like Astro, Hugo and Jekyll. For those of you who take progressive enhancement seriously: Here's your opportunity to really start from the bottom.
The API is currently a bit unpolished, but the showcase pages and composably.spec.svelte.ts
describe most of the functionality that this plugin provides. Feel free to clone and hack.
Create a new SvelteKit (^2.20.0) project or use an existing, then install composably:
npm install composably
In your vite.config.ts, add composably() and pass a config with the locations for your content and components.
// vite.config.ts
import { composably } from 'composably/vite';
const config = {
componentRoot: 'src/components',
contentRoot: 'src/content',
//optional
remarkPlugins: [],
rehypePlugins: []
};
export default defineConfig({
plugins: [composably(config)]
});
The plugin exposes a pre-built virtual module composably:content
with all
content it has discovered under your contentRoot
(e.g. src/lib/content
):
// src/routes/your-ssg-site/[...path]/+page.ts
import content from 'composably:content';
export const load = async ({ params }) => {
return await content(params.path);
};
// src/routes/your-ssg-site/[...path]/+page.svelte
<page.component {...page} />
Create this index.md
directly under contentRoot
:
---
component: Page # This will be replaced by a reference to the Page.svelte component
title: Hello Composably!
---
Welcome to your first **Composable** page!
Write standard Markdown here, it will be available as
`body` along with the frontmatter.
## Features
- The headings are extracted for a TOC
- Components can be inserted in the document using ::slots
- Frontmatter can be interpolated with double braces {{title}}
- Emojis, definition lists, extended tables and more...
Create a component Page.svelte in componentRoot
(e.g. src/lib/components
):
<script module>
import { c } from 'composably/schemas'; // Schema helpers
export const schema = c.content({
title: c.string(), // Expect a string title
body: c.markdown() // Markdown will be automatically processed
});
</script>
<script>
// Props are validated against the schema above!
// Note: 'body' includes processed content AND metadata like headings
let { title, body } = $props();
</script>
<h1>{title}</h1>
{#if body.headings && body.headings.length > 0}
<nav>
<strong>On this page:</strong>
<ul>
{#each body.headings as heading}
<li><a href="#{heading.id}">{heading.text}</a></li>
{/each}
</ul>
</nav>
{/if}
<body.component {...body} />
Load in src/routes/+page.ts
:
import content from 'composably:content';
export const load = async ({ params }) => {
return await content(params.path);
};
Render in src/routes/+page.svelte
:
<script>
let { page } = $props();
</script>
<page.component {...page} />
Boom! Validated, pre-loaded content from markdown.
content/features.yaml
:
component: FeatureList
title: Awesome Features
features:
- name: Type-Safe Content
description: Catch errors at build time, not runtime!
- name: Component-Driven
description: Map content directly to Svelte components.
- name: Flexible Formats
description: Use Markdown OR YAML based on your needs.
Create src/components/FeatureList.svelte
:
<script module>
import { c } from 'composably/schemas';
export const schema = c.content({
title: c.string(),
features: c.array(c.object({
name: c.string(),
description: c.string()
}))
});
</script>
<script>
let { title, features } = $props();
</script>
<h2>{title}</h2>
<ul>
{#each features as feature, key (key)}
<li><strong>{feature.name}:</strong> {feature.description}</li>
{/each}
</ul>
Load it: const features = await content('features')
;
Define common content once, reuse everywhere.
Create content/_author-jane.yaml
(leading _ ignored in route discovery):
component: AuthorBio
name: Jane Doe
bio: Expert writer exploring Composably.
Create src/components/AuthorBio.svelte
:
<script module>
import { c } from 'composably/schemas';
export const schema = c.content({ name: c.string(), bio: c.string() });
</script>
<script> let { name, bio } = $props(); </script>
<span><strong>{name}</strong> ({bio})</span>
Reference it in content/blog/my-post.md
:
---
component: BlogPost
title: My Awesome Post
author: _author-jane.yaml # <-- Reference the fragment!
---
Blog content here...
src/components/BlogPost.svelte
schema expects it:
<script module>
import { c } from 'composably/schemas';
export const schema = c.content({
title: c.string(),
// Validate the linked fragment data against AuthorBio's schema!
author: c.component(['AuthorBio']),
body: c.markdown()
});
</script>
<script>
let { title, author, body } = $props();
</script>
<article>
<h1>{title}</h1>
<p>By <author.component {...author} /></p>
<body.component {...body} />
</article>
Need a carousel or alert inside your Markdown flow? Use slots!
Define slot data in content/another-post.md:
---
component: Page
title: Embedding with Slots
slots:
carousel: # Slot name
component: Swiper # Component for the slot
slides: # Props for the Swiper component
- image: /img1.jpg
- image: /img2.jpg
---
Here is some introductory text.
Now, right here, I want my image carousel:
::carousel
And the text continues after the embedded component. How cool is that?
Ensure src/components/Page.svelte
schema includes slots:
// <script module> in Page.svelte
import { c } from 'composably/schemas';
export const schema = c.content({
title: c.string(),
body: c.markdown(), // Processes ::carousel using 'slots' data
slots: c.slots()
});
// ... rest of Page.svelte ...
Create src/components/Swiper.svelte
with its schema (slides: c.array(...)). Composably's c.markdown
processor magically replaces ::carousel
with the rendered Swiper component!
Composably's markdown parser comes with the following features out-of-the-box:
⚠️ Early Alpha - Use with Caution! ⚠️
This package is currently in the early alpha stage of development. While functional for its core purpose, APIs might change, bugs are likely present, and it has not yet been battle-tested in diverse production environments. Please do not rely on this for critical applications yet.
Testers and contributors are warmly welcome! Your feedback, bug reports, and code contributions are highly valuable at this stage.
Follow these steps to set up the project locally for development or testing:
Clone the repository:
git clone https://github.com/kompismoln/composably
cd composably
Install dependencies:
# Using npm
npm install
# Or using pnpm
# pnpm install
# Or using yarn
# yarn install
Start the development server:
💡 Set
DEBUG=composably*
for verbose logging duringnpm run dev
,npm run test
, ornpm run build
.
This runs the example site included in the repository, using the local version of the plugin.
npm run dev
Run tests:
npm run test # Runs unit tests once
npm run test:unit # Runs unit tests in watch mode
Check code quality: Ensure your changes meet the project's standards before committing.
npm run format # Formats code using Prettier
npm run lint # Lints code using ESLint
npm run check # Runs svelte-check for type checking
Build the package:
This compiles the plugin code into the /dist
directory.
npm run build
If you use Nix, you can enter a reproducible development shell with all required dependencies activated:
nix develop
FAQs
Composably is a build-time content processing and integration plugin for Vite and SvelteKit. It enhances the build process by automatically discovering, parsing, validating, and transforming content from files (like Markdown and YAML) into structured data
The npm package composably receives a total of 328 weekly downloads. As such, composably popularity was classified as not popular.
We found that composably demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The MCP community is launching an official registry to standardize AI tool discovery and let agents dynamically find and install MCP servers.
Research
Security News
Socket uncovers an npm Trojan stealing crypto wallets and BullX credentials via obfuscated code and Telegram exfiltration.
Research
Security News
Malicious npm packages posing as developer tools target macOS Cursor IDE users, stealing credentials and modifying files to gain persistent backdoor access.