🪧 How to - vite-plugin-kit-routes
KitQL itself is not a library, it’s “nothing” but a collection of standalone libraries.
vite-plugin-kit-routes
automatically updates route references in SvelteKit projects, crucial for
large applications where manual tracking of route changes is error-prone. It simplifies development
by ensuring all route links are consistent and up-to-date, saving time and preventing broken links.
No more 🤞, now be confident ✅!
By default, no Configuration is requiered. Just Install the plugin, and use
objects/functions available in your $lib/ROUTES.ts
generated file (always in sync).
Note that this plugin is meant to be used with typescript today. If you want a JSDoc version of it, please open an issue.
Showcase
Examples
<script lang="ts">
import { route } from '$lib/ROUTES'
</script>
<!-- 🤞 before, hardcoded string, error prone -->
<a href="/terms-and-conditions">Terms</a>
<!-- ✅ after, typechecked route, no more errors -->
<a href={route('/terms-and-conditions')}>Terms</a>
<!--
If you change location of `/terms-and-conditions/+page.svelte`:
- the key '/terms-and-conditions' will not exist
- `route` function will yell!
-->
<script lang="ts">
import { route } from '$lib/ROUTES'
</script>
<!-- 🤞 before, hardcoded string, error prone -->
<a href="/site/123">Go to site</a>
<!-- ✅ after, typechecked route, no more errors -->
<a href={route('/site/[id]', { id: 123 })}>Go to site</a>
<script lang="ts">
import { route } from '$lib/ROUTES'
</script>
<!-- 🤞 before, hardcoded string, error prone -->
<a href="/site/123?limit=3">Go to site</a>
<!-- ✅ after, typechecked route, no more errors -->
<a href={route('/site/[id]', { id: 123, limit: 3 })}>Go to site</a>
<script lang="ts">
import { enhance } from '$app/forms'
import { page } from '$app/stores'
import { route } from '$lib/ROUTES'
const id = $page.params.id
// 🤞 before, hardcoded string, error prone
const action = `/site/${id}?/send`
// ✅ after, typechecked route, no more errors
const action = route('send /site/[id]', { id })
</script>
<form method="POST" use:enhance {action}>
<button>Check</button>
</form>
<script lang="ts">
import { route } from '$lib/ROUTES'
</script>
<!-- 🤞 before, hardcoded string, error prone -->
<a href="https://twitter.com/jycouet">Twitter</a>
<!-- ✅ after, typechecked route, no more errors -->
<a href={route('twitter')}>Twitter</a>
<script lang="ts">
import { route } from '$lib/ROUTES'
</script>
<!-- 🤞 before, hardcoded string, error prone -->
<img src="https://www.gravatar.com/avatar/jycouet?s=20&d=identicon" alt="logo" />
<!-- ✅ after, typechecked route, no more errors -->
<img src={route('gravatar', { str: 'jycouet', s: 20 })} alt="logo" />
* You can add a lot of configs to specify search params, types, …
Installation
npm i -D vite-plugin-kit-routes
Demo
Local
npm create kitql@latest --template kit-routes
Online
Configuration
Add the plugin like this:
import { sveltekit } from '@sveltejs/kit/vite'
import { kitRoutes } from 'vite-plugin-kit-routes'
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
sveltekit(),
// ✅ Add the plugin
kitRoutes()
]
}
export default config
It will generate a file ./src/lib/ROUTES.ts
at the start of your dev server & any update of any of
your +page.svelte
| +server.ts
| +page.server.ts
.
Side Notes
ctrl + space
to discover config options. 🎉- What kind of format you want to use ?
You can choose anyway 😜
kitRoutes({
/**
* // format: `route(path)` -> default <-
* route("/site/[id]", { id: 7, tab: 'info' })
*
* // format: `route(symbol)`
* route("site_id", { id: 7, tab: 'info' })
*
* // format: `variables` (best for code splitting & privacy)
* PAGE_site_id({ id: 7, tab: 'info' })
*
* // format: `object[path]`
* PAGES["/site/[id]"]({ id: 7, tab: 'info' })
*
* // format: `object[symbol]`
* PAGES.site_id({ id: 7, tab: 'info' })
*
* // you have also `route(path) & object[path]` AND `route(symbol) & object[symbol]`
* // if you want everything to be exported
*/
format: 'route(path)'
})
- In addition to formats, you can swich
on
a flag to have even shorter functions. This applies when you have only 1 required param.
kitRoutes({
/**
* default is: `false`
*
* If you have only 1 required param, it will be a direct arg (not part of an object).
*
* route("/site/[id]", 7) route(path)
* route("site_id", 7) route(symbol)
* PAGE_site_id(7) variables
* PAGES["/site/[id]"](7) object[path]
* PAGES.site_id(7) object[symbol]
*/
format_short: true
})
- You like nice and formated files? You can add any cmd after the generation.
Here is an example of prettier
kitRoutes({
post_update_run: 'npm exec prettier ./src/lib/ROUTES.ts -- -w'
})
- You can specify a searchParam for some paths (you can also do it globally)
kitRoutes({
PAGES: {
'/site': {
explicit_search_params: {
limit: { type: 'number' }
}
}
}
})
- You can narrow down the type of params (You can also change
"string | number"
default globally)
kitRoutes({
PAGES: {
'/site/[id]': {
params: {
id: { type: 'string' }
}
}
}
})
- You want better typings? Add the
KIT_ROUTES
type… It will be crazy good! I’m not sure you are ready! UnderPAGES
,SERVERS
andACTIONS
, you will get autocompletion for route config. 🤯
import { kitRoutes } from 'vite-plugin-kit-routes'
import type { KIT_ROUTES } from '$lib/ROUTES'
kitRoutes<KIT_ROUTES>({
// Conf
})
- You want to use some
LINKS
in different places in your app? Let’s show you what we can do:
kitRoutes({
LINKS: {
// reference to a hardcoded link
twitter: 'https://twitter.com/jycouet',
// ✅ <a href={LINKS.twitter}>Twitter</a>
// reference to link with params! (Like svelteKit routes add [ ] to specify params)
twitter_post: 'https://twitter.com/[name]/status/[id]',
// ✅ <a href={LINKS.twitter_post({ name: 'jycouet', id: '1727089217707159569' })}>Twitter Post</a>
// reference to link with params & search params!
gravatar: {
href: 'https://www.gravatar.com/avatar/[str]',
explicit_search_params: {
s: { type: 'number', default: 75 },
d: { type: '"retro" | "identicon"', default: '"identicon"' }
}
}
// ✅ <img src={LINKS.gravatar({ str: 'jycouet', s: 20 })} alt="logo" />
}
})
Let me know what I forgot to add on TwiX, or what you would like to see in the future. 🙏