---
name: vector-sveltekit
description: "Provisions an Upstash Vector index for a SvelteKit app with `npx extraorbital add vector` (no signup, no card) and wires it into SvelteKit with `@upstash/vector`. Use when a SvelteKit project needs Vector index, embeddings, semantic search, RAG, a vector database or UPSTASH_VECTOR_REST_URL, or when UPSTASH_VECTOR_REST_URL is missing or unset in .env."
---

# Vector index in SvelteKit

<!-- Generated from ExtraOrbital's service registry by `pnpm skills:build` in platform/app. Edit the generator, not this file. -->

ExtraOrbital provisions an Upstash Vector index in one command and writes the credentials into the project's env file. For anything this recipe does not cover, use the `extraorbital` skill or https://extraorbital.dev/llms.txt.

## 1. Provision

```bash
npx extraorbital add vector
```

Run it from the project root. It is idempotent (a second run returns the same resource) and writes to `.env.local` if the project has one, otherwise `.env`, keeping that file out of git. Add `--json` to parse the result; credential values are redacted there, and you should never print them either.

| Variable | |
| --- | --- |
| `UPSTASH_VECTOR_REST_URL` |  |
| `UPSTASH_VECTOR_REST_TOKEN` |  |

Free on the Prototype plan: 10K queries + 10K updates/day.

## 2. Install the client

```bash
npm install @upstash/vector
```

## 3. Connect

SvelteKit reads `.env` and `.env.local` into `$env/dynamic/private` in dev; in production the host's environment fills it.

**`src/lib/server/vector.ts`**

```ts
import { Index } from "@upstash/vector";
import { env } from "$env/dynamic/private";

export const vectorIndex = new Index({
  url: env.UPSTASH_VECTOR_REST_URL!,
  token: env.UPSTASH_VECTOR_REST_TOKEN!,
});
```

## 4. Use it

**`src/routes/api/vector/+server.ts`**

```ts
import { json } from "@sveltejs/kit";
import { vectorIndex } from "$lib/server/vector";

export async function GET() {
  const info = await vectorIndex.info();
  return json({ vectors: info.vectorCount, dimension: info.dimension });
}
```

Store and search:

```ts
// Each vector must have the index's dimension (1536 unless provisioned otherwise).
await vectorIndex.upsert({ id: "doc-42", vector: embedding, metadata: { title: "Q3 report" } });
const hits = await vectorIndex.query({ vector: queryEmbedding, topK: 5, includeMetadata: true });
```

## 5. Verify

```bash
npx extraorbital list        # the resource is listed as active
npm run dev
curl http://localhost:5173/api/vector
```

A JSON answer means the credentials, the client and the route all work. Delete the route afterwards if the app does not need it.

## Pitfalls

- Dimensions and the similarity function are fixed at creation. Match the embedding model: `npx extraorbital add vector --dimensions 3072` (default 1536, `COSINE`); to change them, provision a new `--slug` and re-index.
- `provision .` creates the index at 1536 dimensions when it detects the variables; run `add vector --dimensions …` first if your model differs.
- Embeddings come from your model; for an API key to call one, see the `ai-gateway-*` skills.
- Read credentials through `$env/dynamic/private`, not `process.env`: Vite does not put `.env` into `process.env` in dev, and `$lib/server/` keeps the module out of the browser bundle.
- `$env/dynamic/private` is empty while a page is prerendered: do not call the client from a prerendered route.
- Only `PUBLIC_*` variables reach the browser. Pass anything public a page needs from a `+page.server.ts` load function instead.
- Exit code 3 means the account is past its free allowance: show the human the link the command printed and wait. Do not retry or work around it.

Docs: https://extraorbital.dev/docs/resources/vector.md
