@markup-carve/webpack-loader
August 21, 2026 ยท View on GitHub
A webpack 5 loader for importing Carve markup as build-time-rendered HTML. It is also the supported bridge for Next.js projects that use webpack.
Install
npm install @markup-carve/webpack-loader
Webpack
export default {
module: {
rules: [
{ test: /\.crv$/, use: ['@markup-carve/webpack-loader'] },
],
},
}
import html, { source, frontmatter } from './document.crv'
The default export and named html export contain rendered HTML. source
contains the original document and frontmatter contains Carve's raw
{format, content} metadata object (or null). Rendering happens during the
build; the Carve engine is not sent to the browser.
Options are passed under carveOptions:
{ test: /\.crv$/, use: [{
loader: '@markup-carve/webpack-loader',
options: { carveOptions: { allowRawHtml: false } },
}] }
Next.js
Add the same rule in next.config.mjs:
export default {
webpack(config) {
config.module.rules.push({
test: /\.crv$/,
use: ['@markup-carve/webpack-loader'],
})
return config
},
}
Then render an import from a Server Component:
import html from './welcome.crv'
export default function Page() {
return <article dangerouslySetInnerHTML={{__html: html}} />
}
Next.js 16 uses Turbopack by default. Run next dev --webpack and
next build --webpack with this configuration. Turbopack accepts a subset of
webpack loaders, but this package only claims the webpack path until its ESM
dependency loading has been verified in Turbopack itself.
Because rendering produces HTML, use Carve's allowRawHtml: false option when
authors are not trusted. React's dangerouslySetInnerHTML does not sanitize.
TypeScript
declare module '*.crv' {
export const source: string
export const html: string
export const frontmatter: {format: string; content: string} | null
const value: string
export default value
}
License
MIT