A simple, password-based session management library for SvelteKit personal projects.
Uses SvelteKit's experimental remote functions for type-safe client-server communication with progressive enhancement.
- Password-based authentication via environment variable
- Progressive enhancement with form-based sign in
- Cookie-based session management
- Full TypeScript support
- Works without JavaScript (graceful degradation)
- SvelteKit
^2.49.0(this library is only intended to use with SvelteKit!) - Svelte
^5.46.0
npm install sk-sesherAdd the experimental flag to your svelte.config.js:
// svelte.config.js
export default {
kit: {
experimental: {
remoteFunctions: true
}
}
};Create a .env file with your password:
SESSION_PASSWORD=your-secret-passwordUpdate your src/app.d.ts:
import type { SessionLocals } from 'sk-sesher';
declare global {
namespace App {
interface Locals extends SessionLocals {}
}
}
export {};Create or update src/hooks.server.ts:
import { handleSession } from 'sk-sesher';
export const handle = handleSession();Create src/routes/+layout.server.ts:
export const load = ({ locals }) => {
return {
session: locals.session
};
};Make sure to export them from any file ending in .remote.ts.
// src/lib/remote/auth.remote.ts
export { signIn, signOut } from "sk-sesher/auth/remote"Create src/routes/+layout.svelte:
<script>
import { signIn, signOut } from '$lib/remote/auth.remote.ts';
import { invalidateAll } from '$app/navigation';
let { data, children } = $props();
async function handleSignOut () {
await signOut()
await invalidateAll()
}
</script>
{#if data.session.isAuthenticated}
<button onclick={handleSignOut}>Sign Out</button>
{@render children()}
{:else}
<form {...signIn}>
<label>
Password
<input {...signIn.fields._password.as('password')} />
</label>
{#each signIn.fields._password.issues() as issue}
<p class="error">{issue.message}</p>
{/each}
<button disabled={!!signIn.pending}>
{signIn.pending ? 'Signing in...' : 'Sign In'}
</button>
</form>
{/if}That's it! Your app now has password protection.
import { handleSession } from 'sk-sesher';
export const handle = handleSession({
// Environment variable name for the password
envKey: 'MY_SECRET_PASSWORD', // default: 'SESSION_PASSWORD'
// Cookie name for the session
cookieName: 'auth', // default: 'session'
// Session duration in seconds
maxAge: 60 * 60 * 24 // default: 7 days
});import { handleSession } from 'sk-sesher';
import { sequence } from '@sveltejs/kit/hooks';
export const handle = sequence(
handleSession()
// your other hooks...
);This library provides two remote functions for authentication. Please keep in mind to re-export these from your own src/lib folder, otherwise they won't work. And turn on the experimental flags.
A remote form that handles password authentication with progressive enhancement.
<script>
import { signIn } from '$lib/remote/auth.remote';
import { invalidateAll } from '$app/navigation';
</script>
<form {...signIn}>
<label>
Password
<input {...signIn.fields._password.as('password')} />
</label>
{#each signIn.fields._password.issues() as issue}
<p class="error">{issue.message}</p>
{/each}
<button disabled={!!signIn.pending}>
{signIn.pending ? 'Signing in...' : 'Sign In'}
</button>
</form>Key features:
- Spread
{...signIn}onto your<form>element for progressive enhancement - Use
signIn.fields._password.as('password')to get the input attributes - Access validation issues via
signIn.fields._password.issues() - Check
signIn.result?.errorfor server-side errors (e.g., wrong password) - Check
signIn.pendingto show loading state
Note: The password field is named
_password(with underscore) to prevent it from being sent back to the client on validation errors, as per SvelteKit's sensitive data handling.
A remote command that clears the session cookie.
<script>
import { signOut } from '$lib/remote/auth.remote';
import { invalidateAll } from '$app/navigation';
async function handleSignOut() {
await signOut();
await invalidateAll(); // Refresh page data to reflect logged-out state
}
</script>
<button onclick={handleSignOut}>Sign Out</button>| Export | Type | Description |
|---|---|---|
handleSession |
(config?) => Handle |
Creates the session management hook |
SessionConfig |
type |
Configuration options type |
Session |
type |
Session state type ({ isAuthenticated: boolean }) |
SessionLocals |
type |
Type to extend App.Locals |
| Export | Type | Description |
|---|---|---|
signIn |
RemoteForm |
Form-based sign in with progressive enhancement |
signOut |
RemoteCommand |
Signs out and clears the session cookie |
handleSessionhook runs on every request, reading the session cookie and populatinglocals.sessionsignInis a remote form function that validates the password against the environment variable and sets a secure cookiesignOutis a remote command that clears the session cookie- The layout passes session state to the client and conditionally renders content
- The password is stored as an environment variable and never exposed to the client
- Session cookies are
httpOnly,secure, and usesameSite: 'lax' - The password field uses an underscore prefix (
_password) to prevent it from being echoed back on form errors - This is designed for personal projects with a single shared password, not multi-user authentication
MIT