Build Your First dcupl Application
In this tutorial, you will build a complete dcupl application from scratch. By the end, you will have a working app that loads data, queries it, and displays results.
Time required: 15 minutes
What you will build: A simple book library app that filters books by genre and displays results.
Prerequisites
Before starting, make sure you have:
- Node.js 18 or higher installed (
node -vto check) - A code editor (VS Code recommended)
- Basic familiarity with TypeScript/JavaScript
Step 1: Create a New Project
Create a new directory for your project and initialize it.
mkdir my-dcupl-app
cd my-dcupl-app
npm init -yInstall the dcupl core package:
npm install @dcupl/coreyarn add @dcupl/corepnpm add @dcupl/coreTypeScript types are included, so no additional packages are needed.
Step 2: Create the Application File
Create a new file called app.ts in your project root:
import { Dcupl } from '@dcupl/core';
async function main() {
console.log('Starting dcupl app...');
// We will add code here in the next steps
}
main();Run it to make sure everything is set up correctly:
npx tsx app.tsYou should see "Starting dcupl app..." in your terminal.
Step 3: Create a dcupl Instance
The Dcupl class is the entry point for everything. Create an instance at the top of your main function:
import { Dcupl } from '@dcupl/core';
async function main() {
// Create the dcupl instance
const dcupl = new Dcupl();
console.log('dcupl instance created');
}
main();The dcupl instance is an empty container. Next, you will tell it what kind of data to expect.
Step 4: Define a Model
Models describe the structure of your data. Think of them like TypeScript interfaces or database schemas.
Add this model definition after creating the dcupl instance:
import { Dcupl } from '@dcupl/core';
async function main() {
const dcupl = new Dcupl();
// Define the Book model
dcupl.models.set({
key: 'Book',
properties: [
{ key: 'title', type: 'string' },
{ key: 'author', type: 'string' },
{ key: 'genre', type: 'string' },
{ key: 'year', type: 'int' },
{ key: 'rating', type: 'float' },
],
});
console.log('Model defined');
}
main();This tells dcupl that "Book" items have five properties: title, author, genre, year, and rating.
Step 5: Load Data
Now add some data that matches the model. In a real app, this could come from an API or file. For now, use inline data:
import { Dcupl } from '@dcupl/core';
async function main() {
const dcupl = new Dcupl();
// Define the Book model
dcupl.models.set({
key: 'Book',
properties: [
{ key: 'title', type: 'string' },
{ key: 'author', type: 'string' },
{ key: 'genre', type: 'string' },
{ key: 'year', type: 'int' },
{ key: 'rating', type: 'float' },
],
});
// Load book data
dcupl.data.set(
[
{
key: 'b1',
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
genre: 'Fiction',
year: 1925,
rating: 4.5,
},
{
key: 'b2',
title: 'To Kill a Mockingbird',
author: 'Harper Lee',
genre: 'Fiction',
year: 1960,
rating: 4.8,
},
{
key: 'b3',
title: 'A Brief History of Time',
author: 'Stephen Hawking',
genre: 'Science',
year: 1988,
rating: 4.6,
},
{
key: 'b4',
title: 'The Selfish Gene',
author: 'Richard Dawkins',
genre: 'Science',
year: 1976,
rating: 4.3,
},
{
key: 'b5',
title: '1984',
author: 'George Orwell',
genre: 'Fiction',
year: 1949,
rating: 4.7,
},
{
key: 'b6',
title: 'Cosmos',
author: 'Carl Sagan',
genre: 'Science',
year: 1980,
rating: 4.9,
},
],
{ model: 'Book' }
);
console.log('Data loaded');
}
main();Each item needs a unique key property. This is how dcupl identifies items internally.
Step 6: Initialize dcupl
Before querying, you must call init(). This builds indexes for fast lookups:
// ... previous code ...
// Initialize dcupl (builds indexes)
await dcupl.init();
console.log('dcupl initialized and ready');
}
main();Run the app again to verify everything works:
npx tsx app.tsStep 7: Create Your First Query
Now for the fun part. Create a list to query your data:
import { Dcupl } from '@dcupl/core';
async function main() {
const dcupl = new Dcupl();
dcupl.models.set({
key: 'Book',
properties: [
{ key: 'title', type: 'string' },
{ key: 'author', type: 'string' },
{ key: 'genre', type: 'string' },
{ key: 'year', type: 'int' },
{ key: 'rating', type: 'float' },
],
});
dcupl.data.set(
[
{
key: 'b1',
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
genre: 'Fiction',
year: 1925,
rating: 4.5,
},
{
key: 'b2',
title: 'To Kill a Mockingbird',
author: 'Harper Lee',
genre: 'Fiction',
year: 1960,
rating: 4.8,
},
{
key: 'b3',
title: 'A Brief History of Time',
author: 'Stephen Hawking',
genre: 'Science',
year: 1988,
rating: 4.6,
},
{
key: 'b4',
title: 'The Selfish Gene',
author: 'Richard Dawkins',
genre: 'Science',
year: 1976,
rating: 4.3,
},
{
key: 'b5',
title: '1984',
author: 'George Orwell',
genre: 'Fiction',
year: 1949,
rating: 4.7,
},
{
key: 'b6',
title: 'Cosmos',
author: 'Carl Sagan',
genre: 'Science',
year: 1980,
rating: 4.9,
},
],
{ model: 'Book' }
);
await dcupl.init();
// Create a list for the Book model
const bookList = dcupl.lists.create({ modelKey: 'Book' });
// Get all books
const allBooks = bookList.catalog.query.items();
console.log('All books:', allBooks.length);
// Get the first book
const firstBook = bookList.catalog.query.first();
console.log('First book:', firstBook?.title);
}
main();Run it:
npx tsx app.tsYou should see:
All books: 6
First book: The Great GatsbyStep 8: Add Filters
Filter the list to show only science books:
// ... after creating bookList ...
// Filter by genre
bookList.catalog.query.addCondition({
attribute: 'genre',
operator: 'eq',
value: 'Science',
});
const scienceBooks = bookList.catalog.query.items();
console.log('\nScience books:');
scienceBooks.forEach((book) => {
console.log(` - ${book.title} by ${book.author}`);
});Output:
Science books:
- A Brief History of Time by Stephen Hawking
- The Selfish Gene by Richard Dawkins
- Cosmos by Carl SaganStep 9: Add Multiple Filters
Add another filter to find highly-rated science books:
// Add a second condition (rating >= 4.5)
bookList.catalog.query.addCondition({
attribute: 'rating',
operator: 'gte',
value: 4.5,
});
const topScienceBooks = bookList.catalog.query.items();
console.log('\nTop-rated science books (4.5+):');
topScienceBooks.forEach((book) => {
console.log(` - ${book.title} (${book.rating})`);
});Multiple conditions use AND logic by default.
Step 10: Sort and Paginate
Sort results and limit the output:
// Clear previous filters
bookList.catalog.query.clear();
// Get all books sorted by year (newest first)
const sortedBooks = bookList.catalog.query.items({
sort: { attributes: ['year'], order: ['desc'] },
});
console.log('\nBooks by year (newest first):');
sortedBooks.forEach((book) => {
console.log(` - ${book.year}: ${book.title}`);
});
// Paginate: get first 3 books
const firstPage = bookList.catalog.query.items({
start: 0,
count: 3,
});
console.log('\nFirst page (3 books):');
firstPage.forEach((book) => {
console.log(` - ${book.title}`);
});Step 11: Get Facet Counts
Facets tell you how many items exist for each value. This is useful for building filter UIs:
// Get facet counts for genres
const genreFacets = bookList.catalog.fn.facets({ attribute: 'genre' });
console.log('\nBooks by genre:');
genreFacets.forEach((facet) => {
console.log(` - ${facet.value}: ${facet.count} books`);
});Output:
Books by genre:
- Fiction: 3 books
- Science: 3 booksComplete Code
Here is the complete application:
import { Dcupl } from '@dcupl/core';
async function main() {
// 1. Create dcupl instance
const dcupl = new Dcupl();
// 2. Define model
dcupl.models.set({
key: 'Book',
properties: [
{ key: 'title', type: 'string' },
{ key: 'author', type: 'string' },
{ key: 'genre', type: 'string' },
{ key: 'year', type: 'int' },
{ key: 'rating', type: 'float' },
],
});
// 3. Load data
dcupl.data.set(
[
{
key: 'b1',
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
genre: 'Fiction',
year: 1925,
rating: 4.5,
},
{
key: 'b2',
title: 'To Kill a Mockingbird',
author: 'Harper Lee',
genre: 'Fiction',
year: 1960,
rating: 4.8,
},
{
key: 'b3',
title: 'A Brief History of Time',
author: 'Stephen Hawking',
genre: 'Science',
year: 1988,
rating: 4.6,
},
{
key: 'b4',
title: 'The Selfish Gene',
author: 'Richard Dawkins',
genre: 'Science',
year: 1976,
rating: 4.3,
},
{
key: 'b5',
title: '1984',
author: 'George Orwell',
genre: 'Fiction',
year: 1949,
rating: 4.7,
},
{
key: 'b6',
title: 'Cosmos',
author: 'Carl Sagan',
genre: 'Science',
year: 1980,
rating: 4.9,
},
],
{ model: 'Book' }
);
// 4. Initialize
await dcupl.init();
// 5. Create a queryable list
const bookList = dcupl.lists.create({ modelKey: 'Book' });
// Get all books
console.log('Total books:', bookList.catalog.query.count());
// Filter by genre
bookList.catalog.query.addCondition({
attribute: 'genre',
operator: 'eq',
value: 'Science',
});
console.log('\nScience books:');
bookList.catalog.query.items().forEach((book) => {
console.log(` - ${book.title} by ${book.author}`);
});
// Clear and show facets
bookList.catalog.query.clear();
console.log('\nBooks by genre:');
bookList.catalog.fn.facets({ attribute: 'genre' }).forEach((facet) => {
console.log(` - ${facet.value}: ${facet.count}`);
});
}
main();What You Learned
In this tutorial, you learned how to:
- Create a dcupl instance
- Define a model with typed properties
- Load data into the model
- Initialize dcupl to build indexes
- Create a list to query data
- Filter data with conditions
- Sort and paginate results
- Get facet counts for building filter UIs
Next Steps
Now that you have the basics, try these tutorials:
- Build a Product Catalog - Create a filterable product catalog with faceted navigation
- Core Concepts - Understand models, properties, and references in depth
- Querying - Learn all the filter operators available
Troubleshooting
Error: "Cannot find module '@dcupl/core'"
Make sure you installed the package:
npm install @dcupl/coreError: "Model not found"
Make sure you call dcupl.models.set() before dcupl.init().
Query returns no results
Check that your filter values match exactly. Filters are case-sensitive by default.