Getting Started
Creating a new project
SvelTeX is distributed as a community add-on for the official Svelte CLI (sv). To start from scratch, first scaffold a SvelteKit project:
pnpm dlx sv createbunx sv createnpx sv createyarn dlx sv create...then add SvelTeX to it, as described in the next section.
create-sveltex is deprecatedEarlier versions of SvelTeX shipped a create-sveltex scaffolding package. It has been superseded by the sv add-on below; the create-sveltex binary now only prints a notice pointing here.
Adding to an existing project
Using the sv add-on
The quickest way to add SvelTeX to an existing SvelteKit project is the sv add-on. It installs SvelTeX and the peer dependencies for the backends you pick, creates a sveltex.config.js, and wires the preprocessor into your svelte.config.js:
pnpm dlx sv add @nvl/sv-sveltexbunx sv add @nvl/sv-sveltexnpx sv add @nvl/sv-sveltexyarn dlx sv add @nvl/sv-sveltex...and follow the prompts.
Prefer to set things up by hand? The rest of this page walks through the manual installation and configuration.
Installation
To install SvelTeX, run the following command in your project's root directory (wherever your package.json is located):
pnpm add -D @nvl/sveltexbun add -D @nvl/sveltexnpm add -D @nvl/sveltexyarn add -D @nvl/sveltexSvelTeX doesn't bundle the markdown, code, or math backends — you install the ones you've chosen as peer dependencies. For example, the unified markdown backend needs the unified, remark-parse, remark-rehype, and rehype-stringify packages, the shiki code backend needs shiki, and so on. SvelTeX will tell you exactly which packages are missing the first time you run a build.
If you pick mathjax as your math backend, you need the @mathjax/src package at version 4 or later:
pnpm add -D @mathjax/srcMathJax v4 ships each math font as a separate npm package, but @mathjax/src already declares @mathjax/mathjax-newcm-font as a dependency — so the default font is pulled in automatically. If you override math.font, also install the matching @mathjax/mathjax-<font>-font package — e.g. for fira:
pnpm add -D @mathjax/mathjax-fira-fontdevDependencies is the right scope for both: the CHTML output's font files are served from a CDN at runtime by default (via MathJax's fontURL), and the SVG output bakes glyph paths into the rendered HTML at build time. Either way, the npm packages themselves only need to be present while SvelTeX runs.
See the Math page for details.
Setup
SvelTeX has one main export, sveltex. This is an asynchronous function that takes two arguments:
Backend specification: An object with the following (optional) properties:
markdownBackend: The markdown processor to use.codeBackend: The syntax highlighter to use.mathBackend: The math renderer to use. This is different from the full-fledged TeX to SVG pipeline, and intended for simpler math expressions (i.e., expressions that can be rendered with MathJax or KaTeX).
Configuration object: An object with the following (optional) properties:
extensions: An array of file extensions to process. Defaults to['.sveltex'].code: Configuration options for the code backend.markdown: Configuration options for the markdown backend.math: Configuration options for the math backend.tex: Configuration options for the TeX to SVG pipeline.verbatim: Map of verbatim environments to their respective configuration options.frontmatter: Which of SvelTeX's frontmatter-processing steps (head injection,metadataexport,importstatements) to perform. Passfalseto disable frontmatter handling entirely, or an object to toggle individual steps.
In turn, it returns a promise which resolves to a Svelte preprocessor.
Splitting the backend choices from the configuration is what makes the config type-aware. The backends you pick in the first argument set the generic types that drive IntelliSense for the second argument, so your editor offers exactly the options each chosen backend supports — and flags the ones it doesn't. Merging everything into one object would throw that inference away.
For example:
// sveltex.config.js
import { sveltex } from '@nvl/sveltex';
export default await sveltex({
markdownBackend: 'unified',
codeBackend: 'shiki',
mathBackend: 'mathjax'
}, {
code: { shiki: { theme: 'github-dark' } },
verbatim: { Tex: { type: 'tex', aliases: ['TeX'] } }
})You can then use this export in your svelte.config.js:
// svelte.config.js
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
import sveltexPreprocessor from './sveltex.config.js';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// ...
preprocess: [
vitePreprocess(), // (optional)
sveltexPreprocessor,
// ...
],
extensions: ['.svelte', '.sveltex'],
// ...
};
export default config;If you prefer, you can also just use the sveltex function directly in your svelte.config.js. Just remember to await it.
Troubleshooting
A few common first-run snags:
The preprocessor seems to do nothing, or Svelte errors that it isn't a valid preprocessor.
sveltex(...)is async — it returns a promise that resolves to the preprocessor, not the preprocessor itself.awaitit (top-levelawaitworks in bothsveltex.config.jsandsvelte.config.js):jsexport default await sveltex(/* … */); // ✅ awaitedBackend options appear to be ignored, or TypeScript complains about the configuration.
sveltextakes two arguments — the backend choices first, then the configuration — not a single merged object:js// ✅ two arguments await sveltex( { markdownBackend: 'unified', codeBackend: 'shiki' }, { code: { shiki: { theme: 'github-dark' } } }, ); // ❌ one object — the backend options silently won't apply await sveltex({ markdownBackend: 'unified', code: { shiki: { theme: 'github-dark' } }, });The split is deliberate — it's what makes the configuration fully typed for your chosen backends (see Setup above).
A peer dependency is missing. SvelTeX names the exact packages it needs for the backends you picked on the first build — install those and re-run.
.sveltexfiles aren't being processed. Check thatextensionsinsvelte.config.jsincludes'.sveltex'and that the preprocessor is actually in thepreprocessarray.