qadeer-mustafa/nextgen-ai icon
public
Published on 9/4/2025
nova

An adaptive AI agent designed to analyze user input, learn from interactions, and deliver personalized recommendations. It combines natural language understanding, data-driven reasoning, and contextual awareness to act as a smart digital assistant across multiple domains.

Rules
Models
Context
40kinput·32koutput
200kinput·64koutput
openai GPT-5 model icon

GPT-5

OpenAI

400kinput·128koutput
anthropic Claude 4 Opus model icon

Claude 4 Opus

anthropic

200kinput·32koutput
200kinput·32koutput
200kinput·64koutput

MCP Servers

Learn more
URL: https://mcp.context7.com/mcp
URL: https://mcp.deepwiki.com/mcp
npx -y mongodb-mcp-server --connectionString ${{ inputs.CONNECTION_STRING }} --readOnly
## General

- The `.netlify` folder is not for user code. Add it to `.gitignore`.
- Do not include version numbers in imports (use `@netlify/functions`, not `@netlify/functions@VERSION`).
- Never add CORS headers (e.g., `Access-Control-Allow-Origin`) unless explicitly requested by the user.
- Use `netlify dev` to start the dev server unless the user requests a different command.

## Guidelines

- Netlify Blobs: Use for general object/state/data storage.
- Netlify Image CDN: Use for on-demand, dynamic image optimization and caching (not for build/development-time image modifications).
- Environment Variables: Store secrets, API keys, or sensitive/external values here—never in code.

## Local Development Troubleshooting

- If Netlify platform primitives (Blobs, Functions, etc.) aren't working locally, ensure `@netlify/vite-plugin` is installed for Vite-powered projects (or `@netlify/nuxt` for Nuxt), configured, and you're running the framework's dev command directly (e.g., `npm run dev`). This enables full local platform primitives emulation.




### Serverless Functions (aka Functions, aka Synchronous functions)
- Serverless functions use Node.js and should attempt to use built-in methods where possible
- When adding new npm modules, ensure "node_modules" is in the .gitignore
- ALWAYS use the latest format of a function structure.
- if using typescript, ensure types are installed from `npm install @netlify/functions`
- DO NOT put global logic outside of the exported function unless it is wrapped in a function definition
- ONLY use vanilla javascript if there are other ".js" files in the functions directory.
- ALWAYS use typescript if other functions are typescript or if there are no existing functions.
- The first argument is a web platform Request object that represents the incoming HTTP request
- The second argument is a custom Netlify context object.
- Functions have a global `Netlify` object that is also accessible.
  - ONLY use `Netlify.env.*` for interacting with environment variables in code.
- Place function files in `YOUR_BASE_DIRECTORY/netlify/functions` or a subdirectory.
  - The serverless functions directory can be changed via:
    - **Netlify UI**: *Project configuration > Build & deploy > Continuous deployment > Build settings*
    - **`netlify.toml`**:
      ```toml
      [functions]
        directory = "my_functions"
    ```
  - `netlify.toml` settings override UI settings.
- If using a subdirectory, name the entry file `index.mts` or match the subdirectory name.
  - Example valid function paths:
    - `netlify/functions/hello.mts`
    - `netlify/functions/hello/index.mts`
    - `netlify/functions/hello/hello.mts`
- Naming files with `.mts` enables modern ES module syntax

#### Examples of the latest Serverless Function or Function structures
  - ```typescript
      import type { Context, Config } from "@netlify/functions";

      export default async (req: Request, context: Context) => {
        // user code
        return new Response("Hello, world!")
      }

      export const config: Config = {
        // use this path instead of /.netlify/functions/{fnName}
        path: "/hello-world"
      };
    ```
  - ```javascript
      export default async (req, context) => {
        // user code
        return new Response("Hello, world!")
      }

      export const config = {
      // use this path instead of /.netlify/functions/{fnName}
        path: "/hello-world"
      };
    ```
#### In-code function config and routing for serverless functions
- prefer to use in-code configuration via exporting a `config` object. This is the structure the config can have:
- prefer to provide a friendly path using the config object.
- ONLY serverless functions use `/.netlify/functions/{function_name}` path by default.
- If you set a specific path via this config or the netlify.toml, it will only be available at that new path.
- path and excluded path supports substring patterns or the URLPattern syntax from the web platform.

```
{
  path: string | string[], // Defines the URL path(s) that trigger the function. Can be a single string or an array of paths.
  excludedPath?: string | string[], // Optional. Defines paths that should be excluded from triggering the function.
  preferStatic?: boolean, // Optional. If true, prevents the function from overriding existing static assets on the CDN.
}
```

### Background Functions
- Use background functions when you need to run long-running logic, and that logic does not need to compute a response immediately.
- Any data that background functions need to serve to users should be calculated and stored in a place that a serverless function can read from later - such as Netlify Blobs or a preconfigured database.
- Background functions operate the same as standard Serverless functions and are syntactically the same with the following exceptions
  - they have a 15-minute timeout measured by "wall clock" time
  - they immediately return an empty response with a 202 status code. Return values from these functions are ignored.
  - Background functions MUST have a "-background" suffix on the function file name or function directory (for example, netlify/functions/hello-background.mts or netlify/functions/hello-background/index.mts).

#### Examples of the latest background function structures
- ```typescript
    import { Context } from "@netlify/functions";

    export default async (req: Request, context: Context) => {
      await someLongRunningTask();

      console.log("Done");
    };
  ```

- ```javascript
    export default async (req, context) => {
      await someLongRunningTask();

      console.log("Done");
    };
  ```

### Scheduled Functions
- Use scheduled functions when the logic needs to run on an interval or can be defined via CRON timing.
- CRON expressions are executed against the UTC timezone
- our CRON syntax supports extensions defined the RFC except for the @reboot and @annually.
- The minimum interval is 1 minute
- Scheduled functions have a 30-second execution limit
- Scheduled functions do not return response bodies
- the request body is a JSON-encoded object containing a `next_run` property. It represents the timestamp of the next scheduled invocation, as a string in the ISO-8601 format.
- in addition to in-code config, schedules can be defined in the `netlify.toml`. ONLY do this for consistency or if explicitly asked to keep all schedules in one place.
  ```toml
    [functions."test-scheduled-function"]
      schedule = "@hourly"
  ```
- Scheduled functions ONLY run on published deploys. They don’t run on Deploy Previews or branch deploys.
- For local tests, the Netlify CLI to run the project in dev mode and the `netlify functions:invoke` [command](mdc:https:/cli.netlify.com/commands/functions/#functionsinvoke) to trigger the scheduled function.
  example:
  ```bash
    netlify functions:invoke myfunction
  ```

#### Examples of the latest background function structures
- ```typescript
    import type { Config } from "@netlify/functions"

    export default async (req: Request) => {
        const { next_run } = await req.json()

        console.log("Received event! Next invocation at:", next_run)
    }

    export const config: Config = {
        schedule: "@hourly"
    }

  ```

- ```javascript
    export default async (req) => {
        const { next_run } = await req.json()

        console.log("Received event! Next invocation at:", next_run)
    }

    export const config = {
        schedule: "@hourly"
    }

  ```



### Edge Functions
- ALWAYS use the latest format of an edge function structure.
- **DO NOT** add CORS headers (such as Access-Control-Allow-Origin) unless explicitly asked for them.
- if using typescript, ensure types are installed from `npm install @netlify/edge-functions`
- DO NOT put global logic outside of the exported function unless it is wrapped in a function definition
- ONLY use vanilla javascript if there are other ".js" files in the functions directory.
- ALWAYS use typescript if other functions are typescript or if there are no existing functions.
- The first argument is a web platform Request object that represents the incoming HTTP request
- The second argument is a custom Netlify context object.
- Edge functions have a global `Netlify` object that is also accessible.
  - ONLY use `Netlify.env.*` for interacting with environment variables in code.
- Place function files in `YOUR_BASE_DIRECTORY/netlify/edge-functions` or a subdirectory.
  - The serverless functions director can be changed via`netlify.toml`:
    ```toml
    [build]
      edge_functions = "my-custom-directory"
    ```

- Edge functions use Deno as runtime and should attempt to use built-in methods where possible. See the list of available web APIs to know which built-ins to use.
  - **Module Support**:
    - Supports **Node.js built-in modules**, **Deno modules**, and **npm packages** (beta).
  - **Importing Modules**:
    - **Node.js built-in modules**: Use `node:` prefix (e.g., `import { randomBytes } from "node:crypto"`).
    - **Deno modules**: Use **URL imports** (e.g., `import React from "https://esm.sh/react"` or an **import map**).
    - **npm packages (beta)**: Install via `npm install` and import by package name (e.g., `import _ from "lodash"`).
    - Some npm packages with **native binaries** (e.g., Prisma) or **dynamic imports** (e.g., cowsay) may not work.
  - You may use an **import map** to reference third-party modules with shorthand names instead of full URLs.
  - **Import Map Usage**:
    - Define mappings in a separate **import map file** (not in `deno.json`).
    - The file can be placed anywhere in the project directory.
  - **Example Import Map (`import_map.json`)**:
    ```json
    {
      "imports": {
        "html-rewriter": "https://ghuc.cc/worker-tools/html-rewriter/index.ts"
      }
    }
    ```
  - **Enabling Import Maps**:
    - Declare the import map in `netlify.toml`:
      ```toml
      [functions]
        deno_import_map = "./path/to/your/import_map.json"
      ```
  - **Usage in Code**:
    - Modules can now be imported by name:
      ```javascript
      import { HTMLRewriter } from "html-rewriter";
      ```
#### Examples of the latest Edge function structures
  - ```typescript
      import type { Context, Config } from "@netlify/edge-functions";

      export default async (req: Request, context: Context) => {
        // user code
        return new Response("Hello, world!")
      }

      export const config: Config = {
        path: "/hello-world"
      };
    ```
  - ```javascript
        export default async (req, context) => {
          // user code
          return new Response("Hello, world!")
        }

        export const config = {
          path: "/hello-world"
        };
    ```

#### Extra properties on context argument for Edge Functions
- these are ONLY available in Edge Functions

```
{
  ...ALL OTHER Context fields/methods,

  next: (options?: { sendConditionalRequest?: boolean }) => Promise<Response>, // Invokes the next item in the request chain, optionally using conditional requests.

  nextRequest: (request: Request, options?: { sendConditionalRequest?: boolean }) => Promise<Response>, // Same as next(), but requires an explicit Request object.
}

```

#### Web APIs available in Edge Functions ONLY
- console.*
- atob
- btoa
- Fetch API
  - fetch
  - Request
  - Response
  - URL
  - File
  - Blob
- TextEncoder
- TextDecoder
- TextEncoderStream
- TextDecoderStream
- Performance
- Web Crypto API
  - randomUUID()
  - getRandomValues()
  - SubtleCrypto
- WebSocket API
- Timers
  - setTimeout
  - clearTimeout
  - setInterval
- Streams API
  - ReadableStream
  - WritableStream
  - TransformStream
- URLPattern API


#### In-code function config and routing for Edge functions
- prefer to use in-code configuration via exporting a `config` object. This is the structure the config can have:
- prefer to provide a friendly path using the config object.
- Edge functions are configured with a path pattern and only paths matching those patterns will run the edge function
- path and excludedPath supports substring patterns or the URLPattern syntax from the web platform.
- unless explicitly asked to modify other properties, only set path, pattern, excludedPath when creating functions.

```
{
  path?: string | string[], // URLPattern expression defining paths where the edge function should run. Must start with '/'.
  excludedPath?: string | string[], // Optional. Defines paths to exclude from execution. Must start with '/'.
  pattern?: RegExp | RegExp[], // Alternative to `path`. Uses regex for path matching.
  excludedPattern?: RegExp | RegExp[], // Optional. Defines regex patterns to exclude certain routes.
  method?: string | string[], // Optional. Specifies HTTP methods that should trigger the function (e.g., "GET", ["POST", "PUT"]).
  onError?: "continue" | "fail" | "fallback", // Optional. Controls how the function handles errors.
  cache?: 'manual', // Optional. Enables response caching if set to 'manual'.
} = {
  path: "", // Default value; should be set per function.
};
```

#### Configuring Edge Functions in netlify.toml
- ONLY Use `netlify.toml` for precise function order control instead of inline declarations.
- DO NOT use `netlify.toml` if there is not edge function ordering requirements.
- When controlling order, it's important to include all edge functions for order control.

- **Declare Edge Functions in `netlify.toml`**:
  - Allows multiple edge functions on the same path with explicit execution order.
  - Functions run **top-to-bottom**, except cached functions, which always run last.

- **Edge Function Properties**:
  - `function`: Name of the edge function.
  - `path`: URL pattern to trigger the function (must start with `/`).
  - `excludedPath`: Excludes specific routes from `path` (supports string or array).
  - `pattern`: Regex-based path matching.
  - `excludedPattern`: Excludes specific regex patterns (single or array).
  - `cache`: Enables response caching (cached functions run after non-cached ones) set to 'manual' to opt in.

- **Netlify.toml config examples**
  ```toml
  [[edge_functions]]
    path = "/admin"
    function = "auth"

  [[edge_functions]]
    path = "/admin"
    function = "injector"
    cache = "manual"

  [[edge_functions]]
    path = "/blog/*"
    function = "auth"

  [[edge_functions]]
    path = "/blog/*"
    function = "rewriter"

  [[edge_functions]]
    pattern = "/products/(.*)"
    excludedPattern = "/products/things/(.*)"
    function = "highlight"

  [[edge_functions]]
    path = "/*"
    excludedPath = "/img/*"
    function = "common"
```
- **Execution Order for Edge Functions**:
  1. **Configuration-based** edge functions (`netlify.toml`) run first.
  2. **Framework-generated** edge functions execute before user-defined functions.
  3. **Non-cached** edge functions execute before cached functions.
  4. **Inline-declared** edge functions override duplicate `netlify.toml` functions.
  5. **Multiple inline edge functions** run alphabetically by filename.

- **Caveats & Special Cases**:
  - If an edge function returns a response, redirects for that path DO NOT occur.
  - Edge functions DO NOT execute for rewritten static routing targets.
  - `fetch()` or `URL()` triggers a **new request chain**, re-running matching functions.
  - Use `context.next()` to continue processing instead of re-triggering functions.
  - Function failure behavior depends on its **error handling configuration**.

#### Edge functions limitations
- 20 MB (compressed) code size limit
- 512 MB per deployment memory limit
- 50ms per request CPU execution time (excludes waiting time)
- 40 seconds Response header timeout
- **Not compatible with these Netlify features**:
  - Netlify's split testing feature
  - Custom Headers (including basic authentication) from _headers or netlify.toml config
  - Netlify prerendering feature on paths served by edge functions
- Be aware that multiple framework adapters may generate conflicting edge functions
- **Restrictions**:
  - Can only rewrite requests to same-site URLs (use `fetch()` for external content)
  - Cached edge functions override existing static files
  - No local caching; HTTP cache headers are ignored in local testing
  - Not included in Netlify’s HIPAA-compliant hosting offering


## Netlify Blobs

- Prefer using Netlify Blobs over creating a new database unless a flat file is not appropriate data layer, if explicitly asking to use a tool, or the dev needs to created relational structures or search that's more appropriate for databases
- Blobs do not require configuration to use, everything is automatically provisions, and devs can simply start using them via any Netlify compute. The API will be the same across all compute types.
- ensure `@netlify/blobs` NPM module is installed
- **Local development troubleshooting**: If you see "The environment has not been configured to use Netlify Blobs. To use it manually, supply the following properties when creating a store: siteID, token" error, install `@netlify/vite-plugin` for Vite-based projects to automatically configure the local environment. This does NOT apply to legacy V1 functions which require manual siteID/token configuration.
- Requirements and limits
  - Requires Fetch API support (Node.js 18+ recommended) - a fetch function can be provided to the store
  - Store names cannot exceed 64 bytes
  - Object keys cannot exceed 600 bytes
  - Maximum object size: 5GB
  - Local development uses a sandboxed store


### Netlify Blobs API

```typescript
  export interface BlobMetadata {
    [key: string]: any;
  }

  export interface BlobData<T = string> {
    data: T | null;
    etag: string;
    metadata: BlobMetadata;
  }

  export interface ListResult {
    blobs: { etag: string; key: string }[];
    directories?: string[];
  }

  interface GetKeyOptions {
    type?: 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text'
  }

  interface GetKeyAndMetadataOptions {
    type?: 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text',
    etag?: string;
  }

  // THESE ARE THE ONLY STORE METHODS. DO NOT MAKE UP NEW ONES
  interface Store {

    // Creates or overwrites a blob entry.
    // example: await store.set('key-name', 'contents-of key');
    // - NEVER add metadata unless instructed to.
    set(key: string, value: ArrayBuffer | Blob | string, { metadata?: object }): Promise<void>;

    // Stores a JSON-serializable object.
    // example: await store.setJSON('key-name', {version: 'a', someBoolean: true});
    // - NEVER add metadata unless instructed to.
    setJSON(key: string, value: any, { metadata?: object }): Promise<void>;

    // Retrieves a stored blob.
    // example: await store.get('key-name');
    // - NEVER add the second arg unless you need an explicit type 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text'.
    // - Instead of using JSON.parse(blob), use store.get('key-name', {type: 'json'})
    // - if the blob is missing, it will resolve the promise with a null value
    get(key: string, getOpt?: GetKeyOptions): Promise<any | null>;

    // Retrieves a blob along with metadata
    // example: await store.getWithMetadata('key-name');
    // - NEVER add the second getOpts arg unless you need an explicit type or have an etag to check against.
    // - AVOID adding it unless it's reliably available but IF an etag is provided, it will only return the blob if the etag is different that what's stored.
    // - if the blob is missing, it will resolve the promise with a null value
    getWithMetadata(key: string, getOpts?: GetKeyAndMetadataOptions): Promise<{ data: any, etag: string, metadata: object } | null>;

    // Retrieves metadata of a blob WITHOUT downloading the data.
    // example: await store.getMetadata('key-name');
    // - NEVER add the second getOpts arg unless you need an explicit type or have an etag to check against.
    // - AVOID adding it unless it's reliably available but IF an etag is provided, it will only return the blob if the etag is different that what's stored.
    // - if the blob is missing, it will resolve the promise with a null value
    getMetadata(key: string, getOpts?: GetKeyAndMetadataOptions): Promise<{ etag: string, metadata: object } | null>;

    // Lists blobs in the store with optional hierarchical browsing.
    // example:
    //      const { blobs } = await store.list()
    //      // blobs === [ { etag: 'etag1', key: 'some-key' }, { etag: 'etag2', key: 'another-key' } ]
    //
    // - NEVER add the options arg unless you need an explicit reduce the searched data.
    //    -- ONLY if you have to reduce searched data, use `prefix: 'some-prefix'` to pull blobs that start with that prefix value. Use `directories: true` to include the full directory path on the `key`
    // - By default, the list() method retrieves all pages, meaning you'll always get the full list of results. This can be slow or memory intensive. To paginate, pass the `paginate: true` in the options to turn the response into an AsyncIterator that allows you to for-of loop through the blobs in the store.
    // - if store path is empty, the blobs will resolve the promise with an empty array
    list(options?: { directories?: boolean, paginate?: boolean. prefix?: string }): Promise<{ blobs: BlobResult[], directories: string[] }> | AsyncIterable<{ blobs: BlobResult[], directories: string[] }>

    // Deletes a blob.
    // example: await store.delete('key-name');
    // - The return value is always resolves to `undefined`, regardless of whether or not there was an object to delete.
    delete(key: string): Promise<void>;
  }

  interface GetDeployStoreOptions extends Partial<ClientOptions> {
    deployID?: string;
    name?: string;
    region?: Region;
  }

  // Returns a store instance for managing blobs. This is global scoped data across all deploys.
  // example: const store = getStore('my-store');
  // - ONLY add the options argument if the user needs strong consistency
  export function getStore(name: string, options?: { consistency?: 'strong' | 'eventual' }): Store;

  // Returns a deploy-specific store instance for managing blobs tied to a deploy.
  // example: const store = getDeployStore('my-store');
  // - ONLY add the options argument if the user needs strong consistency
  declare const getDeployStore: (input?: GetDeployStoreOptions | string) => Store;
  interface GetStoreOptions extends Partial<ClientOptions> {
      deployID?: string;
      name?: string;
  }

  // Lists all stores available on a project.
  // example:
  //    const { stores } = await listStores();
  //      // [ "beauty", "construction" ]
  // - By default, the listStores() method retrieves all pages, meaning you'll always get the full list of results. This can be slow or memory intensive. To paginate, pass the `paginate: true` in the options to turn the response into an AsyncIterator that allows you to for-of loop through the blobs in the store.
  // - DO NOT pass options unless paginating.
  declare function listStores(options?: {
      paginate?: boolean;
  }): Promise<ListStoresResponse> | AsyncIterable<ListStoresResponse>;

  interface ListStoresResponse {
      stores: string[];
      next_cursor?: string;
  }

```

## File-Based Uploads
With file-based uploads, write blobs to deploy-specific stores after the project’s build completes. Useful for frameworks and other tools integrating with Netlify as it does not require a build plugin.

Put files in `.netlify/blobs/deploy/*` for deploy specific
```
.netlify/
├─ blobs/
|  ├─ deploy/
│  |  ├─ beauty/
│  │  |  └─ nails.jpg
```
To attach metadata to a blob via file upload flows, include a JSON file that prefixes the corresponding blob filename with $ and has a .json extension. For example:
```
├─ blobs/
|  ├─ deploy/
│  |  ├─ beauty/
│  │  |  ├─ nails.jpg
│  │  |  └─ $nails.jpg.json
```

## Blob consistency models
- By default, blobs are "eventually consistent" - Fast reads, updates/deletions propagated within 60 seconds.
- To have strong consistency that ensures updates are immediately visible at the cost of slower reads. set the `consistency` field to `'strong'` on the store instantiation.
- There is no concurrency control built in, last write wins. Add object-locking mechanisms if you need concurrency guarantees.

Example:
```javascript
const store = getStore({ name: "animals", consistency: "strong" });
await store.set("dog", "🐶");
const dog = await store.get("dog");
```

## Storage scopes
- blobs can be stored in a deploy-specific scope or at a global scope
- deploy-specific blobs sync with deploys and are removed with deploy deletions. `getDeployStore()` is used to interact with deploy specific stores.
- global scope blobs are not automatically cleaned up and are consistent across all branches. `getStore()` is used for global scope.
- Build plugins and file-based uploads must write to deploy-specific stores.
- ALWAYS When creating logic that saves to global scope, ensure that non-production data does not get stored in these global stores. This keeps production data isolated from test data. To do that, check for the environment and choose which store to use depending on the environment.

#### Examples of blob usage

```javascript
  // basic writing to a deploy store
  import { getDeployStore } from "@netlify/blobs";
  const store = getDeployStore("construction");
```

```javascript
  // basic writing to a global store
  import { getStore } from "@netlify/blobs";
  const store = getStore("construction");
```

```javascript
  // using global store if in production, otherwise use deploy scope store
  import { getStore, getDeployStore } from "@netlify/blobs";

  function getBlobStore(...storeOptions){

    if((Netlify.context?.deploy.context === 'production'){
      return getStore(...storeOptions);
    }

    return getDeployStore(...storeOptions)
  }

  const store = getBlobStore("construction");
```

## Netlify Image CDN
- All Netlify projects have a `/.netlify/images` route supported by their project without any additional enablement.
- Transform images via query parameters in requests to `/.netlify/images`.
- NEVER introduce circular dependencies with urls redirecting to urls that redirect back to the same url in a loop
- when using the ?url={URL} parameter, ensure the url is a URI encoded component.
- Supported transformations:
  - **source**: Required, specifies image URL (relative or remote).
  - **size**: `w` (width) and `h` (height) in pixels.
  - **fit**: Determines how the image is resized (`contain`, `cover`, `fill`).
  - **position**: Cropping alignment (`top`, `bottom`, `left`, `right`, `center`).
  - **format**: Convert to `avif`, `jpg`, `png`, `webp`, `gif`, or `blurhash`.
  - **quality**: Controls lossy format quality (`q`, 1-100, default 75).

### Example transformations
```html
  <!-- get an image hosted on this project and change its size and format -->
  <img src="/.netlify/images?url=/image.jpg&w=100&h=100&fit=cover&fm=webp&q=80" />

  <!-- get an image hosted externally and change its size and format -->
  <img src="/.netlify/images?url=https://example.com/path/to/image&w=40&h=10&fm=jpg&q=80" />
```

### Caching & deployment behavior
- Transformed images are cached at the edge.
- Source images are cached for future transformations.
- After a new deploy cached images are invalidated and so images can be reprocessed in case of changes
- Cache-busting via asset fingerprinting is recommended if you must finely control cache key.
- In order to use externally hosted (aka remote) images the domain pattern must be allowlisted in the Netlify `netlify.toml`.
  - Allow remote sources using:
    ```toml
    [images]
      remote_images = ["https://externalexample.com/.*"]
    ```
    - only absolute urls to external servers need to be in remote_images

### Redirects & Rewrites
- If you do not want to use the default `/.netlify/images` path, a redirect or rewrite can be used to have a different url.
- Define reusable transformation routes in `_redirects` or `netlify.toml` files.
- When doing so, the parameters can remain parameters to pass in or can be statically defined.
- Examples:
  - netlify.toml to use /transform-my-images/{imagePath}
    ```toml
      [[redirects]]
        from = "/transform-my-images/*"
        to = "/.netlify/images?url=/:splat&w=50&h=50"
        status = 200
    ```
  - _redirects to use /transform-all/{...imagePath}
    ```
      /transform-all/* /.netlify/images?url=/:splat&w=50&h=50 200
    ```

### Custom headers
- Custom headers can ONLY be applied to images hosted on the same domain.
- ONLY do this when explicitly asked
- Examples:
  - netlify.toml to use /transform-my-images/{imagePath}
    ```toml
      [[headers]]
        for = "/source-images/*"
        [headers.values]
          Cache-Control = "public, max-age=604800, must-revalidate"
    ```
  - _headers to use /{...imagePath}
    ```
      /source-images/* Cache-Control: public, max-age=604800, must-revalidate
    ```
### Image CDN framework support
Netlify Image CDN integrates with frameworks for automatic optimizations:
- **Angular**: `NgOptimizedImage` component will use Image CDN automatically
- **Astro**: `<Image />` component will use Image CDN automatically
- **Gatsby**: set `NETLIFY_IMAGE_CDN=true` and use the Contentful, Drupal, or WordPress source plugins.
- **Next.js**: set `remotePatterns` in `next.config.js`
- **Nuxt**: `nuxt/image` module will use Image CDN automatically



## Environment Variables
- securely create, manage, and use environment variables across projects. These variables can be set via the UI, CLI, API, or configuration files.
- when setting environment variables, Netlify local environment and cloud environment will make these variables available.
- **Precedence**: `netlify.toml` overrides UI/CLI/API variables, and project-specific variables take precedence over shared ones.

### Creating Environment Variables
Variables can be created and managed using:
- **Netlify UI**: Suggest using if they don't want to provide the values directly to this agent. They can navigate to it via the path "Project configuration > Environment variables".
- **Netlify CLI**: Prefer using this if the agent can run commands. This requires the project to be linked.
- **Netlify Configuration (`netlify.toml`)**: Defines variables at the repository level. ONLY use this for environment variables where the project is not linked yet and the values are not sensitive.

### Netlify CLI Command
- The project must be linked first before the CLI will add variables. See the rules for initializing and linking projects for how to do this.
- Use `env:set` for changes, `env:unset` to delete. `env:import` to import from a dotenv`.env` file.

#### Example usage of env var CLI
- Basic setting an environment variable for the project
  ```sh
    netlify env:set API_KEY "not-a-secret"
  ```
- Setting an environment variable that should be treated as a secret
  ```sh
      netlify env:set API_KEY "secret-value" --secret
  ```

### Example `netlify.toml` Configuration
- Using the netlify.toml the configuration can be specific to certain branches/deploy contexts.
- examples
  ```toml
    # Production context: all deploys from the Production branch
    # set in your project’s Branches settings in the Netlify UI will inherit
    # these settings. You can define environment variables
    # here but we recommend using the Netlify UI for sensitive
    # values to keep them out of your source repository.
    [context.production]
      publish = "output/"
      command = "make publish"
      environment = { NODE_VERSION = "14.15.3" }

    # Here is an example of how to define context-specific
    # environment variables. Be mindful when using this
    # option and avoid committing sensitive values to public
    # source repositories.
    [context.deploy-preview.environment]
      NOT_PRIVATE_ITEM = "not so secret"

    # Branch Deploy context: all deploys that are not from
    # a pull/merge request or from the Production branch
    # will inherit these settings.
    [context.branch-deploy.environment]
      NODE_ENV = "development"

    # Dev context: environment variables set here
    # are available for local development environments
    # run using Netlify Dev. These values can be
    # overwritten on branches that have a more specific
    # branch context configured.
    [context.dev.environment]
      NODE_ENV = "development"

    # Specific branch context: all deploys from
    # this specific branch will inherit these settings.
    [context.staging.environment] # “staging” is a branch name
      NODE_ENV = "development"
  ```

### `.env` File Handling
- Netlify builds do not read `.env` files directly
- Import `.env` variables into Netlify using the UI or CLI (`netlify env:import .env`).
- Export Netlify variables to `.env` files via UI or CLI (`env:list`).

### Export `.env` Variables
```sh
# list the production deploy context values in .env format
netlify env:list --plain --context production

# list the production deploy context values in .env format
# and pipe results into a .env file
netlify env:list --plain --context production > .env
```



  ## Netlify Forms

  If using Netlify Forms, prevent spam submissions with a honeypot field.

# Creating new sites

- do not add redirects to netlify.toml or \_redirects unless requested
- do not add custom headers to the netlify.toml or \_headers unless requested


# Initializing sites or linking them

- determine if a site is linked by checking if `PROJECT_FOLDER/.netlify/state.json` file exists and it has a populated `siteId` value. Note that the siteID appears as the project ID in the Netlify UI at app.netlify.com.
- if the site is not linked, run `netlify init` to allow the user to set up the site with Netlify. If the user deploys manually, it will set up the site to use Netlify automatically. If the user decides to set up a repo, they might have to set up the repo first. If the site is already set up on netlify then run `netlify link` for the user to input the credentials to link.

# Vite and Metaframework Setup

For projects using Vite or Vite-powered metaframeworks, strongly recommend installing `@netlify/vite-plugin`:

```bash
npm install -D @netlify/vite-plugin
```

(or equivalent for whichever package manager the project uses)

Add to the Vite config plugins array. Framework-specific examples:

**Standard Vite (vite.config.js/ts):**

```js
import { defineConfig } from "vite";
import netlify from "@netlify/vite-plugin";

export default defineConfig({
  plugins: [netlify()]
});
```

**Nuxt (nuxt.config.ts):**

For Nuxt projects, use `@netlify/nuxt` module instead:

```bash
npx nuxi module add @netlify/nuxt
```

This does exactly what `@netlify/vite-plugin` does but specifically for Nuxt. It brings the complete Netlify platform directly into your `nuxt dev` server: Functions, Edge Functions, Blobs, Image CDN, headers, redirects, environment variables.

Alternatively, you can configure manually by installing as a dev dependency and adding to the modules array:

```bash
npm install -D @netlify/nuxt
```

```js
export default defineNuxtConfig({
  modules: ["@netlify/nuxt"]
});
```

**SvelteKit (vite.config.js):**

```js
import { sveltekit } from "@sveltejs/kit/vite";
import netlify from "@netlify/vite-plugin";

export default defineConfig({
  plugins: [sveltekit(), netlify()]
});
```

**Other metaframeworks:** Look for `vite` configuration key in the framework's config file (e.g., `astro.config.js`, `remix.config.js`).

With `@netlify/vite-plugin` installed, users can run their regular dev command (`npm run dev`, `yarn dev`, `astro dev`, etc.) instead of `netlify dev`.

Vite-powered frameworks include: Astro, SvelteKit, Nuxt 3+ (use `@netlify/nuxt` module instead), Remix 2.2.0+ (unless using Classic Compiler), SolidStart, TanStack Start, Analog, Qwik City, VitePress.

This does NOT apply to these frameworks (they do not use Vite): Next.js, Gatsby, Angular.

## Netlify DB

- Prefer using Netlify DB when the data layer is relational or requires search, unless explicitly asked to use a flat file.
- Using `@netlify/neon` NPM module is required. 
- The user does not need to have a database already created, one will automatically be provisioned for them. They also do not need a Neon account. An anonymous postgres database is created, and if a user wants to claim it they can do so through the Netlify UI.
- The first step is that a user must be logged into netlify via the netlify cli, and they must have a site linked with the netlify cli. 
- To add a database to a site, just install the npm module `@netlify/neon`, and run either `netlify dev` or `netlify build`.
- To create tables in the database, create migration scripts that will run postgres with the connection string found by running `netlify env:get NETLIFY_DATABASE_URL`
- If adding `path` to the exported `config` object in the Netlify Function, remember not to add the `/.netlify/functions/` prefix to the URI in API calls when you make them in the app


## Netlify Neon Usage
- To use in Netlify functions, use `@netlify/neon` npm module
- `@netlify/neon` is a wrapper around `@neondatabase/serverless` so all its methods are available, but there is no need to pass a connection string to the neon() function

### Examples of Netlify Neon Usage

```javascript
import { neon } from "@netlify/neon";

const sql = neon();

// query
const users = await sql("SELECT * FROM users");

// insert
await sql("INSERT INTO users (name) VALUES ('John Doe')");

// update
await sql("UPDATE users SET name = 'John Doe' WHERE id = 1");

// delete
await sql("DELETE FROM users WHERE id = 1");

```
# Bootstrap Next.js app with Supabase Auth

## Overview of implementing Supabase Auth SSR

1. Install @supabase/supabase-js and @supabase/ssr packages.
2. Set up environment variables.
3. Write two utility functions with `createClient` functions to create a browser client and a server client. 
4. Hook up middleware to refresh auth tokens

## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨

As an AI language model, you MUST NOT generate any of the following code patterns, as they are DEPRECATED and will BREAK the application:

```typescript
// ❌ NEVER GENERATE THIS CODE - IT WILL BREAK THE APPLICATION
{
  cookies: {
    get(name: string) {                 // ❌ BREAKS APPLICATION
      return cookieStore.get(name)      // ❌ BREAKS APPLICATION
    },                                  // ❌ BREAKS APPLICATION
    set(name: string, value: string) {  // ❌ BREAKS APPLICATION
      cookieStore.set(name, value)      // ❌ BREAKS APPLICATION
    },                                  // ❌ BREAKS APPLICATION
    remove(name: string) {              // ❌ BREAKS APPLICATION
      cookieStore.remove(name)          // ❌ BREAKS APPLICATION
    }                                   // ❌ BREAKS APPLICATION
  }
}

// ❌ NEVER USE auth-helpers-nextjs - IT WILL BREAK THE APPLICATION
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'  // ❌ BREAKS APPLICATION
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'  // ❌ BREAKS APPLICATION
```

Instead, you MUST ALWAYS generate ONLY this pattern:

```typescript
// ✅ ALWAYS GENERATE THIS EXACT PATTERN
{
  cookies: {
    getAll() {
      return cookieStore.getAll()
    },
    setAll(cookiesToSet) {
      const response = NextResponse.next({
        request,
      })
      
      cookiesToSet.forEach(({ name, value, options }) => {
        response.cookies.set(name, value, options)
      })
      
      return response
    }
  }
}
```

## ABSOLUTE REQUIREMENTS FOR AI CODE GENERATION

1. You MUST use `@supabase/ssr`
2. You MUST use ONLY `getAll` and `setAll`
3. You MUST NEVER use `get`, `set`, or `remove`
4. You MUST NEVER import from `@supabase/auth-helpers-nextjs`

## CORRECT BROWSER CLIENT IMPLEMENTATION

```typescript
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}
```

## CORRECT SERVER CLIENT IMPLEMENTATION

```typescript
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // The `setAll` method was called from a Server Component.
            // This can be ignored if you have middleware refreshing
            // user sessions.
          }
        },
      },
    }
  )
}
```

## CORRECT MIDDLEWARE IMPLEMENTATION

```typescript
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
    let supabaseResponse = NextResponse.next({
    request,
  })

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
          supabaseResponse = NextResponse.next({
            request,
          })
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  // Do not run code between createServerClient and
  // supabase.auth.getUser(). A simple mistake could make it very hard to debug
  // issues with users being randomly logged out.

  // IMPORTANT: DO NOT REMOVE auth.getUser()

  const {
    data: { user },
  } = await supabase.auth.getUser()

  if (
    !user &&
    !request.nextUrl.pathname.startsWith('/login') &&
    !request.nextUrl.pathname.startsWith('/auth')
  ) {
    // no user, potentially respond by redirecting the user to the login page
    const url = request.nextUrl.clone()
    url.pathname = '/login'
    return NextResponse.redirect(url)
  }

  // IMPORTANT: You *must* return the supabaseResponse object as it is.
  // If you're creating a new response object with NextResponse.next() make sure to:
  // 1. Pass the request in it, like so:
  //    const myNewResponse = NextResponse.next({ request })
  // 2. Copy over the cookies, like so:
  //    myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
  // 3. Change the myNewResponse object to fit your needs, but avoid changing
  //    the cookies!
  // 4. Finally:
  //    return myNewResponse
  // If this is not done, you may be causing the browser and server to go out
  // of sync and terminate the user's session prematurely!

  return supabaseResponse
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}
```

## AI MODEL VERIFICATION STEPS

Before generating any code, you MUST verify:

1. Are you using ONLY `getAll` and `setAll`? If not, STOP and FIX.
2. Are you importing from `@supabase/ssr`? If not, STOP and FIX.
3. Do you see ANY instance of `get`, `set`, or `remove`? If yes, STOP and FIX.
4. Are you importing from `auth-helpers-nextjs`? If yes, STOP and FIX.

## CONSEQUENCES OF INCORRECT IMPLEMENTATION

If you generate code using:
- Individual cookie methods (`get`/`set`/`remove`)
- `auth-helpers-nextjs` package

The implementation will:
1. Break in production
2. Fail to maintain session state
3. Cause authentication loops
4. Result in security vulnerabilities

## AI MODEL RESPONSE TEMPLATE

When asked about Supabase Auth SSR implementation, you MUST:
1. ONLY use code from this guide
2. NEVER suggest deprecated approaches
3. ALWAYS use the exact cookie handling shown above
4. VERIFY your response against the patterns shown here

Remember: There are NO EXCEPTIONS to these rules.
## Positive affirmation
You are a principal-level TypeScript and React engineer who writes best-practice, high performance code.

## Sanity Studio Schema Types
### Content modelling

- Unless explicitly modelling web pages or app views, create content models for what things are, not what they look like in a front-end
- For example, consider the `status` of an element instead of its `color`

### Basic schema types

- ALWAYS use the `defineType`, `defineField`, and `defineArrayMember` helper functions
- ALWAYS write schema types to their own files and export a named `const` that matches the filename
- ONLY use a `name` attribute in fields unless the `title` needs to be something other than a title-case version of the `name`
- ANY `string` field type with an `options.list` array with fewer than 5 options must use `options.layout: "radio"`
- ANY `image` field must include `options.hotspot: true`
- INCLUDE brief, useful `description` values if the intention of a field is not obvious
- INCLUDE `rule.warning()` for fields that would benefit from being a certain length
- INCLUDE brief, useful validation errors in `rule.required().error('<Message>')` that signal why the field must be correct before publishing is allowed
- AVOID `boolean` fields, write a `string` field with an `options.list` configuration
- NEVER write single `reference` type fields, always write an `array` of references
- CONSIDER the order of fields, from most important and relevant first, to least often used last

```ts
// ./src/schemaTypes/lessonType.ts

import {defineField, defineType} from 'sanity'

export const lessonType = defineType({
  name: 'lesson',
  title: 'Lesson',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      type: 'string',
    }),
    defineField({
      name: 'categories',
      type: 'array',
      of: [defineArrayMember({type: 'reference', to: {type: 'category'}})],
    }),
  ],
})
```

### Schema type with custom input components
- If a schema type has input components, they should be colocated with the schema type file. The schema type should have the same named export but stored in a `[typeName]/index.ts` file:

```ts
// ./src/schemaTypes/seoType/index.ts

import {defineField, defineType} from 'sanity'

import seoInput from './seoInput'

export const seoType = defineType({
  name: 'seo',
  title: 'SEO',
  type: 'object',
  components: { input: seoInput }
  // ...
})
```

### No anonymous reusable schema types

- ANY schema type that benefits from being reused in multiple document types should be registered as its own custom schema type.

```ts
// ./src/schemaTypes/blockContentType.ts

import {defineField, defineType} from 'sanity'

export const blockContentType = defineType({
  name: 'blockContent',
  title: 'Block content',
  type: 'array',
  of: [defineField({name: 'block',type: 'block'})],
})
```

### Decorating schema types

Every `document` and `object` schema type should:

- Have an `icon` property from `@sanity/icons`
- Have a customized `preview` property that shows rich contextual details about the document
- Use `groups` when the schema type has more than a few fields to collate related fields and only show the most important group by default. These `groups` should use the icon property as well.
- Use `fieldsets` with `options: {columns: 2}` if related fields could be grouped visually together, such as `startDate` and `endDate`

## Writing Sanity content for importing

When asked to write content:

- ONLY use the existing schema types registered in the Studio configuration
- ALWAYS write content as an `.ndjson` file at the root of the project
- NEVER write a script to write the file, just write the file
- IMPORT `.ndjson` files using the CLI command `npx sanity dataset import <filename.ndjson>`
- NEVER include a `.` in the `_id` field of a document unless you need it to be private
- NEVER include image references because you don't know what image documents exist
- ALWAYS write images in this format below, replacing the document ID value to generate the same placeholder image
```JSON
{"_type":"image","_sanityAsset":"image@https://picsum.photos/seed/[[REPLACE_WITH_DOCUMENT_ID]]/1920/1080"}
```

## Writing GROQ queries

- ALWAYS use SCREAMING_SNAKE_CASE for variable names, for example POSTS_QUERY
- ALWAYS write queries to their own variables, never as a parameter in a function
- ALWAYS import the `defineQuery` function to wrap query strings from the `groq` or `next-sanity` package
- ALWAYS write every required attribute in a projection when writing a query
- ALWAYS put each segement of a filter, and each attribute on its own line
- ALWAYS use parameters for variables in a query
- NEVER insert dynamic values using string interpolation

Here is an example of a good query:

```ts
import {defineQuery} from 'groq'

export const POST_QUERY = defineQuery(`*[
  _type == "post"
  && slug.current == $slug
][0]{
  _id,
  title,
  image,
  author->{
    _id,
    name
  }
}`)
```

## TypeScript generation

### For the Studio

- ALWAYS re-run schema extraction after making schema file changes with `npx sanity@latest schema extract` 

### For monorepos with a studio and a front-end

- ALWAYS extract the schema to the web folder with `npx sanity@latest schema extract --path=../<front-end-folder>/sanity/extract.json` 
- ALWAYS generate types with `npx sanity@latest typegen generate` after every GROQ query change
- ALWAYS create a TypeGen configuration file called `sanity-typegen.json` at the root of the front-end code-base

```json
{
  "path": "./**/*.{ts,tsx,js,jsx}",
  "schema": "./<front-end-folder>/sanity/extract.json",
  "generates": "./<web-folder>/sanity/types.ts"
}
```

### For the front-end

- ONLY write Types for document types and query responses if you cannot generate them with Sanity TypeGen

## Project settings and data

- ALWAYS check if there is a way to interact with a project via the CLI before writing custom scripts `npx sanity --help`

Prompts

Learn more

No Prompts configured

Context

Learn more
Reference all of the changes you've made to your current branch
Reference the last command you ran in your IDE's terminal and its output
Reference any file in your current workspace