Skip to main content
Anchor’s mobile app is built with offline-first architecture, allowing you to work seamlessly without an internet connection. All your notes are stored locally and automatically sync when you’re back online.

How Offline Works

The app uses a local SQLite database to store all your notes, tags, and settings directly on your device. This means:
  • Create new notes offline
  • Edit existing notes offline
  • Search through your notes offline
  • Organize with tags offline
  • Archive and delete notes offline
All changes are tracked locally and automatically synced to your server when a connection is available.

Local Storage

Database Technology

Anchor uses Drift (SQLite) for local storage:
  • Persistent: Data survives app restarts
  • Fast: Instant search and retrieval
  • Reliable: ACID-compliant transactions
  • Isolated: Separate database per user account

What’s Stored Locally

Your local database contains:
  • Notes: Title, content, metadata (pinned, archived, background color)
  • Tags: Tag names, colors, and note associations
  • State: Sync status, last modified timestamps
  • Relationships: Note-tag mappings, sharing information
Authentication tokens are stored securely using Flutter Secure Storage, separate from the notes database.

Storage Location

Data is stored in your device’s application documents directory:
/data/data/com.anchor.mobile/app_flutter/db_[user_id].sqlite
Each user account has a separate database file, allowing you to switch between accounts without data conflicts.

Creating Notes Offline

When you create a note without internet:
1

Create Note

Tap the + button and create your note as usual. The note is immediately saved to your local database.
2

Local UUID

The app generates a unique ID (UUID) for the note locally. This ID remains the same when synced to the server.
3

Sync Flag

The note is marked as “unsynced” in the local database, indicating it needs to be sent to the server.
4

Auto-Sync

When you reconnect, the app automatically syncs the note to your server in the background.

Editing Notes Offline

Editing works the same offline as online:
  1. Open any note from your local database
  2. Make changes to title, content, tags, or formatting
  3. Changes are saved locally with updated timestamps
  4. Sync flag is set to trigger server update when online
There’s no visual difference between editing online and offline. The app handles sync transparently.

Automatic Synchronization

Anchor uses bidirectional sync to keep your data consistent:

When Sync Happens

Sync is triggered automatically:
  • On connect: When internet connection is restored
  • After changes: When you create, edit, or delete a note
  • On app launch: When you open the app while online
  • Periodic: Background sync while the app is open and online

Sync Process

1

Detect Connection

The app uses the connectivity_plus package to monitor network status.When connection is restored, the sync manager is notified automatically.
2

Sync Tags First

Tags are synced before notes to ensure tag IDs are resolved correctly.This prevents issues where a note references a tag that doesn’t exist on the server yet.
3

Send Local Changes

All unsynced notes are sent to the server:
{
  "lastSyncedAt": "2026-03-01T10:30:00Z",
  "changes": [
    {
      "id": "note-uuid",
      "title": "My Note",
      "content": "[{\"insert\":\"Note content\"}]",
      "isPinned": false,
      "isArchived": false,
      "state": "active",
      "tagIds": ["tag-uuid"],
      "updatedAt": "2026-03-01T12:15:00Z"
    }
  ]
}
4

Receive Server Changes

The server responds with:
  • Notes modified on the server since last sync
  • Notes shared with you by other users
  • Revoked sharing permissions (notes removed from your access)
  • Deleted notes (tombstones)
  • New sync timestamp
5

Resolve Conflicts

If the same note was modified both locally and on the server:
  • Compare timestamps (updatedAt)
  • Server wins if timestamps are equal or server is newer
  • Local changes are overwritten to maintain server as source of truth
Avoid editing the same note on multiple devices simultaneously. The latest change based on server time wins.
6

Update Local Database

Server changes are applied to your local database:
  • New notes are inserted
  • Updated notes overwrite local versions
  • Deleted notes are removed
  • Sync flags are cleared for successfully synced notes

Manual Sync

You can manually trigger sync:
  1. Pull down on the notes list to refresh
  2. The app will sync immediately if you’re online

Offline Features

Full Functionality

These features work completely offline:
  • Create, edit, and delete notes
  • Add and remove tags
  • Pin and unpin notes
  • Archive and unarchive notes
  • Move notes to trash and restore them
  • Search notes by title and content
  • Format text with rich text editor
  • Change note background colors
  • View note edit history (local changes)

Limited Functionality

These features require internet connection:
  • Sharing notes: Requires server to manage permissions
  • User search: Needs server to look up other users
  • Profile updates: Syncs to server for other users to see
  • OIDC authentication: Requires identity provider connection

Offline Indicators

The app shows your connection status:
  • No indicator: You’re online and synced
  • Sync icon: Sync in progress
  • Warning: Sync failed (will retry automatically)
The app is designed to feel the same whether you’re online or offline. There’s no degraded experience.

Data Persistence

App Restart

Your data persists across app restarts:
  • Close the app with unsaved changes
  • Reopen the app
  • All changes are still there, waiting to sync

Cache Management

The app doesn’t use a traditional cache that expires:
  • All notes are considered primary data, not cached
  • Data only changes through sync or user actions
  • No automatic data deletion

Storage Limits

The only limit is your device’s available storage:
  • SQLite databases can grow very large (gigabytes)
  • Rich text content is stored efficiently
  • Images are referenced by URL, not embedded

Conflict Resolution

Timestamp-Based Resolution

Conflicts are resolved using timestamps:
if (serverUpdatedAt.isAfter(localUpdatedAt) || 
    serverUpdatedAt.isAtSameMomentAs(localUpdatedAt)) {
  // Server wins
  updateLocalNote(serverNote);
}

Conflict Scenarios

Scenario 1: Edit on phone while offline
  • You edit a note at 2:00 PM
  • Server was last synced at 1:00 PM
  • When you sync, your changes go to the server
Scenario 2: Edit on two devices
  • You edit on phone at 2:00 PM
  • You edit on web at 2:05 PM
  • When phone syncs, server’s 2:05 PM version wins
  • Your 2:00 PM changes are lost
There is no merge strategy. The last edit wins. Avoid editing the same note on multiple devices without syncing in between.

Deleted Notes

When a note is deleted:
  1. It’s marked as state: 'deleted' (tombstone)
  2. Tombstone syncs to server
  3. Server confirms deletion
  4. Local tombstone is removed from database
This ensures deletions propagate to all devices.

Sync Failure Handling

If sync fails (network error, server down, etc.):
  • Changes remain marked as unsynced
  • Sync will retry on next connection event
  • No data is lost
  • You can continue working offline

Retry Strategy

The app automatically retries sync:
  • When connectivity is restored
  • When app returns to foreground
  • After any new local changes
  • No exponential backoff (immediate retry)

Multi-Account Support

Each user account has isolated storage: When you switch accounts:
  • Previous account’s database is closed
  • New account’s database is opened
  • No data mixing between accounts

Privacy and Security

Local Encryption

Note content in the SQLite database is not encrypted by default. The database is protected by:
  • Android/iOS app sandboxing
  • Device-level encryption (if enabled)
  • Secure storage for authentication tokens
On a rooted/jailbroken device, the database could be accessed. Keep your device secure and use device encryption.

Authentication Tokens

JWT tokens are stored separately using flutter_secure_storage:
  • Encrypted using platform keychain (iOS) or Keystore (Android)
  • Not accessible to other apps
  • Wiped when app is uninstalled

Clearing Local Data

To delete all local data:
  1. Open Settings
  2. Scroll to Account section
  3. Tap Sign Out
  4. Choose Sign out and delete local data
This permanently deletes all local notes. Ensure you’ve synced before clearing data, or your unsynced changes will be lost.
Alternatively, uninstalling the app removes all data:
# Android
adb uninstall com.anchor.mobile

Best Practices

Maximize Offline Reliability

  1. Sync regularly: Open the app while online to keep data fresh
  2. Avoid conflicts: Don’t edit the same note on multiple devices
  3. Check sync status: Ensure notes sync before switching devices
  4. Keep app updated: Updates improve sync reliability

Troubleshooting Sync Issues

Notes not syncing:
  • Check internet connection
  • Verify server is reachable
  • Pull down to manually trigger sync
  • Check server logs for errors
Lost changes:
  • Likely due to conflict resolution (server won)
  • Check note’s “Updated” timestamp
  • Avoid editing on multiple devices simultaneously
Database corruption:
  • Extremely rare with SQLite
  • Sign out and re-sync from server
  • Report issue if persistent

Technical Details

Dependencies

Offline functionality uses:
  • Drift: SQLite ORM and query builder
  • sqlite3_flutter_libs: Native SQLite library
  • path_provider: Find database storage location
  • connectivity_plus: Monitor network status
  • flutter_secure_storage: Encrypted token storage

Database Schema

The notes table structure:
CREATE TABLE notes (
  id TEXT PRIMARY KEY,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  isPinned BOOLEAN NOT NULL DEFAULT FALSE,
  isArchived BOOLEAN NOT NULL DEFAULT FALSE,
  background TEXT,
  state TEXT NOT NULL DEFAULT 'active',
  updatedAt DATETIME,
  permission TEXT NOT NULL DEFAULT 'owner',
  shareIds TEXT,
  sharedById TEXT,
  sharedByName TEXT,
  sharedByEmail TEXT,
  sharedByProfileImage TEXT,
  isSynced BOOLEAN NOT NULL DEFAULT FALSE
);

Sync Endpoint

The sync API endpoint:
POST /api/notes/sync
See the source code in lib/features/notes/data/repository/notes_repository.dart:345 for implementation details.

Next Steps

Learn more about using Anchor’s mobile app:

Rich Text Editing

Format notes with the Flutter Quill editor

Tags & Organization

Organize notes with tags and search

Build docs developers (and LLMs) love