Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions documentation/docs/20-commands/20-sv-add.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,3 @@ Prevents installing dependencies
- [`tailwindcss`](tailwind)
- [`vitest`](vitest)

## Community add-ons

> [!NOTE]
> Community add-ons are currently **experimental**. The API may change. Don't use them in production yet!

> [!NOTE]
> Svelte maintainers have not reviewed community add-ons for malicious code!

Community add-ons are npm packages published by the community. Look out for add-ons from your favorite libraries and tools. _(soon)_ many are building `sv` add-ons to make integration a one-liner. You can find them [on npm](https://www.npmx.dev/search?q=keyword:sv-add) by searching for keyword: `sv-add`.

```sh
# Install a community add-on by org
npx sv add @supacool

# Use a local add-on (for development or custom/private add-ons)
npx sv add file:../path/to/my-addon

# Mix and match official and community add-ons
npx sv add eslint @supacool

# Also works when creating a new project directly
npx sv create --add eslint @supacool
```

Want to create your own? Check the [Add-on Docs](community).
216 changes: 0 additions & 216 deletions documentation/docs/30-add-ons/99-community.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,221 +2,5 @@
title: [create your own]
---

> [!NOTE]
> Community add-ons are currently **experimental**. The API may change. Don't use them in production yet!

This guide covers how to create, test, and publish community add-ons for `sv`.

## Quick start

The easiest way to create an add-on is using the `addon` template:

```sh
npx sv create --template addon [path]
```

The project has a `README.md` and `CONTRIBUTING.md` to guide you along.

## Project structure

Typically, an add-on looks like this:

```js
// @noErrors
import { transforms } from '@sveltejs/sv-utils';
import { defineAddon, defineAddonOptions } from 'sv';

// your add-on definition, the entry point
export default defineAddon({
id: 'your-addon-name',

// optional: one-liner shown in prompts
shortDescription: 'does X',

// optional: link to docs/repo
homepage: 'https://...',

// Define options for user prompts (or passed as arguments)
options: defineAddonOptions()
.add('who', {
question: 'To whom should the addon say hello?',
type: 'string' // boolean | number | select | multiselect
})
.build(),

// preparing step, check requirements and dependencies
setup: ({ dependsOn }) => {
dependsOn('tailwindcss');
},

// actual execution of the addon
run: ({ isKit, cancel, sv, options, directory }) => {
if (!isKit) return cancel('SvelteKit is required');

// Add "Hello [who]!" to the root page
sv.file(
directory.kitRoutes + '/+page.svelte',
transforms.svelte(({ ast, svelte }) => {
svelte.addFragment(ast, `<p>Hello ${options.who}!</p>`);
})
);
}
});
```

> `sv` is responsible for the file system - `sv.file()` accepts a `path` to the file and a callback function to modify it.
> `@sveltejs/sv-utils` is responsible for the content - `transforms.svelte()` provides you with the proper AST and utils to modify the file. See [sv-utils](/docs/cli/sv-utils) for the full API.

## Development

You can run your add-on locally using the `file:` protocol:

```sh
cd /path/to/test-project
npx sv add file:../path/to/my-addon
```

This allows you to iterate quickly without publishing to npm.

The `file:` protocol also works for custom or private add-ons that you don't intend to publish - for example, to standardize project setup across your team or organization.

> [!NOTE]
> It is not necessary to build your add-on during development.

## Testing

The `sv/testing` module provides utilities for testing your add-on:

```js
import { setupTest } from 'sv/testing';
import { test, expect } from 'vitest';
import addon from './index.js';

test('adds hello message', async () => {
const { content } = await setupTest({
addon,
options: { who: 'World' },
files: {
'src/routes/+page.svelte': '<h1>Welcome</h1>'
}
});

expect(content('src/routes/+page.svelte')).toContain('Hello World!');
});
```

## Publishing

### Bundling

Community add-ons are bundled with [tsdown](https://tsdown.dev/) into a single file. Everything is bundled except `sv`. (It is a peer dependency provided at runtime.)

### `package.json`

Your add-on must have `sv` as a peer dependency and **no** `dependencies` in `package.json`:

```jsonc
{
"name": "@your-org/sv",
"version": "1.0.0",
"type": "module",
// entrypoint during development
"exports": {
".": "./src/index.js"
},
"publishConfig": {
"access": "public",
// entrypoint on build
"exports": {
".": { "default": "./dist/index.js" }
}
},
// cannot have dependencies
"dependencies": {},
"peerDependencies": {
// minimum version required to run by this addon
"sv": "^0.13.0"
},
// Add this keyword so users can discover your add-on
"keywords": ["sv-add"]
}
```

### Naming convention

Name your package `@your-org/sv`. Users install it by typing just the org:

```sh
# npm package: @your-org/sv
npx sv add @your-org
```

> [!NOTE]
> Unscoped packages are not supported yet

### Export options

`sv` first tries to import `your-package/sv`, then falls back to the default export. This means you have two options:

1. **Default export** (recommended for dedicated add-on packages):

```json
{
"exports": {
".": "./src/index.js"
}
}
```

2. **`./sv` export** (for packages that also export other functionality):
```json
{
"exports": {
".": "./src/main.js",
"./sv": "./src/addon.js"
}
}
```

### Publish to npm

```sh
npm login
npm publish
```

> `prepublishOnly` automatically runs the build before publishing.

## Next steps

You can optionally display guidance in the console after your add-on runs:

```js
// @noErrors
import { color } from '@sveltejs/sv-utils';

export default defineAddon({
// ...
nextSteps: ({ options }) => [
`Run ${color.command('npm run dev')} to start developing`,
`Check out the docs at https://...`
]
});
```

## Version compatibility

Your add-on should specify a minimum `sv` version in `peerDependencies`. Your user will get a compatibility warning if their `sv` version has a different major version than what was specified.

## Examples

See the [official add-on source code](https://github.com/sveltejs/cli/tree/main/packages/sv/src/addons) for some real world examples.

## Architecture

The Svelte CLI is split into two packages with a clear boundary:

- **`sv`** = **where and when** to do it. It owns paths, workspace detection, dependency tracking, and file I/O. The engine orchestrates add-on execution.
- **`@sveltejs/sv-utils`** = **what** to do to content. It provides parsers, language tooling, and typed transforms. Everything here is pure - no file system, no workspace awareness.

This separation means transforms are testable without a workspace and composable across add-ons.
Loading
Loading