Svelte CLI add-ons are built using two primary packages that maintain a strict boundary of concerns:
sv: The orchestration engine. It handles where and when actions occur. It manages file paths, workspace detection, dependency tracking, and file I/O.@sveltejs/sv-utils: The content toolkit. It handles what is done to content. It provides pure parsers, language tooling, and typed transforms. It has no knowledge of the file system or the workspace, making transforms highly testable and composable.
An add-on is defined using defineAddon and typically implements options, setup, run, and nextSteps hooks.
import { transforms } from '@sveltejs/sv-utils';
import { defineAddon, defineAddonOptions } from 'sv';
export default defineAddon({
id: 'addon-name',
shortDescription: 'a better description of what your addon does ;)',
options: defineAddonOptions()
.add('who', {
question: 'To whom should the addon say hello?',
type: 'string' // boolean | number | select | multiselect
})
.build(),
setup: ({ dependsOn, isKit, unsupported, addOption }) => {
if (!isKit) unsupported('Requires SvelteKit');
dependsOn('vitest');
// addOption('key', { question: '...', type: 'boolean', default: true });
},
run: ({ isKit, cancel, sv, options, file, language, directory }) => {
sv.file(
directory.kitRoutes + '/+page.svelte',
transforms.svelte(({ ast, svelte }) => {
svelte.addFragment(ast, `<p>Hello ${options.who}!</p>`);
})
);
},
nextSteps: ({ options }) => ['enjoy the add-on!']
});