Basic Svelte
Introduction
Bindings
Classes and styles
Attachments
Advanced Svelte
Advanced reactivity
Motion
Advanced bindings
Advanced transitions
Context API
Special elements
<script module>
Next steps
Basic SvelteKit
Introduction
Routing
Loading data
Headers and cookies
Shared modules
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion
Environment variables — like API keys and database credentials — can be added to a .env file, and they will be made available to your application.
You can also use
.env.localor.env.[mode]files — see the Vite documentation for more information. Make sure you add any files containing sensitive information to your.gitignorefile!
In this exercise, we want to allow the user to enter the website if they know the correct passphrase, using an environment variable.
First, in .env, add a new environment variable:
PASSPHRASE="open sesame"Next, create src/env.js, import defineEnvVars from @sveltejs/kit/env, and declare PASSPHRASE:
import { defineEnvVars } from '@sveltejs/kit/env';
export const variables = defineEnvVars({
PASSPHRASE: {}
});Environment variables are private by default, so PASSPHRASE is now available from $app/env/private.
Open src/routes/+page.server.js. Import the named variable and use it inside the form action:
import { redirect, fail } from '@sveltejs/kit';
import { PASSPHRASE } from '$app/env/private';
export function load({ cookies }) {
if (cookies.get('allowed')) {
redirect(307, '/welcome');
}
}
export const actions = {
default: async ({ request, cookies }) => {
const data = await request.formData();
if (data.get('passphrase') === PASSPHRASE) {
cookies.set('allowed', 'true');
redirect(303, '/welcome');
}
return fail(403, {
incorrect: true
});
}
};The website is now accessible to anyone who knows the correct passphrase.
Keeping secrets
It’s important that sensitive data doesn’t accidentally end up being sent to the browser, where it could easily be stolen by hackers and scoundrels.
SvelteKit makes it easy to prevent this from happening. Notice what happens if we try to import PASSPHRASE into src/routes/+page.svelte:
<script>
import { PASSPHRASE } from '$app/env/private';
let { form } = $props();
</script><script lang="ts">
import { PASSPHRASE } from '$app/env/private';
let { form } = $props();
</script>An error overlay pops up, telling us that $app/env/private cannot be imported into client-side code. It can only be imported into server-only modules, including:
- SvelteKit server modules like
+page.server.js,+layout.server.js,+server.jsandhooks.server.js - modules with a
serverfilename segment, likeserver.js,foo.server.jsorfoo.server.test.js - modules inside a
serverdirectory, except forserverdirectories insidesrc/routesorstatic
In turn, these modules can only be imported by other server modules.
Dynamic vs static
Environment variables are dynamic by default — their values are read when the app runs, rather than being fixed when it is built. This means you can build the app once and deploy it to different environments with different values.
If a value is known at build time, you can add static: true to its definition. For example, add a feature flag to .env:
PASSPHRASE="open sesame"
FEATURE_FLAG_X=enabledThen declare it as static:
import { defineEnvVars } from '@sveltejs/kit/env';
export const variables = defineEnvVars({
PASSPHRASE: {},
FEATURE_FLAG_X: {
static: true
}
});Static values are inlined into your application code, enabling useful optimisations like dead-code elimination:
import { FEATURE_FLAG_X } from '$app/env/private';
if (FEATURE_FLAG_X === 'enabled') {
// code in here will be removed from the build output
// if FEATURE_FLAG_X is not enabled
}Prior to SvelteKit 3 you didn’t have the option to declare an
env.jsfile - instead, private environment variables were automatically available via$env/dynamic/privateand$env/static/private.
<script>
let { form } = $props();</script>
<form method="POST">
<label>
enter the passphrase
<input name="passphrase" autocomplete="off" />
</label>
</form>
{#if form?.incorrect}<p class="error">wrong passphrase!</p>
{/if}<style>
.error {color: red;
}
</style>