{"id":45157446,"url":"https://github.com/couchbase-examples/flutter_cbl_learning_path","last_synced_at":"2026-02-20T05:02:51.211Z","repository":{"id":89742048,"uuid":"526866895","full_name":"couchbase-examples/flutter_cbl_learning_path","owner":"couchbase-examples","description":"Learn Couchbase Lite SDK with Dart and Flutter for Mobile and Desktop Developers","archived":false,"fork":false,"pushed_at":"2024-02-09T16:01:27.000Z","size":7573,"stargazers_count":7,"open_issues_count":1,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-05-02T02:25:28.877Z","etag":null,"topics":["couchbase-lite","couchbase-mobile","dart","flutter","flutter-app","flutter-examples"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/couchbase-examples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-08-20T08:18:42.000Z","updated_at":"2024-03-16T18:44:16.000Z","dependencies_parsed_at":"2024-02-08T00:45:49.260Z","dependency_job_id":null,"html_url":"https://github.com/couchbase-examples/flutter_cbl_learning_path","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/couchbase-examples/flutter_cbl_learning_path","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase-examples%2Fflutter_cbl_learning_path","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase-examples%2Fflutter_cbl_learning_path/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase-examples%2Fflutter_cbl_learning_path/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase-examples%2Fflutter_cbl_learning_path/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/couchbase-examples","download_url":"https://codeload.github.com/couchbase-examples/flutter_cbl_learning_path/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/couchbase-examples%2Fflutter_cbl_learning_path/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29641929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T03:21:14.183Z","status":"ssl_error","status_checked_at":"2026-02-20T03:18:24.455Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["couchbase-lite","couchbase-mobile","dart","flutter","flutter-app","flutter-examples"],"created_at":"2026-02-20T05:02:41.737Z","updated_at":"2026-02-20T05:02:51.204Z","avatar_url":"https://github.com/couchbase-examples.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learn Couchbase Lite with Dart and Flutter \n\nIn this learning path you will be reviewing an Android and iOS Application written in Dart and Flutter that uses the community Couchbase Lite SDK for Dart and Flutter. You will learn how to get and insert documents using the key-value engine, query the database using the QueryBuilder engine or SQL++, and learn how to sync information between your mobile app and either a Couchbase Server using Sync Gateway or using peer-to-peer technology.\n\nFull documentation can be found on the [Couchbase Developer Portal](https://developer.couchbase.com/learn/).\n\n\u003e**Note**:  The \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://github.com/cbl-dart/cbl-dart\"\u003eDart SDK for Couchbase Lite\u003c/a\u003e is a community based project on GitHub and is not officially supported by Couchbase.  If you have questions or issues with the SDK, please \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://github.com/cbl-dart/cbl-dart/discussions\"\u003epost them on the GitHub project\u003c/a\u003e.\n\n## Prerequisites\n\nBefore you get started you should take the following prerequisites into consideration:\n\n- Familiarity with building \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://dart.dev/\"\u003eDart\u003c/a\u003e and \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://flutter.dev\"\u003eFlutter\u003c/a\u003e Apps\n- Familiarity with \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://bloclibrary.dev/\"\u003eBloc\u003c/a\u003e and \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://bloclibrary.dev/#/architecture\"\u003estatement management patterns\u003c/a\u003e in Flutter\n- Android SDK installed and setup (\u003e v.32.0.0)\n- Android Build Tools (\u003e v.32.0.0)\n- XCode 13 or later installed and setup \n- Android device or emulator running API level 23 (Android 6.0 Marshmallow) or above\n- iOS device or simulator setup for iOS 14 or later\n- IDE of choice (IntelliJ, Android Studio, VS Code, etc.)\n- Flutter \u003e 3.0 installed, setup, and configured for your IDE of choice\n\n- curl HTTP client \n  * You could use any HTTP client of your choice. But we will use *curl* in our tutorial. Mac OS Package Manager users can use \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://brew.sh/\"\u003ehomebrew\u003c/a\u003e. Windows Package Manager users can use \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.microsoft.com/en-us/windows/package-manager/winget/\"\u003ewinget\u003c/a\u003e. \n\n## Demo Application \n\n### Overview\n\nThe demo application used in this learning path is based on auditing \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://en.wikipedia.org/wiki/Inventory\"\u003einventory\u003c/a\u003e in various warehouses for a fictitious company.  Most companies have some inventory - from laptops to office supplies and must audit their stock from time to time. For example, when a user's laptop breaks, the Information Technology department can send out a replacement from the inventory of spare laptops they have on hand. In this app, the items we are auditing are cases of beer.  \n\nUsers running the mobile app would log into the application to see the projects they are assigned to work on. Then, the user would look at the project to see which warehouse they need to travel to. Once at the warehouse, they would inspect the number of cases of beer, tracking them in the mobile application.  Finally the data can be synced back to the server for use with other analytical data.\n\n### Architecture\n\nThe demo application uses \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://bloclibrary.dev/#/\"\u003ebloc\u003c/a\u003e, a very popular \u003ca target=\"_blank\" rel=\"noopener noreferrer\"  href=\"https://bloclibrary.dev/#/architecture\"\u003estatement management pattern\u003c/a\u003efor Dart. \n\nBloc is used to manage dependency inversion, injection, and state management.  Repositories and Services are registered using Bloc's \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://pub.dev/documentation/flutter_bloc/latest/flutter_bloc/MultiRepositoryProvider-class.html\"\u003eMultiRepositoryProvider\u003c/a\u003e.  The sample application is broken down into features which can be found in the src/lib/features directory.\n\nThe \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/database/database_provider.dart\"\u003eDatabase Provider\u003c/a\u003e, found in the src/lib/features/database/ diretory, is a custom class that manages the database state and lifecycle.  Querying and updating documents in the database is handled using the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://bloclibrary.dev/#/architecture?id=repository\"\u003erepository pattern\u003c/a\u003e.  Blocs will query or post updates to the repository and control the state of objects that the Flutter widgets can use to display information. \n\n### Application Flow\n\nThe application structure starts with the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/main.dart#L15\"\u003emain function\u003c/a\u003e.  It creates an \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/inventory_audit_app.dart#L16\"\u003eInventoryAuditApp\u003c/a\u003e that is a Stateless Widget and sets up all repositories and services using \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/inventory_audit_app.dart#L47\"\u003eMultiRepositoryProvider\u003c/a\u003e.  The \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/router/bloc/route_bloc.dart#L10 \"\u003eRouteBloc\u003c/a\u003e defined is used to handle all routing calls.  This bloc defines a child, \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/app_view.dart#L13\"\u003eAppView\u003c/a\u003e, which is a stateful widget that uses a MultiBlocListern to react to changes in the route state and thus render new screens as requested.  \n\nThe default state of the app is for the user to not be authenticated, which will call the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/views/login_screen.dart\"\u003eLoginScreen\u003c/a\u003e widget to render.  LoginScreen uses a \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://pub.dev/documentation/flutter_bloc/latest/flutter_bloc/BlocProvider-class.html\"\u003eBlocProvider\u003c/a\u003e to inject \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/bloc/login_bloc.dart\"\u003eLoginBloc\u003c/a\u003e into the render tree which defines \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/views/login_form.dart#L6\"\u003eLoginForm\u003c/a\u003e as a child to render the UI.  When a user taps the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/views/login_form.dart#L130\"\u003e_LoginButton\u003c/a\u003e, the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/bloc/login_event.dart#L28\"\u003eLoginSubmitted\u003c/a\u003e event is added to LoginBloc, which runs the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/login/bloc/login_bloc.dart#L47\"\u003e_onSubmitted\u003c/a\u003e method to update state with if the user logged in properly or not.  If the user is authenticated properly the state is updated and the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/app_view.dart#L57\"\u003eBlocListner for RouteState\u003c/a\u003e will push the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/project/views/project_list_screen.dart#L12\"\u003eProjectListScreen\u003c/a\u003ewidget to the render tree.  \n\nThe user can use the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/drawer/views/menu_drawer.dart#L7\"\u003emenu drawer\u003c/a\u003e to navigate to other sections of the app or use the Floating Action button to \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/featu\"\u003eadd a new Project\u003c/a\u003e.\n\n### Replication\n\n#### Couchbase Capella App Services Users\nIt's highly recommended to follow the full documentation on the [Couchbase Developer Portal](https://developer.couchbase.com/learn/).  An overview of the steps using the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/mobile-guides/intro.html\"\u003eCouchbase Capella\u003c/a\u003e documentation is provided below:\n\nThe steps below will guide you through the following:\n * Setup an App Endpoint under your App Services in Couchbase Capella named `projects` \n * Update your import and sync functions\n * Create App Roles and App Users\n * Copy the URL of the App Endpoint\n * Download the App Endpoint Public Certificate file\n * Update the app to use the public certficate and URL information to connect to Couchbase Capella App Services to sync documents between the mobile app and App Services.  \n\n1. Create an endpoint called projects using the documentation found  \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/app-services/deployment/creating-an-app-endpoint.html\"\u003ehere\u003c/a\u003e.\n  * **NOTE** Use the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/capella/import.js\"\u003eimport.js\u003c/a\u003e file in the Import Filter section of the documentation.\n2. You will need to update the Access Control and Validation for the App Endpoint usng documentation you can find \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/app-services/deployment/access-control-data-validation.html\"\u003ehere\u003c/a\u003e.\n  * **NOTE** Use the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/capella/sync.js\"\u003esync.js\u003c/a\u003e file in the second step under Security \u003e Access and Validation.\n3. You will need to add the roles for the users using the documentation found \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/app-services/user-management/create-app-role.html\"\u003ehere\u003c/a\u003e.\n * You will need to create roles `team1` through `team15` with the same channel name as the role name.  These are assigned to the user in the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/router/service/auth_service.dart#L67\"\u003eauth_services.dart\u003c/a\u003e file and must must match this file or you will get a 403 error when trying to replicate.\n4. You will need to create sample users using the documentation found \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/app-services/user-management/create-user.html\"\u003ehere\u003c/a\u003e.\n  * You will need to create users `demo@example.com` through `demo15@example.com` same roles as found in the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/router/service/auth_service.dart#L67\"\u003eauth_services.dart\u003c/a\u003e file.  If the user isn't added to the proper role, you will have issues when trying to replicate documents.\n5. From the App Services Endpoint section of Couchbase Capella, click on the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://docs.couchbase.com/cloud/app-services/connect/connect-apps-to-endpoint.html\"\u003eConnect tab\u003c/a\u003e.\n6.  You will need to write down the `Public Connection` URL that is provided on this page so we can update the hostname in the `replicator_provider.dart` file in a later step.\n7.  Download the Public Certificate file.  The dart SDK doesn't include the App Services certificate, so you will need to provide it in the app and then `pin it` in the replication configuration.  You can click the Download button under Public Certificate which should download a cert.pem file.\n8.  Add the .pem file (certificate) to the src folder.  It should be at the same folder structure level as your \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/pubspec.yaml\"\u003epubspec.yaml\u003c/a\u003e file. \n9.  Update the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/pubspec.yaml#L43\"\u003esrc/pubspec.yaml\u003c/a\u003e file to include the certificate file.  Note it's YAML so the spacing is important.  An example of what the file file should look like after this change is provided below:\n```yaml\n  assets:\n    - asset/images/couchbase.png\n    - asset/database/startingWarehouses.zip\n    - cert.pem\n```  \n10. Open the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/database/replicator_provider.dart\"\u003ereplicator_provider.dart\u003c/a\u003e file found in the src/lib/features/database directory.\n11. Uncomment \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/database/replicator_provider.dart#L82\"\u003eline 82\u003c/a\u003e that will load the pem file that you added in `step 5` and put in the YAML file in `step 6`\n```dart\nvar pem = await rootBundle.load('cert.pem');\n```\n12. Update \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/database/replicator_provider.dart#L87\"\u003eline 87\u003c/a\u003e with the hostname part of your URL that you got from `step 3`.  Note you have to remove the `endpoint` name from the url to get the hostname.  It should look similar to this:\n```dart\n  var url = Uri(scheme: 'wss',\n        port: 4984,\n        host: 'your_account_hostname.apps.cloud.couchbase.com',             \n        path: 'projects',\n      );\n```  \n13.  Uncomment out \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/database/replicator_provider.dart#L103\"\u003eline 103\u003c/a\u003e in order to load the PEM file as a pinned certificate.  This will allow the device to trust the connection between App Services and the mobile device.  Your code should look like this when done:\n```dart\n      _replicatorConfiguration = ReplicatorConfiguration(\n          database: db,\n          target: endPoint,\n          authenticator: basicAuthenticator,\n          continuous: true,\n          replicatorType: ReplicatorType.pushAndPull,\n          heartbeat: const Duration(seconds: 60),\n          // **UNCOMMENT** this the line below if you are using App Services or a custom certificate\n          pinnedServerCertificate: pem.buffer.asUint8List()\n        );\n```\n14.  Open the \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/router/bloc/route_bloc.dart#L110\"\u003esrc/lib/features/router/bloc/route_bloc.dart\u003c/a\u003e file \n15.  Uncomment out \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://github.com/couchbase-examples/flutter_cbl_learning_path/blob/main/src/lib/features/router/bloc/route_bloc.dart#L110\"\u003eline 110\u003c/a\u003e so it enables the replicator to initalize once the user logs into the app.\n\n```dart\n  await _replicatorProvider.init();\n```\n16.  You should be able to now debug the app and replication should start working.  Any documents found on Couchbase Server will be replicated to the mobile device and any documents created on the mobile device will be replicated to the server.  You can use the Couchbase Server UI to see the documents that are being replicated.\n\n### Try it out\n\n* Open src folder using your favorite IDE\n* Build and run the project.\n* Log in to the app with  **_\"demo@example.com\"_** and **_\"P@ssw0rd12\"_** for user Id and password fields respectively.\n\n## Community Documentation\n\nThe Dart and Flutter community documentation can be found \u003ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https://cbl-dart.dev/\"\u003ehere\u003c/a\u003e.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcouchbase-examples%2Fflutter_cbl_learning_path","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcouchbase-examples%2Fflutter_cbl_learning_path","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcouchbase-examples%2Fflutter_cbl_learning_path/lists"}