# Noteable — AI Coding Guide

> Read this file before inspecting, planning, or changing this repository. It provides project context, coding conventions, architecture, and safety rules for AI coding assistants.
>
> **Source-of-truth rule:** This guide documents intended architecture and known conventions; it does not prove that every uploaded snapshot is current or complete. Inspect actual files before editing. If this guide conflicts with source code, identify the conflict and inspect the implementation rather than silently making broad changes.

## 1. Project overview

**Noteable** is a cross-platform Flutter note-taking and knowledge-management app. The repository contains a Flutter client and a Node.js/MariaDB backend.

Capabilities represented in the source include notes and rich-text editing, tags/note types, checklists, reminders, relations/history, boards and columns/cards, local-first storage and sync queues, account login and server sync, import/export, images and text scanning, Windows desktop widgets/tray/reminders, Android home-screen widgets/overlay services, and Arabic/English text with RTL handling. Check actual platform implementations; do not assume every feature works the same on every platform.

## 2. Stack

Read `pubspec.yaml`, `noteable-server/package.json`, and lockfiles before changing dependencies. The client uses Flutter/Dart, Drift/SQLite, `sqlite3` with the `sqlite3mc` hook, `flutter_quill`, `shared_preferences`, `flutter_secure_storage`, `http`, `path_provider`, `window_manager`, `tray_manager`, `home_widget`, notifications/timezone packages, ML Kit text recognition, file/image pickers, and UUID. The server uses Node.js, MariaDB, and pnpm. Verify actual SDK and dependency versions from current files; do not upgrade packages incidentally.

## 3. Key source tree

```text
/
├── AGENTS.md                         # This AI guide
├── pubspec.yaml                      # Flutter SDK/dependencies/configuration
├── lib/
│   ├── main.dart                     # Entry point/platform startup
│   ├── app.dart                      # App/root configuration
│   ├── core/                         # Constants, theme, text-direction utilities
│   ├── database/
│   │   ├── app_database.dart         # Drift schema, DB initialization/migrations
│   │   ├── app_database.g.dart       # Generated: do not edit manually
│   │   ├── tables/                   # Drift table declarations
│   │   └── dao/                      # DAOs and generated companions
│   ├── models/                       # Domain/data models
│   ├── repositories/                 # Note, board, relation, reminder, tag operations
│   ├── screens/                      # Pages, editors, login, board and widget windows
│   ├── services/                     # API, auth, sync, files, images, widgets, reminders
│   └── widgets/                      # Reusable UI components
├── android/app/src/main/             # Android Kotlin, manifests, widgets/resources
├── noteable-server/
│   ├── package.json                  # Server dependencies/scripts
│   ├── src/server.js                 # HTTP server/routes
│   ├── src/db.js                     # MariaDB pool/connection setup
│   ├── src/logger.js                 # Structured logging
│   ├── src/middleware/auth.js        # Auth middleware
│   ├── src/routes/auth.js            # Login/registration/password routes
│   ├── src/routes/devices.js         # Device registration
│   ├── src/routes/sync.js            # Note synchronization
│   ├── src/routes/note_types.js      # Note-type synchronization
│   ├── src/routes/board_sync.js      # Board synchronization
│   └── migrations/Noteable_fresh_install.sql
├── windows
```

The uploaded project snapshot may omit folders such as `windows/`, assets, tests, or local configuration. Use the actual folder tree as the definitive inventory; never claim to have inspected files that were not supplied.

### Where to start

| Task | Inspect first |
|---|---|
| Notes/editor/home | `lib/screens/note_editor_screen.dart`, `home_screen.dart`, relevant note models/repositories/widgets |
| Local DB/schema | `lib/database/app_database.dart`, `database/tables/`, `database/dao/`, repositories |
| Sync | `lib/services/sync_manager.dart`, `sync_service.dart`, `sync_api_service.dart`, sync queue DAOs, server routes |
| Login/session | `lib/services/auth_service.dart`, `login_screen.dart`, `api_config.dart`, all secure-storage usages |
| Device registration | `lib/services/device_api_service.dart`, `device_service.dart`, server `routes/devices.js` |
| API/database errors | `lib/services/api_config.dart`, server `src/db.js`, `server.js`, relevant route |
| Boards/Kanban | `lib/screens/board_views.dart`, board repository/DAOs/tables, `routes/board_sync.js` |
| Tags/note types | `lib/screens/tags_page.dart`, `note_tag_service.dart`, note-type DAO/service/route |
| Quill/checklists/images | `note_editor_screen.dart`, Quill widgets/models, `note_image_service.dart` |
| Windows startup/widgets/tray | `lib/main.dart`, desktop widget services/storage/state service and related screens |
| Android widgets/overlay | `android/app/src/main/`, `lib/services/android_edge_widget_service.dart` |
| Import/export | Relevant import/export services in `lib/services/` |

## 4. Architecture and data flow

Preferred pattern:

```text
Screen/Widget → Repository or focused Service → DAO/Drift database
                                      └──────→ API client/HTTP → Node routes → MariaDB
```

- Preserve the existing architecture; do not add a parallel data-access layer without a reason.
- Keep UI code free of duplicated SQL/network/persistence logic when an existing repository or service owns it.
- Local data is important. Preserve local-first behavior unless the user explicitly asks otherwise.
- Sync queues, revisions, conflict handling, and soft-deletion semantics are part of the data model. Do not bypass them when modifying synced data.
- Keep client and server IDs, payload fields, operation names, and response shapes consistent. Inspect both sides for API changes.

## 5. Coding rules

1. **Inspect before editing:** read the target file, its callers, related models/services/DAOs, and tests if present. Search all uses of a changed field, preference key, database table, API route, or method.
2. **Make the smallest complete change:** avoid unrelated rewrites, renames, folder reorganizations, and opportunistic cleanup.
3. **Preserve behavior:** keep navigation, keyboard/mouse interactions, localization, RTL, accessibility, and platform-specific behavior unless explicitly asked to change them.
4. **Follow Dart conventions:** files `lower_case_with_underscores.dart`, types `UpperCamelCase`, methods/variables `lowerCamelCase`. Follow nearby style and format edited files.
5. **Reuse existing code:** prefer existing constants, utilities, models, repositories, services, and error handling over duplicate logic.
6. **Async safety:** handle loading/errors, check widget lifecycle before using `BuildContext` after `await`, and avoid unhandled async failures.
7. **Do not swallow errors:** use existing UI/logging paths. Never log passwords, tokens, secrets, or private note content.
8. **Avoid unnecessary dependencies and broad formatting churn.** Check existing packages first.
9. **Be honest about verification:** never claim analysis, tests, or builds passed unless actually run. State unavailable checks and give commands for the user to run.

## 6. Database and migrations — critical

- Drift schema is defined in `lib/database/app_database.dart` and `lib/database/tables/`; DAOs are under `lib/database/dao/`.
- **Never edit `.g.dart` files by hand.** Edit source declarations and regenerate generated code when needed.
- Schema changes require reviewing the current schema version and adding a correct migration in `app_database.dart`. Do not silently reset a user's database.
- SQLite is configured for encryption support via `sqlite3mc` in `pubspec.yaml`. Before changing initialization, inspect database factory, key loading/storage, and encryption configuration.
- Preserve user notes. Back up important data before path, encryption, schema, or migration changes. Do not delete a database as the first troubleshooting step.
- `SqliteException(26): file is not a database` may mean wrong path/file, invalid file, or encryption/key mismatch. Verify the resolved path and initialization before attempting recovery.
- Keep database files separate from preferences, widget state, exported files, and server database configuration.
- `noteable-server/migrations/Noteable_fresh_install.sql` is for fresh installation unless reviewed and adapted as a migration. Do not run it against populated production/test data without a backup and explicit migration plan.

Useful commands from the Flutter project root:

```powershell
flutter pub get
dart format lib/path/to/edited_file.dart
flutter analyze
flutter test
dart run build_runner build --delete-conflicting-outputs
```

Run code generation only when relevant generated files need updating; verify SDK compatibility first.

## 7. Authentication, API, and environment isolation

- API configuration: `lib/services/api_config.dart`; auth/session: `lib/services/auth_service.dart`.
- Intended endpoints: release API `https://noteable.anas4tech.com`; Windows debug/test API `https://test.noteable.anas4tech.com`. **Inspect current code/build flags before assuming this configuration is implemented.**
- Requirement: Debug and Release have separate local session storage, but may log in to the same server account. Logging in or out of Debug must not overwrite or clear Release's session.
- Separate sessions at the secure-storage namespace/key layer without changing Release keys or server account data. Check actual `flutter_secure_storage` plugin/platform behavior: a prefixed key may not fully isolate storage if the platform/plugin uses shared native storage.
- Do not direct all builds to the test API. Environment selection must be explicit and preserve production release behavior.
- Never commit or expose passwords, tokens, signing keys, certificates, service-account JSON, or environment secrets.
- A client HTTP 500 does not by itself prove a Flutter bug. Correlate the request with backend logs before changing the client.
- A MariaDB `ER_GET_CONNECTION_TIMEOUT` with `active=0 idle=0` means the pool could not supply/create a connection. Inspect host, port, credentials, reachability, DB availability, connection limits, and pool initialization before blindly increasing the pool limit.

## 8. Notes, rich text, files, and images

- `flutter_quill` content is stored as Quill Delta JSON. Preserve this representation when loading/saving notes; do not convert it to plain text unless requested.
- Checklists, reminders, relations, tags/note types, boards, and sync queues have their own models/tables/services. Inspect current representation before changing serialization.
- Use existing file/image services for attachment paths and copy/move behavior. A stored path is not necessarily a URL.
- Import/export formats are compatibility surfaces. If model/serialization changes, inspect and update affected import/export services and tests.
- Preserve title defaults, rich-text body, checklist semantics, and sync metadata unless the request requires a change.

## 9. Windows and Android behavior

- Windows startup, tray, widget restoration, and reminder scheduling have platform-specific flows. Inspect `main.dart` and desktop services before changing startup.
- Debug must not overwrite/remove the Release startup shortcut or accidentally share local state. If launching secondary windows/processes, inspect arguments and process matching so Debug does not control Release processes.
- Windows runner files live under `windows/` in a complete Flutter project. If absent from the uploaded source, do not claim native runner changes were inspected or made.
- Android widgets/overlay depend on Kotlin, manifests, and XML resources. Dart-only changes may not be enough.

## 10. Localization and UI

- Preserve Arabic/English support and correct RTL behavior in layout, text, icons, selection, drag/drop, and hit targets.
- Visual mirroring does not guarantee interaction hit-testing is correct. Test controls in both LTR and RTL.
- Reuse the existing theme and widgets instead of scattering hardcoded styles.
- Test actual interactions, not only appearance: taps, dragging, checkbox hit targets, keyboard input, dialogs, and navigation.

## 11. Backend rules

- Inspect `src/db.js`, auth middleware, the target route, and `logger.js` before changing server behavior.
- Use parameterized SQL; never interpolate user-provided values into SQL.
- Preserve authorization checks for protected routes.
- Do not return raw stack traces, SQL, secrets, or internal filesystem paths to clients. Keep diagnostics in server logs.
- Keep the Flutter client contract aligned with server request/response payloads.
- Use test/staging for validation when possible. Correlate `requestId`, route, timestamp, and error event when debugging.

## 12. Workflow for every AI task

### Before editing
1. Translate the request into specific expected behavior.
2. Scan the relevant tree and inspect current implementation.
3. Identify related callers, data models, persistence, API, and platform-specific code.
4. For non-trivial work, list files to change and why.
5. Identify risks to data, migrations, authentication, security, and release behavior.

### While editing
1. Make focused changes following established patterns.
2. Update tests/generated code only as appropriate.
3. Keep Debug/Release and test/production boundaries intact.
4. Do not silently change schema, API contracts, or storage paths.

### After editing
1. Review the diff and search for affected references.
2. Run available formatter/analyzer/tests/builds.
3. List exactly which files changed.
4. Report commands actually run and results; identify checks not run.
5. Provide concise manual verification steps for behavior that cannot be tested in the current environment.

## 13. Known cautions

- Uploaded archives may be incomplete or older than the user's working tree. Inspect current files and do not infer that omitted files do not exist.
- Do not guess schema, auth key names, payload fields, route contracts, widget behavior, or file paths; read source first.
- If a necessary file is missing, ask for that specific file instead of fabricating a replacement.
- If the user requests **only edited files**, provide only those files rather than an unrelated full-project archive.
- Protect user data first; prefer reversible changes and explain any operation that may reset local data.
