Ponder

Architecture Overview

System architecture for the Flutter client, Appwrite backend, and repository layering.

Runtime Shape

Ponder is a Flutter Material 3 application initialized in lib/main.dart and assembled by PonderApp in lib/app.dart. The app loads .env, initializes Sentry, optionally starts New Relic Mobile when an iOS or Android token is provided through .env or Dart defines, creates a Riverpod ProviderScope, and uses MaterialApp.router with the router from routerProvider.

The backend is Appwrite. The repository uses Appwrite Auth, TablesDB, Functions, and Storage. appwrite.json declares the backend contract and lib/core/constants/appwrite_config.dart declares the IDs consumed by Flutter.

Layers

| Layer | Code area | Responsibility | | — | — | — | | UI | lib/features/**/screens, lib/shared/widgets | Screens, user input, presentation, modal sheets, and navigation calls. | | State | lib/features/**/providers, lib/core/providers | Riverpod providers/notifiers, async state, cache invalidation, local preference state. | | Services and repositories | lib/core/services, lib/features/**/services | Business logic, Appwrite queries, function execution, profile image upload, encryption-aware chat orchestration. | | Backend access | TablesService, Appwrite SDK providers | TablesDB REST calls, Account, Databases, Functions, Storage clients. | | Backend runtime | functions/** | Scheduled content ingestion, fact-check execution, chat writes, like-count synchronization. |

Widgets do not contain direct database logic. The active pattern is widget -> provider/notifier -> service/repository -> TablesService or Appwrite SDK client.

Client Entry Points

Monitoring

lib/core/monitoring wraps New Relic behind a conditional adapter so non-mobile targets remain no-op safe. The app records auth context, route breadcrumbs, Appwrite table/function operation timings, critical-flow events, and selected handled errors without sending sensitive content such as email addresses, chat bodies, article bodies, fact-check claim text, print statements, or HTTP response bodies.

Backend Access

AppwriteConfig reads APPWRITE_ENDPOINT and APPWRITE_PROJECT_ID from .env; missing values throw a StateError. The database ID is ponder_db. Table IDs and function IDs are constants.

appwrite_service.dart exposes Riverpod providers for:

TablesService wraps Appwrite TablesDB REST endpoints under /tablesdb/{databaseId}/tables/{tableId}/rows and exposes listRows, getRow, createRow, updateRow, and deleteRow.

Feature Modules

Backend Contract

The active Appwrite backend declares:

Compatibility Notes

The Flutter and function code retain compatibility for older chat schemas. Threads prefer pairKey but still write contentId as dm:{sortedParticipantIds}. Thread messages prefer type and contentId but can encode article shares in the legacy body prefix __ponder_article__: when the deployed schema does not support typed columns.