Package Exports
- sveltekit-flash-message/client
- sveltekit-flash-message/server
Readme
sveltekit-flash-message ⚡
This is a Sveltekit library that passes temporary data to the next request, usually from endpoints. It's useful when you want a "success" message displayed after a POST, which is not always displayed at the form, rather as a message on the page that the request was redirected to (since we are making well-behaved web apps that Redirects after Post).
This is known as a flash message, and it's especially well known in PHP apps, since it's easy to add this functionality with PHP's built-in session handling. With Sveltekit it's a bit harder, but this library was made to alleviate that.
Installation
pnpm i -D sveltekit-flash-message
Configuration
As usual, there are a few hoops to jump through:
1. [Typescript only] Add the flash message to app.d.ts
In src/app.d.ts
you should add the type for the flash message to App.Session
and App.Locals
as an optional property called flash
. It can be as simple as a string
, or something more advanced. It has to be serializable though, so only JSON-friendly data structures. Here's an example:
src/app.d.ts
type FlashMessage = {type: 'success' | 'error', message: string}
declare namespace App {
interface Locals {
flash?: Session['flash']
}
interface Session {
flash?: FlashMessage
}
}
2. Implement hooks
If you're not using any SvelteKit hooks, this is a simple step. Create a src/hooks.ts
file with the following content:
src/hooks.ts
export { handle, getSession } from 'sveltekit-flash-message/server'
If you've implemented a handle
hook already, you can use sequence with the handleFlashMessage
function instead:
src/hooks.ts
import { sequence } from '@sveltejs/kit/hooks'
import { handleFlashMessage } from 'sveltekit-flash-message/server'
const yourHandle : Handle = async ({ event, resolve }) => {
// ...
}
export const handle = sequence(handleFlashMessage(), yourHandle)
If you've implemented getSession
as well, just add the flash
property to your own code:
src/hooks.ts
export const getSession = (event : RequestEvent) => {
return {
// ... other session variables here ...
flash?: event.locals.flash
}
}
3. Add lifecycle methods
After adding the hooks, the library is pretty much ready to use for SSR, but we want it to work client-side as well! To do this, you must add some lifecycle functions in a top-level component, most likely __layout.svelte
:
src/routes/__layout.svelte
<script lang="ts">
import { session } from '$app/stores';
import { updateFlashMessage } from 'sveltekit-flash-message/client'
import { onMount, beforeUpdate } from 'svelte';
onMount(() => updateFlashMessage(session))
beforeUpdate(() => updateFlashMessage(session))
</script>
This should take care of updates passed on from the endpoints, which is the next step to add:
4. Start using the library
Server-side: Update endpoints
To set the actual flash message, you'll import the flashMessage
function in your endpoints, and use it on a RequestHandlerOutput (the structure you return from an endpoint). Here's an example from the Todo app, if your flash message is a string
:
import { flashMessage } from 'sveltekit-flash-message/server'
export const POST : RequestHandler = async ({ request, locals }) => {
const form = await request.formData();
await api('POST', `todos/${locals.userid}`, {
text: form.get('text')
});
const redirect = {
status: 303,
headers: {
location: '/todos'
}
}
// <App.Session['flash']> is optional, but helps with type-safety.
return flashMessage<App.Session['flash']>("That's the entrepreneur spirit!", redirect)
}
Note: You should not add flash messages to GET
requests! It causes caching and SSR problems, and goes against the idea of getting a message after an action is taken. The exception is if the GET
request redirects, then it's useful as an explanation why the redirect happened.
Client-side: Update session directly
If you want to update the flash message on the client, just assign a new value to $session.flash
.
5. Finally, display the flash message!
This is the simplest step of them all, just import session
and use $session.flash
like any other store:
YourComponent.svelte
<script lang="ts">
import { session } from '$app/stores';
</script>
{#if $session.flash}
<p><b>{$session.flash}</b></p>
{/if}
So much work, for so little?
It may seem so, but this library works for any kind of request, both SSR and client, which is trickier than it seems (and maybe trickier than what it should be...?)
Bonus: Removing flash message when navigating
This little snippet can be useful if you'd like to have the flash message removed when the user navigates to another route.
YourNavComponent.svelte
import { beforeNavigate } from '$app/navigation';
import { session } from '$app/stores';
beforeNavigate(nav => {
if(nav.from.href != nav.to?.href && $session.flash) {
$session.flash = undefined
}
})
Finally, an important warning
Since the flash message is transferred in a cookie, it can be easily tampered with, so don't trust its content. Treat it like you do with any user data - hanging from a ten-foot pole over a fiery pit. 🔥
Enjoy the library, and please open a github issue if you have suggestions or feedback in general!