Skip to content

Commit b547e8f

Browse files
docs: community addon (#1018)
Co-authored-by: jycouet <jycouet@gmail.com>
1 parent 5efb942 commit b547e8f

File tree

6 files changed

+254
-249
lines changed

6 files changed

+254
-249
lines changed

documentation/docs/20-commands/20-sv-add.md

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -71,49 +71,20 @@ Prevents installing dependencies
7171
> [!NOTE]
7272
> Svelte maintainers have not reviewed community add-ons for malicious code!
7373
74-
You can find [community add-ons on npm](https://www.npmx.dev/search?q=keyword:sv-add) by searching for keyword: `sv-add`.
75-
76-
### How to install a community add-on
77-
78-
```sh
79-
npx sv add [PROTOCOL][COMMUNITY_ADDON]
80-
```
81-
82-
You can:
83-
84-
- mix and match official and community add-ons
85-
- use the interactive prompt or give args to the cli
86-
- use the `--add` option in the `create` command
87-
88-
```sh
89-
npx sv add eslint "@supacool"
90-
```
74+
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`.
9175

9276
```sh
93-
npx sv create --add eslint "@supacool"
94-
```
95-
96-
### Package Protocols
97-
98-
```sh
99-
# Scoped package: @org (preferred), we will look for @org/sv
100-
npx sv add "@supacool"
101-
102-
# Regular npm package (with or without scope)
103-
npx sv add my-cool-addon
77+
# Install a community add-on by org
78+
npx sv add @supacool
10479

105-
# Local add-on
80+
# Use a local add-on (for development or custom/private add-ons)
10681
npx sv add file:../path/to/my-addon
107-
```
108-
109-
### How to create a community add-on
11082

111-
To start on a good track, create your add-on with the `addon` template.
83+
# Mix and match official and community add-ons
84+
npx sv add eslint @supacool
11285

113-
```sh
114-
npx sv create --template addon [path]
86+
# Also works when creating a new project directly
87+
npx sv create --add eslint @supacool
11588
```
11689

117-
In your new add-on directory, check out the `README.md` and `CONTRIBUTING.md` to get started.
118-
119-
Then you can continue with the [API docs](/docs/cli/add-on) to start building your add-on. You can also have a look at the [official addons source code](https://github.com/sveltejs/cli/tree/main/packages/sv/src/addons) to get some inspiration on what can be done.
90+
Want to create your own? Check the [Add-on Docs](community).
File renamed without changes.
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
---
2+
title: [create your own]
3+
---
4+
5+
> [!NOTE]
6+
> Community add-ons are currently **experimental**. The API may change. Don't use them in production yet!
7+
8+
This guide covers how to create, test, and publish community add-ons for `sv`.
9+
10+
## Quick start
11+
12+
The easiest way to create an add-on is using the `addon` template:
13+
14+
```sh
15+
npx sv create --template addon [path]
16+
```
17+
18+
The project has a `README.md` and `CONTRIBUTING.md` to guide you along.
19+
20+
## Project structure
21+
22+
Typically, an add-on looks like this:
23+
24+
```js
25+
// @noErrors
26+
import { transforms } from '@sveltejs/sv-utils';
27+
import { defineAddon, defineAddonOptions } from 'sv';
28+
29+
// your add-on definition, the entry point
30+
export default defineAddon({
31+
id: 'your-addon-name',
32+
33+
// optional: one-liner shown in prompts
34+
shortDescription: 'does X',
35+
36+
// optional: link to docs/repo
37+
homepage: 'https://...',
38+
39+
// Define options for user prompts (or passed as arguments)
40+
options: defineAddonOptions()
41+
.add('who', {
42+
question: 'To whom should the addon say hello?',
43+
type: 'string' // boolean | number | select | multiselect
44+
})
45+
.build(),
46+
47+
// preparing step, check requirements and dependencies
48+
setup: ({ dependsOn }) => {
49+
dependsOn('tailwindcss');
50+
},
51+
52+
// actual execution of the addon
53+
run: ({ isKit, cancel, sv, options, directory }) => {
54+
if (!isKit) return cancel('SvelteKit is required');
55+
56+
// Add "Hello [who]!" to the root page
57+
sv.file(
58+
directory.kitRoutes + '/+page.svelte',
59+
transforms.svelte(({ ast, svelte }) => {
60+
svelte.addFragment(ast, `<p>Hello ${options.who}!</p>`);
61+
})
62+
);
63+
}
64+
});
65+
```
66+
67+
> `sv` is responsible for the file system - `sv.file()` accepts a `path` to the file and a callback function to modify it.
68+
> `@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.
69+
70+
## Development
71+
72+
You can run your add-on locally using the `file:` protocol:
73+
74+
```sh
75+
cd /path/to/test-project
76+
npx sv add file:../path/to/my-addon
77+
```
78+
79+
This allows you to iterate quickly without publishing to npm.
80+
81+
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.
82+
83+
> [!NOTE]
84+
> It is not necessary to build your add-on during development.
85+
86+
## Testing
87+
88+
The `sv/testing` module provides utilities for testing your add-on:
89+
90+
```js
91+
import { setupTest } from 'sv/testing';
92+
import { test, expect } from 'vitest';
93+
import addon from './index.js';
94+
95+
test('adds hello message', async () => {
96+
const { content } = await setupTest({
97+
addon,
98+
options: { who: 'World' },
99+
files: {
100+
'src/routes/+page.svelte': '<h1>Welcome</h1>'
101+
}
102+
});
103+
104+
expect(content('src/routes/+page.svelte')).toContain('Hello World!');
105+
});
106+
```
107+
108+
## Publishing
109+
110+
### Bundling
111+
112+
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.)
113+
114+
### `package.json`
115+
116+
Your add-on must have `sv` as a peer dependency and **no** `dependencies` in `package.json`:
117+
118+
```jsonc
119+
{
120+
"name": "@your-org/sv",
121+
"version": "1.0.0",
122+
"type": "module",
123+
// entrypoint during development
124+
"exports": {
125+
".": "./src/index.js"
126+
},
127+
"publishConfig": {
128+
"access": "public",
129+
// entrypoint on build
130+
"exports": {
131+
".": { "default": "./dist/index.js" }
132+
}
133+
},
134+
// cannot have dependencies
135+
"dependencies": {},
136+
"peerDependencies": {
137+
// minimum version required to run by this addon
138+
"sv": "^0.13.0"
139+
},
140+
// Add this keyword so users can discover your add-on
141+
"keywords": ["sv-add"]
142+
}
143+
```
144+
145+
### Naming convention
146+
147+
Name your package `@your-org/sv`. Users install it by typing just the org:
148+
149+
```sh
150+
# npm package: @your-org/sv
151+
npx sv add @your-org
152+
```
153+
154+
> [!NOTE]
155+
> Unscoped packages are not supported yet
156+
157+
### Export options
158+
159+
`sv` first tries to import `your-package/sv`, then falls back to the default export. This means you have two options:
160+
161+
1. **Default export** (recommended for dedicated add-on packages):
162+
163+
```json
164+
{
165+
"exports": {
166+
".": "./src/index.js"
167+
}
168+
}
169+
```
170+
171+
2. **`./sv` export** (for packages that also export other functionality):
172+
```json
173+
{
174+
"exports": {
175+
".": "./src/main.js",
176+
"./sv": "./src/addon.js"
177+
}
178+
}
179+
```
180+
181+
### Publish to npm
182+
183+
```sh
184+
npm login
185+
npm publish
186+
```
187+
188+
> `prepublishOnly` automatically runs the build before publishing.
189+
190+
## Next steps
191+
192+
You can optionally display guidance in the console after your add-on runs:
193+
194+
```js
195+
// @noErrors
196+
import { color } from '@sveltejs/sv-utils';
197+
198+
export default defineAddon({
199+
// ...
200+
nextSteps: ({ options }) => [
201+
`Run ${color.command('npm run dev')} to start developing`,
202+
`Check out the docs at https://...`
203+
]
204+
});
205+
```
206+
207+
## Version compatibility
208+
209+
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.
210+
211+
## Examples
212+
213+
See the [official add-on source code](https://github.com/sveltejs/cli/tree/main/packages/sv/src/addons) for some real world examples.
214+
215+
## Architecture
216+
217+
The Svelte CLI is split into two packages with a clear boundary:
218+
219+
- **`sv`** = **where and when** to do it. It owns paths, workspace detection, dependency tracking, and file I/O. The engine orchestrates add-on execution.
220+
- **`@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.
221+
222+
This separation means transforms are testable without a workspace and composable across add-ons.

0 commit comments

Comments
 (0)