# Your first console project

This tutorial takes you from an empty account to an app that loads your data
from the console. You create a project, import a CSV file, check the model the
console infers from it, run the application in the browser and then load the
same data from TypeScript.

You need an account at [console.dcupl.com](https://console.dcupl.com) and, for
the last step, Node.js with npm.

## 1. Create a project

1. Open [console.dcupl.com](https://console.dcupl.com) and sign in.
2. On the projects page, click **New Project** on the **Start a new Project**
   card.
3. Enter a **Project Name** and, optionally, a **Description**.
4. Leave **Starter Project** on **From Scratch**. The other starters come with
   sample data, which is useful for exploring but gets in the way here.
5. Click **Create Project**.

The project opens on its own. Everything you build from here on is a file in
this project: models, data and the loader configuration `dcupl.lc.json`, which
lists what gets loaded. The starter's loader configuration already defines an
application `default`.

## 2. Import a CSV file

Save these rows as `products.csv`:

```text filename="products.csv"
key,name,category,price,inStock
p1,Trail Runner,Shoes,129.90,true
p2,City Sneaker,Shoes,89.00,true
p3,Rain Jacket,Jackets,149.00,false
p4,Fleece Jacket,Jackets,99.50,true
p5,Wool Socks,Accessories,14.90,true
p6,Running Cap,Accessories,24.00,false
```

The `key` column is the item key: the loader uses a column of that name to
identify each row.

1. Open the file editor on the right-hand rail.
2. Click **+** (**Add resource**) and choose **Import Data**.
3. Under **Method**, pick **File Upload** and drop `products.csv` on the form, or click
   **Choose File**. **Upload Path** becomes `data/products.csv`.
4. Under **Model handling**, choose **Create New Model** and enter `Product` as
   the **Model Key**.
5. Leave **Create a new resource in the loader configuration** ticked. It adds
   the file to `dcupl.lc.json`; without that entry nothing ever loads the file.
6. Click **Continue**.

The importer reads the file, infers the properties and hands you on to the
model form. [Importing data](/console/data-import) explains what each of the
three parts of the form writes, and when an external URL is the better choice.

## 3. Check the inferred model

The model form shows the properties the console read from the CSV, each with a
type. Before you save it, make sure the types are the ones you want:

| Column     | Type to set |
| ---------- | ----------- |
| `name`     | `string`    |
| `category` | `string`    |
| `price`    | `float`     |
| `inStock`  | `boolean`   |

Change any type that came out differently (a postcode read as a number, for
example, should be a `string`), then save the model. The console writes a model file
under `models/` and adds it to `dcupl.lc.json` as a `model` resource, next to
the `data` resource from the import.

A model holds the shape of an item, not its rows: the rows stay in
`data/products.csv` and are loaded into the model by the data resource.
[Models in the Console](/console/models) covers the property types, references
between models and why a model file needs its own loader entry.

## 4. Run the application

1. Open **Applications** in the project sidebar.
2. On the card of the `default` application, click **Run**.

The run loads the project into a real dcupl instance in your browser. It opens
on five views of that one instance:
[Dashboard, Data Explorer, Models, Loader Insights and Quality Analyzer](/console/applications#the-five-views-on-a-run).

Try three things:

- **Data Explorer**: pick the `Product` model. The table lists the six rows.
  Open the `category` filter under **Predefined**: it lists each category, and
  selecting **Shoes** narrows the table to two items. This is the faceted
  filtering your own app gets from the SDK.
- **Models**: the `Product` definition as it actually loaded.
- **Quality Analyzer**: empty if every row matched the model. A row that does
  not, say a price of `n/a`, shows up here instead of breaking the load.

If the Data Explorer warns that the dataset uses a generated model, the data
resource does not point at `Product`: check the entry's `model` in
`dcupl.lc.json` (see [Loader configuration](/console/loader)).

To try a file without saving anything to the project, use **Quick run** on the
Applications page instead; see
[Quick run vs a saved application](/console/applications#quick-run-vs-a-saved-application).

## 5. Load it from your code

Your app loads the same files from the dcupl CDN. It needs two values from the
console:

- **Project ID**: under **Project Settings → General**.
- **API key**: under **Project Settings → API Keys**, copy the value of the
  **Browser (read-only)** key. New projects are private, so every request needs
  a key, and this is the one meant to ship in browser code: it reads the files
  an app loads and writes nothing. [API keys](/console/api-keys) explains the
  other key types.

Install the SDK and the loader:

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

Then load the project and run the same filter as in the Data Explorer:

```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)
  },
});

const loader = new DcuplAppLoader();
dcupl.loaders.add(loader);

await loader.config.fetch(); // dcupl.lc.json of the draft version
await loader.process({ applicationKey: 'default' });
await dcupl.init();

const products = dcupl.lists.create({ modelKey: 'Product' });
products.catalog.query.addCondition({
  attribute: 'category',
  operator: 'eq',
  value: 'Shoes',
});

console.log(products.catalog.query.items()); // Trail Runner, City Sneaker
```

Without a `version`, the SDK loads the project's `draft` version, the one you
just edited in the console. [Load from the console](/sdk/guides/load-from-console)
covers pinning a version such as `production`, environments, and what to check
when the key or a file is refused.

## What you built

- A project whose files live in the console: `data/products.csv`, a model file
  for `Product` and a `dcupl.lc.json` that declares both.
- An application `default` that loads them, browsable in the console.
- An app that loads the same application from the CDN with the Browser
  (read-only) key.

## Next steps

- [Load from the console](/sdk/guides/load-from-console) — Versions, environments and keys for your app
- [REST APIs](/console/rapi) — Serve the same application over HTTP instead of loading it in the client
- [Workflows](/console/workflows) — Import and transform data on a schedule
- [Lists](/sdk/api/lists) — Query, filter and facet the loaded data
