Documentation
Local Storage & Sync

Local Storage & Sync

Plain uses a highly resilient, modern Storage Adapter System (src/storage/). The system prioritizes the most native, robust local storage method the user's browser supports.

Startup Preference Order

When Plain starts, it attempts to load storage adapters in the following order:

  1. Folder Connection: Restore a previously approved folder if the browser grants access.
  2. OPFS Storage: Fall back to browser-managed Origin Private File System (OPFS) storage when available.
  3. Legacy localStorage: Fall back to legacy string storage when newer file APIs are unavailable.

Folder-Backed Storage

If the browser supports the File System Access API, users can explicitly select a local folder on their device. Plain will treat this folder as the definitive source of truth.

Folder Layout

When a folder is selected, Plain structures the files as follows:

<chosen-folder>/
  plain-index.json
  notes/
    <note-id>.md
  trash/
    <note-id>.md

Behavior Details

  • The selected folder handle is remembered using IndexedDB.
  • If the chosen folder is empty upon selection, Plain will copy the current in-browser library into it.
  • Notes are written to disk as clean Markdown with lightweight frontmatter metadata.
  • The note title is stored as a top-level # Heading, ensuring compatibility and readability in tools like Obsidian or Typora.
  • Older .json notes and earlier HTML-in-.md notes are still supported for backwards compatibility.

Browser-Managed Storage

If the user declines folder access or the browser lacks the File System Access API, Plain stores notes internally.

OPFS (Modern Path)

The preferred fallback is the Origin Private File System (OPFS), managed under a plain-data directory. OPFS provides high-performance, sandboxed local file storage.

localStorage (Legacy Compatibility)

For older browsers, Plain relies on standard localStorage.

  • Recognized Keys:
    • plain-notes
    • plain-library
    • plain-legacy-import-complete
    • plain-theme

If older plain-notes data exists in localStorage, the sidebar can surface an import action to upgrade those legacy notes to the newer storage system.

Data Structure

Regardless of the storage engine, notes are edited in-memory as HTML strings and autosaved after a short debounce.

{
  "id": "uuid",
  "title": "My Note Title",
  "content": "<p>Saved as HTML content</p>",
  "pinned": false,
  "createdAt": 1700000000,
  "updatedAt": 1700000000,
  "trashedAt": null
}

Note: When written to Folder Storage, this HTML is converted to Markdown before saving to disk.