# Pinecone Node.js SDK: first working setup
## Install
```
npm install @pinecone-database/pinecone
```
## Authenticate from the environment
```
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone();
```
The SDK README shows this as option B: "Instantiate the client using the PINECONE_API_KEY environment variable". Keep the key out of source; the constructor with no arguments is the safe default.
## Create a serverless index
```
await pc.createIndex({
name: 'quickstart',
dimension: 1536,
metric: 'cosine',
spec: { serverless: { cloud: 'aws', region: 'us-east-1' } },
});
```
`spec` is required. Dimension must equal your embedding model's output width; metric is usually `cosine` for normalized embeddings, `dotproduct` for unnormalized, `euclidean` for the rest. Both are locked at creation.
## Wait, then write
Index creation is asynchronous. Poll `pc.describeIndex('quickstart')` until `status.ready` is true, then:
```
const index = pc.index('quickstart');
await index.upsert([{ id: 'vec1', values: [0.1, 0.2, 0.3] }]);
```
## Traps for agents
1. The package moved from `pinecone-client` (old, v0) to `@pinecone-database/pinecone`. If `npm install pinecone-client` appears in generated code, it is a stale tutorial artifact; use the scoped package.
2. Server code that calls the browser bundle or vice versa: the SDK is isomorphic, but never ship your API key to the browser. Browser-direct calls also hit CORS limits; keep Pinecone calls server-side.
3. Top-level await needs ESM (`"type": "module"`) or an async wrapper. In CommonJS, wrap setup in an async main.