---
title: Build and Run
description: Build and run a starter app to validate your install of Couchbase Lite on C
pubDate: 2026-08-17T09:53:44.266Z
antora:
  editUrl: https://github.com/couchbase/docs-couchbase-lite/edit/release/4.1/modules/c/pages/gs-build.adoc
  xref: xref:couchbase-lite:c:gs-build.adoc[]
---

[Consult the llms.txt file for a full list of contents](/llms.txt)
[View original HTML](/couchbase-lite/current/c/gs-build.html)

# Build and Run

> Description — _Build and run a starter app to validate your install of Couchbase Lite on C_  

Steps in Getting Started

[Install](gs-install.md)| **Build**

Couchbase Lite for C ships both a C API and a C++ wrapper API (cbl++). After installation, both APIs are available in the same package.

Include headers

* C
* C++

```c
#include cbl/CouchbaseLite.h
```

```cpp
#include cbl++/CouchbaseLite.hh
```

## [](#verify-install)Verify Install

Now you have _Couchbase Lite for C_ installed, you can verify that your apps build correctly.

Enter the C and C++ code from [Example 1](#ex-c-starter) into your editor of choice and build it.

Running it creates a database, adds a document, retrieves the document, updates the document and then deletes the document.

Example 1\. Sample code

* C
* C++

```c
//  Purpose-- provide an overview of available crud  and sync functionality
//
// Get the database (and create it if it doesn't exist)
CBLError err = {};
CBLDatabase* database = CBLDatabase_Open(FLSTR("mydb"), NULL, &err);
if(!database) {
    // Error handling.  For brevity, this is truncated in the rest of the snippet
    // and omitted in other doc code snippets
    fprintf(stderr, "Error opening database (%d / %d)\n", err.domain, err.code);
    FLSliceResult msg = CBLError_Message(&err);
    fprintf(stderr, "%.*s\n", (int)msg.size, (const char *)msg.buf);
    FLSliceResult_Release(msg);
    return;
}

// All CRUD operations must be carried out via a collection.
// Remember to release the collection using CBLCollection_Release() when done.
CBLCollection* collection = CBLDatabase_DefaultCollection(database, &err);

// The lack of 'const' indicates this document is mutable
// Create a new document (i.e. a record) in the database
CBLDocument* mutableDoc = CBLDocument_Create();
FLMutableDict properties = CBLDocument_MutableProperties(mutableDoc);
FLMutableDict_SetFloat(properties, FLSTR("version"), 3.0f);

// Save it to the database
if(!CBLCollection_SaveDocument(collection, mutableDoc, &err)) {
    // Failed to save, do error handling as above
    return;
}

// Since we will release the document, make a copy of the ID since it
// is an internal pointer.  Whenever we create or get an FLSliceResult
// or FLStringResult we will need to free it later too!
FLString id = CBLDocument_ID(mutableDoc);
CBLDocument_Release(mutableDoc);

// Update a document
mutableDoc = CBLCollection_GetMutableDocument(collection, id, &err);
if(!mutableDoc) {
    // Failed to retrieve, do error handling as above.  NOTE: error code 0 simply means
    // the document does not exist.
    return;
}

properties = CBLDocument_MutableProperties(mutableDoc);
FLMutableDict_SetString(properties, FLSTR("language"), FLSTR("C"));
if(!CBLCollection_SaveDocument(collection, mutableDoc, &err)) {
    // Failed to save, do error handling as above
    return;
}

// Note const here, means readonly
const CBLDocument* docAgain = CBLCollection_GetDocument(collection, id, &err);
if(!docAgain) {
    // Failed to retrieve, do error handling as above.  NOTE: error code 0 simply means
    // the document does not exist.
    return;
}

// No copy this time, so no release later (notice it is not FLStringResult this time)
FLString retrievedID = CBLDocument_ID(docAgain);
FLDict retrievedProperties = CBLDocument_Properties(docAgain);
FLString retrievedLanguage = FLValue_AsString(FLDict_Get(retrievedProperties, FLSTR("language")));
printf("Document ID :: %.*s\n", (int)retrievedID.size, (const char *)retrievedID.buf);
printf("Learning %.*s\n", (int)retrievedLanguage.size, (const char *)retrievedLanguage.buf);

CBLDocument_Release(mutableDoc);
CBLDocument_Release(docAgain);

// Create a query to fetch documents of type SDK
int errorPos;
CBLQuery* query = CBLDatabase_CreateQuery(
    database,
    kCBLN1QLLanguage,
    FLSTR("SELECT * FROM _ WHERE type = \"SDK\""), &errorPos, &err);
if(!query) {
    // Failed to create query, do error handling as above
    // Note that errorPos will contain the position in the N1QL string
    // that the parse failed, if applicable
    return;
}

CBLResultSet* result = CBLQuery_Execute(query, &err);
if(!result) {
    // Failed to run query, do error handling as above
    return;
}

CBLResultSet_Release(result);
CBLQuery_Release(query);

// Create replicator to push and pull changes to and from the cloud
CBLCollectionConfiguration collectionConfig = {};
collectionConfig.collection = collection;

CBLEndpoint* targetEndpoint = CBLEndpoint_CreateWithURL(FLSTR("ws://localhost:4984/getting-started-db"), &err);
if(!targetEndpoint) {
    // Failed to create endpoint, do error handling as above
    return;
}

CBLReplicatorConfiguration replConfig = {};
replConfig.collections = &collectionConfig;
replConfig.collectionCount = 1;
replConfig.endpoint = targetEndpoint;

CBLAuthenticator* basicAuth = CBLAuth_CreatePassword(FLSTR("john"), FLSTR("pass"));
replConfig.authenticator = basicAuth;

CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err);
CBLAuth_Free(basicAuth);
CBLEndpoint_Free(targetEndpoint);
if(!replicator) {
    // Failed to create replicator, do error handling as above
    return;
}

// Assume a function like the following sample
//
// static void getting_started_change_listener(void* context, CBLReplicator* repl, const CBLReplicatorStatus* status) {
//     if(status->error.code != 0) {
//         printf("Error %d / %d\n", status->error.domain, status->error.code);
//     }
// }

CBLListenerToken* token = CBLReplicator_AddChangeListener(replicator, getting_started_change_listener, NULL);

CBLReplicator_Start(replicator, false);

// Later, stop and release the replicator

// When finished release resources ... eg
CBLListener_Remove(token);

stop_replicator(replicator);

CBLCollection_Release(collection);
CBLDatabase_Release(database);
```

```cpp
//  Purpose-- provide an overview of available CRUD and sync functionality
//
// The C++ API reports failures by throwing cbl::Error. For brevity this
// try/catch is shown only here and is omitted in the other doc snippets.
try {
    // Get the database (and create it if it doesn't exist)
    cbl::Database database("mydb");

    // All CRUD operations must be carried out via a collection. C++ objects
    // are ref-counted, so there is no explicit release/close to remember.
    cbl::Collection collection = database.getDefaultCollection();

    // Create a new document (i.e. a record) in the database. Passing nullptr
    // gives it an auto-generated ID. 'Mutable' means its properties can change.
    cbl::MutableDocument mutableDoc(nullptr);
    mutableDoc["version"] = 3.0f;

    // Save it to the database
    collection.saveDocument(mutableDoc);

    // Keep the auto-generated ID so we can fetch the document again
    std::string id = mutableDoc.id();

    // Update a document
    mutableDoc = collection.getMutableDocument(id);
    mutableDoc["language"] = "C++";
    collection.saveDocument(mutableDoc);

    // Read it back (a cbl::Document, unlike cbl::MutableDocument, is read-only)
    cbl::Document docAgain = collection.getDocument(id);
    std::cout << "Document ID :: " << docAgain.id() << std::endl;
    std::cout << "Learning " << docAgain["language"].asstring() << std::endl;

    // Create a query to fetch documents of type SDK
    cbl::Query query(database, kCBLN1QLLanguage,
                     "SELECT * FROM _ WHERE type = \"SDK\"");
    cbl::ResultSet result = query.execute();

    // Create a replicator to push and pull changes to and from the cloud
    cbl::ReplicatorConfiguration config(
        { cbl::CollectionConfiguration(collection) },
        cbl::Endpoint::urlEndpoint("ws://localhost:4984/getting-started-db"));
    config.authenticator = cbl::Authenticator::basicAuthenticator("john", "pass");

    cbl::Replicator replicator(config);

    // Listen for replicator status changes
    auto token = replicator.addChangeListener(
        [](cbl::Replicator r, const CBLReplicatorStatus& status) {
            if (status.error.code != 0) {
                std::cerr << "Error " << status.error.domain
                          << " / " << status.error.code << std::endl;
            }
        });

    replicator.start();

    // Later, stop the replicator. Ref-counted objects free themselves once
    // the last reference goes away (here, when this scope ends).
    replicator.stop();
} catch (const cbl::Error& e) {
    // Error handling. For brevity, this is truncated here and omitted in the
    // other doc code snippets.
    std::cerr << "Error: " << e.what() << std::endl;
}
```

## [](#related-content)Related Content

###### [](#)

How to . . .

* [Install](gs-install.md)
* [Build and Run](gs-build.md)

.

###### [](#-2)

Learn more . . .

* [Databases](database.md)
* [Documents](document.md)
* [Blobs](blob.md)
* [Remote Sync Gateway](replication.md)
* [Handling Data Conflicts](conflict.md)

.

###### [](#-3)

Dive Deeper . . .

[Mobile Forum](https://forums.couchbase.com/c/mobile/14) | [Blog](https://blog.couchbase.com/) | [Tutorials](https://docs.couchbase.com/tutorials/)

.