# Load from the console

Your app loads a console project's files (`dcupl.lc.json`, models, data, transformers) from the dcupl CDN with `DcuplAppLoader` from `@dcupl/loader`. This page walks through the values the app needs, the version it loads, how to load only part of the project, and what to check when the load fails. For the full setup code next to the other setups, see the [Console + Loader tab on Setup options](/sdk/setup-options#console-loader).

## What you need from the console

| Value      | Where to find it                                                   | Goes into                              |
| ---------- | ------------------------------------------------------------------ | -------------------------------------- |
| Project ID | **Project Settings → General**                                     | `new Dcupl({ config: { projectId } })` |
| API key    | **Project Settings → API Keys**, the **Browser (read-only)** key   | `new Dcupl({ config: { apiKey } })`    |
| Version    | **dcupl Cloud → Version Manager** (`draft` unless you made others) | `new Dcupl({ config: { version } })`   |

New projects are private: the CDN serves their files only to requests that carry one of the project's keys. The **Browser (read-only)** key is the one meant to ship in browser code: it reads `dcupl.lc.json`, `models/**`, `data/**`, `transformers/**` and `operators/**`, and writes nothing. Keys that can write stay on the server. [API keys](/console/api-keys) explains every key type.

Install the SDK and the loader in the same version (see [Compatibility](/sdk/compatibility)):

```bash
npm install @dcupl/core @dcupl/loader
```

## Load the project

```typescript filename="main.ts"
import { Dcupl } from '@dcupl/core';
import { DcuplAppLoader } from '@dcupl/loader';

const dcupl = new Dcupl({
  config: {
    projectId: 'your-project-id', // Project Settings → General
    apiKey: 'your-browser-key', // Browser (read-only)
    version: 'production', // optional, the default is 'draft'
  },
});

const loader = new DcuplAppLoader();
dcupl.loaders.add(loader); // copies projectId, apiKey and version into the loader

await loader.config.fetch(); // dcupl.lc.json of that version
await loader.process({ applicationKey: 'default' }); // models and data
await dcupl.init();
```

The order matters: `dcupl.loaders.add()` before `config.fetch()`, and `process()` before `dcupl.init()`, because `init()` doesn't run loaders. There are no `projectId` or `apiKey` fetch options; the loader reads them from `new Dcupl({ config })` and appends the key to every request to the dcupl CDN as the `api-key` query parameter.

## Pin a version

Without `version`, the app loads the project's `draft` version: the one the console edits. Every change you save in the console then reaches the app on its next load. For a deployed app, create a version such as `production` in the Version Manager (a new version starts as a copy of an existing one) and set `version: 'production'`: the app then loads that version while you keep editing `draft`.

The loader adds a `v` query parameter to its CDN requests that changes when the version's files change, so a browser or CDN cache doesn't serve outdated files after you update the version.

## Load one application

An application is a named preset in `dcupl.lc.json` that picks resources by tag. `process({ applicationKey })` loads only its resources; `process()` without a key loads every resource in the configuration.

```typescript
await loader.process({ applicationKey: 'catalog' });
```

Projects from `dcupl init` and the console's starter projects define `default`, which loads every resource. A key that isn't in the configuration throws `The applicationKey <key> does not exist`. See [Applications in the Loader API](/sdk/api/loader#applications) and [Tags and applications](/console/loader#tags-and-applications).

## Select an environment

An environment in `dcupl.lc.json` (`environments[]`) carries variables, request headers and query parameters for the resource downloads, for example a different API base URL for staging. Select it per run:

```typescript
await loader.process({ applicationKey: 'default', environmentKeys: ['production'] });
```

- An application doesn't select environments: pass `environmentKeys` yourself.
- Environment variables apply in `process()`, not in `config.fetch()`: they can't change which `dcupl.lc.json` is fetched.
- Environment headers are sent only with resources that have `tags`.

The environment type is under [ProjectConfiguration](/sdk/api/loader#projectconfiguration), the variable order under [variables](/sdk/api/loader#variables).

## When the load fails

| What you see                                                                                                  | Cause and fix                                                                                                                                                                                                                                                   |
| ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config.fetch()` throws `Invalid Loader Configuration`                                                        | The request for `dcupl.lc.json` failed. The cause is logged first (prefix `AppLoader`): a `403` means the key is missing, isn't a key of this project, or doesn't cover `dcupl.lc.json`; a wrong `projectId` or a version that doesn't exist fails the same way |
| `config.fetch()` throws `dcupl not connected. Did you add your loader to dcupl? -> dcupl.loaders.add(loader)` | Call `dcupl.loaders.add(loader)` first                                                                                                                                                                                                                          |
| The app starts, but a model has no rows or scripts are missing                                                | The key doesn't cover that resource's path, so it answered `403`. The loader records an `InvalidResource` loader error and loads the rest: check `dcupl.quality.errors.summary()`                                                                               |
| `process()` throws `The applicationKey <key> does not exist`                                                  | The configuration has no application with that key; omit the key or add the application                                                                                                                                                                         |

The Browser (read-only) key doesn't cover `scripts/**`. A browser app whose `dcupl.lc.json` declares `script` resources there needs a scoped key of its own whose read patterns cover them; [The globs must cover everything the app loads](/console/api-keys#the-globs-must-cover-everything-the-app-loads) shows how to check. Every loader error is listed under [Setup errors](/sdk/api/loader#setup-errors) and [Error types](/sdk/advanced/quality-validation#error-types).

## Next steps

- [Production deployment](/sdk/guides/deployment) — Keys on the server, refresh and the Content Security Policy
- [Loader API](/sdk/api/loader) — Every option of `config`, `process()` and `variables`
- [API keys](/console/api-keys) — Key types and read patterns
- [Loader configuration](/console/loader) — The `dcupl.lc.json` file
