Setup options
dcupl offers three setups: Console + Loader (recommended), the Loader with your own files, and SDK-only. All of them use the same query API—your application code stays the same regardless of which you choose.
Console + Loader (recommended)
The Console manages your models and data sources visually. The Loader fetches everything at runtime from Console's CDN.
Why it's recommended:
- Visual model editor – Define schemas without writing JSON
- External data sources – Load data from any URL, or pull it in from APIs, S3, Azure or git with workflows
- Environments – Per-environment variables and headers (e.g. dev, staging, prod) in the loader configuration
- Team collaboration – Non-developers can edit models and data
- Version control – Draft → Production file versions for safe deployments
Where the project ID and the Browser key come from, and how to pin a version or pick an environment: Load from the console.
Loader with your own files
The Loader doesn't need the Console. Point it at any host that serves a dcupl.lc.json and the files it lists: your own server or CDN, or dcupl serve from the CLI, which serves your project's dcupl/ folder on http://localhost:8083 by default.
Models are JSON files you host next to your data, and versioning is up to you (e.g. git).
Use cases:
- Local development against the files on your disk
- Projects that keep models and data in git and deploy them with the app
- Hosting the files yourself instead of on the dcupl CDN
SDK-only
Define models and load data directly in code. No external dependencies.
Use cases:
- Quick prototypes and learning
- Small, static datasets bundled with your app
- Full programmatic control required
Comparison
| Console + Loader (recommended) | Loader with your own files | SDK-only | |
|---|---|---|---|
| Packages | @dcupl/core + @dcupl/loader |
@dcupl/core + @dcupl/loader |
@dcupl/core |
| Models | Visual editor in Console | JSON files you host | Defined in code |
| Data | Auto-fetched from URLs | Auto-fetched from URLs | Inline or manual fetch |
| Environments | Loader environments you define | Loader environments you define | Manual config |
| Versioning | Draft → Production versions | Up to you (e.g. git) | Up to you (e.g. git) |
Setup code
import { Dcupl } from '@dcupl/core';
import { DcuplAppLoader } from '@dcupl/loader';
const dcupl = new Dcupl({
config: {
projectId: 'your-project-id', // From Console
apiKey: 'your-api-key', // From Console
version: 'draft', // CDN file version: 'draft' (default) or 'production'
},
});
const loader = new DcuplAppLoader();
dcupl.loaders.add(loader);
// Fetch configuration and data from Console CDN
await loader.config.fetch();
await loader.process(); // loads every resource in the configuration
await dcupl.init();
// Query your data
const list = dcupl.lists.create({ modelKey: 'Product' });
const results = list.catalog.query.items();import { Dcupl } from '@dcupl/core';
import { DcuplAppLoader } from '@dcupl/loader';
const dcupl = new Dcupl();
const loader = new DcuplAppLoader();
dcupl.loaders.add(loader);
// Fetches `${baseUrl}/dcupl.lc.json`; `${baseUrl}` in resource URLs
// resolves to the same host
await loader.config.fetch({ baseUrl: 'http://localhost:8083' }); // dcupl serve, or your own host
await loader.process();
await dcupl.init();
// Query your data
const list = dcupl.lists.create({ modelKey: 'Product' });
const results = list.catalog.query.items();import { Dcupl } from '@dcupl/core';
const dcupl = new Dcupl();
// Define model in code
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
],
});
// Load data inline
dcupl.data.set(
[
{ key: 'p1', name: 'Widget', price: 29.99 },
{ key: 'p2', name: 'Gadget', price: 49.99 },
],
{ model: 'Product' },
);
await dcupl.init();
// Query your data
const list = dcupl.lists.create({ modelKey: 'Product' });
const results = list.catalog.query.items();For every new Dcupl() option, see DcuplInitOptions.
Script tag (no build step)
For a page without a bundler, load the @dcupl/bundle browser build. It contains the SDK and the Loader and defines one global function, initDcupl():
<script src="https://cdn.jsdelivr.net/npm/@dcupl/bundle/dist/dcupl.bundle.min.js"></script>
<script>
initDcupl({
options: { config: { projectId: 'your-project-id', apiKey: 'your-api-key' } },
})
.then(({ dcupl }) => {
const list = dcupl.lists.create({ modelKey: 'Product' });
console.log(list.catalog.query.items());
})
.catch((error) => console.error('dcupl failed to load', error));
</script>initDcupl({ options, appLoaderConfig, processOptions })runs the Console + Loader setup above:new Dcupl(options),loader.config.fetch(appLoaderConfig),loader.process(processOptions)anddcupl.init(). It resolves{ dcupl, loader }and also setswindow.dcupl. It rejects when the loader configuration can't be fetched (Invalid Loader Configuration).- For your own files, pass
appLoaderConfig: { baseUrl: 'http://localhost:8083' }instead of the project config. - It resolves even when
init()resolvesfalse; the cause is logged to the console (see When init() Resolves false). - The URL above loads the latest release. In production, pin a version and add its
integrityhash together withcrossorigin="anonymous". Withoutcrossorigin, the browser blocks a cross-origin script that has anintegrityhash:
<script
src="https://cdn.jsdelivr.net/npm/@dcupl/bundle@<version>/dist/dcupl.bundle.min.js"
integrity="sha384-<hash>"
crossorigin="anonymous"
></script>Applications
A loader configuration can define applications: named presets in the applications[] array of dcupl.lc.json that pick resources by tag. Pass a key to process({ applicationKey }) to load only that part of the project; Load one application shows the call and what an unknown key does, Applications in the Loader API the full behaviour, and Applications how the Console uses them.
Migrating from SDK-only to Console
- Create a project in Console
- Define models in the visual editor (or import existing JSON)
- Add data sources (URLs, file uploads)
- Get your
projectIdandapiKey - Replace
dcupl.models.set()anddcupl.data.set()with the Loader setup - Query code stays the same—no changes needed