sk-sesher
v0.0.5
Published
Simple password-based session management for SvelteKit personal projects
Maintainers
Readme
sk-sesher
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.
Features
- 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)
Requirements
- SvelteKit
^2.49.0(this library is only intended to use with SvelteKit!) - Svelte
^5.46.0
Installation
npm install sk-sesherQuick Start
1. Enable Remote Functions
Add the experimental flag to your svelte.config.js:
// svelte.config.js
export default {
kit: {
experimental: {
remoteFunctions: true
}
}
};2. Set Environment Variable
Create a .env file with your password:
SESSION_PASSWORD=your-secret-password3. Configure Types
Update your src/app.d.ts:
import type { SessionLocals } from 'sk-sesher';
declare global {
namespace App {
interface Locals extends SessionLocals {}
}
}
export {};4. Add the Hook
Create or update src/hooks.server.ts:
import { handleSession } from 'sk-sesher';
export const handle = handleSession();5. Pass Session to Client
Create src/routes/+layout.server.ts:
export const load = ({ locals }) => {
return {
session: locals.session
};
};6. Re-export remote functions inside your lib folder
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"7. Create Layout with Auth Check
Create src/routes/+layout.svelte:
<script>
import { signIn, signOut } from '$lib/remote/auth.remote.ts';
import { invalidateAll } from '$app/navigation';
let { data, children } = $props();
</script>
{#if data.session.isAuthenticated}
<button onclick={signOut}>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}
{#if signIn.result?.error}
<p class="error">{signIn.result.error}</p>
{/if}
<button disabled={!!signIn.pending}>
{signIn.pending ? 'Signing in...' : 'Sign In'}
</button>
</form>
{/if}That's it! Your app now has password protection.
Configuration
Custom Options
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
});Using with Other Hooks
import { handleSession } from 'sk-sesher';
import { sequence } from '@sveltejs/kit/hooks';
export const handle = sequence(
handleSession()
// your other hooks...
);Remote Functions
This library provides two remote functions for authentication:
signIn (form)
A remote form that handles password authentication with progressive enhancement.
<script>
import { signIn } from 'sk-sesher/auth/remote';
import { invalidateAll } from '$app/navigation';
// Use enhance for progressive enhancement
const enhanced = signIn.enhance(async ({ submit }) => {
await submit();
if (signIn.result?.success) {
await invalidateAll();
}
});
</script>
<form {...enhanced}>
<label>
Password
<input {...signIn.fields._password.as('password')} />
</label>
<!-- Validation errors -->
{#each signIn.fields._password.issues() as issue}
<p class="error">{issue.message}</p>
{/each}
<!-- Server-side errors (wrong password) -->
{#if signIn.result?.error}
<p class="error">{signIn.result.error}</p>
{/if}
<button disabled={!!signIn.pending}>
{signIn.pending ? 'Signing in...' : 'Sign In'}
</button>
</form>Key features:
- Spread
{...enhanced}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.
signOut (command)
A remote command that clears the session cookie.
<script>
import { signOut } from 'sk-sesher/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>API Reference
Exports from sk-sesher
| 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 |
Exports from sk-sesher/auth/remote
| Export | Type | Description |
| --------- | --------------- | ----------------------------------------------- |
| signIn | RemoteForm | Form-based sign in with progressive enhancement |
| signOut | RemoteCommand | Signs out and clears the session cookie |
How It Works
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
Security Notes
- 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
License
MIT
