Everything you need to build a Svelte project, powered by sv.
If you're seeing this, you've probably already done this step. Congrats!
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-appOnce you've created a project and installed dependencies with npm install (or pnpm install or yarn), start a development server:
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --openCopy src/routes/(centered)/contact/contact-info.server.example.toml to
contact-info.server.toml in the same directory, then replace the redacted values. The private
file is ignored by Git. Development falls back to the redacted example when the private file is
absent.
Production deployments should store the complete contents of the private TOML as the
CONTACT_INFO_TOML runtime secret. Do not commit the private file or put its values directly in
wrangler.toml.
For Cloudflare Workers:
pnpm exec wrangler secret put CONTACT_INFO_TOML \
< 'src/routes/(centered)/contact/contact-info.server.toml'For Vercel production:
vercel env add CONTACT_INFO_TOML production \
< 'src/routes/(centered)/contact/contact-info.server.toml'Add the Vercel variable separately for preview when preview deployments need the real profile.
Redeploy after adding or changing the secret.
The admin controls live at /contact/admin. Generate an access key, an admin-session signing
secret, and a separate visitor-grant signing secret:
The login form accepts the generated admin_... access key. It does not accept the SHA-256
digest or either signing secret stored in .env.
node <<'NODE'
const { createHash, randomBytes } = require('node:crypto')
const accessKey = `admin_${randomBytes(24).toString('base64url')}`
const accessKeyDigest = createHash('sha256').update(accessKey).digest('hex')
const sessionSecret = randomBytes(32).toString('base64url')
const grantSecret = randomBytes(32).toString('base64url')
console.log('\n=== ADMIN ACCESS KEY: SAVE THIS AND ENTER IT IN THE LOGIN FORM ===\n')
console.log(accessKey)
console.log('\n=== COPY THESE VALUES TO .env ===\n')
console.log(`CONTACT_ADMIN_KEY_SHA256=${accessKeyDigest}`)
console.log(`CONTACT_ADMIN_SESSION_SECRET=${sessionSecret}`)
console.log('CONTACT_ADMIN_SESSION_VERSION=1')
console.log(`CONTACT_GRANT_SECRET=${grantSecret}`)
console.log('\nRestart the development server after updating .env.\n')
NODEThe access key is printed once. Store it in a password manager. Keep both signing secrets separate
from the access key and from each other, and do not commit any of them. Rotating
CONTACT_GRANT_SECRET immediately invalidates outstanding visitor links and visitor cookies.
Generate and deploy a new value with the same command when the secret may be exposed, then create
fresh links for recipients who still need access. Admin sessions use their separate secret and are
not affected.
Restart the development server after updating .env, then follow the small "Admin" link at the
bottom of /contact or open /contact/admin directly.
To create a production version of your app:
npm run buildYou can preview the production build with npm run preview.
To deploy your app, you may need to install an adapter for your target environment.