Projects

Khazna — Pocket Vault for Links, Notes & Lists

2026·8 min read

React Native
Expo
TypeScript
NativeWind
Zustand
Coming soon to Play

Khazna (خزنة, "vault") is a private, offline pocket vault for links, notes and checklists — one input that works out which of the three you pasted, a capture flow measured in about a second, app lock behind your fingerprint, and no server, no account and no sync behind any of it. Built with Expo SDK 57, React Native 0.86 and TypeScript, Arabic-first with a full right-to-left layout.

Khazna — Pocket Vault for Links, Notes & Lists preview

Khazna (خزنة, "vault") is a private, offline pocket vault for links, notes and checklists — one input that works out which of the three you pasted, a capture flow measured in about a second, app lock behind your fingerprint, and no server, no account and no sync behind any of it. Built with Expo SDK 57, React Native 0.86 and TypeScript, Arabic-first with a full right-to-left layout.

Khazna — a pocket vault for links, notes and checklists

Khazna (خزنة) is Arabic for vault — the small kind, the one in the room rather than the bank. Somewhere to put the link you found at midnight and the four things to pack, that is quick to reach and yours alone.

Download

Coming soon to Google Play. Android-first, Arabic and English, light and dark, free, no ads.

The signed bundle builds locally through pnpm release:aab, which bumps the version code, prebuilds clean so the native project matches app.json, forces all four ABIs, and then verifies the signer and the merged manifest's permissions before it says where the file is.

Privacy Policy

Screens

Fourteen device captures — every surface the app has, in dark, in light, and in Arabic.

Capture The vault
One sheet over whatever you were looking at, with the pasted link already read Links, notes and lists in one feed, grouped by when they were saved
Search A link
Search runs as you type across titles, bodies, links and checklist entries A saved link showing the page title it fetched instead of an address
A checklist Reminders
Tick, drag to reorder, clear the finished ones, watch the ring fill Ask any item to come back at a time you choose, scheduled on the device
Tags Multi-select
The feed narrowed to one tag, with links auto-tagged by domain Select many rows at once and act on all of them
Your own order Settings
Sort by "My order" and drag a row by its grip Appearance, security, network, data, erase — and what each switch actually does
Light A link, light
The light theme is drawn on purpose, not tinted down from the dark one The same detail screen, same type, different ground
Arabic Arabic settings
Full right-to-left layout — mirrored, not merely translated Every setting and its explanation, in Arabic

Why Khazna

The product claim is one number: opening the app and getting a paste into the vault stays near a second. Every feature is measured against it, and most of the ones that would have added a step were cut for exactly that reason.

Two decisions buy the number:

  • Capture is a sheet, not a screen. The floating button, a share from the browser, the launcher long-press and the empty state all open the same sheet over whatever you were looking at. An earlier full-screen composer asked what kind of thing you were saving before it let you type — that question, and the screen transition in front of it, were the whole reason capture felt slow.
  • One input takes anything. Paste a URL, a paragraph or a list of lines, and the app works out which it is: an explicit checkbox beats everything, a leading URL takes the rest of the line as its annotation, and anything else is a note. The guess is a pill you can tap to change, and converting an item folds its content across kinds without losing any of it.

Storage is one persisted store over MMKV, read synchronously at boot, so the feed is on the first frame rather than after a spinner.

Features

Capture

  • One sheet, opened from the FAB, a share from another app, a launcher long-press, or the empty state
  • Detection into Link / Note / List as you type, always overridable, and never destructive to convert
  • A paste banner that offers the clipboard rather than reading it behind your back
  • Android share doors — a share from any app, a Direct Share shortcut, and PROCESS_TEXT on selected text
  • A shared link that is nothing but a URL saves with no sheet at all, with an undo
  • Duplicate detection: it says when you are about to save something already in the vault
  • Tags at capture time, plus a domain table that tags common links by itself

Links

  • Page titles fetched on demand, cached, cancellable, and only ever for a link you saved
  • Tracking parameters (utm_*, fbclid, gclid and the rest) stripped as the link is normalised
  • Every deliberate departure goes through one seam, so opening a saved link does not come back to a lock prompt

Notes and checklists

  • Plain text, committed as you type — no save button, no formatting menus
  • Paste a list and every line becomes an entry; tick, drag by the grip, clear the finished ones
  • A progress ring that fills as a list closes out

Finding things again

  • Search as you type across titles, bodies, URLs and checklist entries
  • Filter by kind and by tag, pin to the top, archive, read / unread
  • Sort by saved date, title or kind — or pick "My order" and drag the vault into the order you want
  • Swipe a row to pin or delete, with undo; multi-select to act on many at once
  • Reminders scheduled locally, with a launch-time reconcile so nothing reads the clock during render

Privacy

  • App lock behind fingerprint, face or device PIN, with a grace window and an escape hatch when biometrics become unavailable
  • Screen privacy (FLAG_SECURE) — out of screenshots and out of the app switcher, only when you turn it on
  • Backup to a file you pick, restore on a new device, erase everything from one screen
  • Anonymous usage analytics, opt-out, that the type system will not let carry anything you typed

Craft

  • Arabic-first with native RTL — the tree comes down and reloads around the direction flip, because a mounted navigator cannot absorb one
  • Dark and light drawn separately, from one palette held in two syntaxes, with a test that fails the build when they drift
  • Tajawal throughout, and no named line-heights anywhere: Android trades the font's own padding band for one and clips Arabic marks
  • Western digits in both languages, except inside Arabic running text, where two named helpers opt into Arabic-Indic
  • A deep-import icon barrel, enforced by a test, because the lucide index evaluates ~1,600 icons otherwise
  • 15 test suites, 113 tests, and a route-screenshot harness that deep-links every screen so a layout defect is found rather than reported

Tech stack

Layer Choice
Framework Expo SDK 57 (managed) + Expo Router (file-based routing)
Runtime React Native 0.86 / React 19.2, React Compiler enabled
Language TypeScript, strict mode
UI NativeWind 4 (Tailwind class names on native)
Animation react-native-reanimated 4 + react-native-gesture-handler
Vector react-native-svg (the mark, the progress rings)
State Zustand, persisted to react-native-mmkv v4 (Nitro module)
Notifications expo-notifications — local reminders only, no push server, no token
Security expo-local-authentication (app lock) · expo-screen-capture (FLAG_SECURE)
Sharing expo-share-intent · expo-quick-actions · a local Expo module for the Direct Share target
Files expo-document-picker + expo-file-system (backup and restore)
Updates expo-updates (OTA)
Analytics PostHog, opt-out, restricted by an allowlist the tests enforce
Fonts Tajawal — one family for Arabic and Latin
Icons lucide-react-native, deep-imported through a generated barrel

Network: two calls, both from the device straight to a third party, both switchable off — a GET for a saved link's <title>, and anonymous analytics. The Expo update check is a third connection that no feature initiates, disclosed rather than hidden behind the number two. There is no backend: no server, no account, no sync, no API key.

Non-negotiables

These are load-bearing — every change must respect them:

  • Vault content never leaves the device. Not titles, bodies, URLs, checklist labels, tag names or search queries. Not truncated, not hashed, not "just the domain". The analytics payload types can only express counts, enums and booleans, and a test fails the build if a free string ever appears in one.
  • No screen may claim the app tracks nothing. Analytics ship, so the README, the onboarding cards and the settings copy all say the true thing.
  • Capture stays near a second. A feature that adds a step to that path has to justify itself against the number.
  • Every screen scrolls. Content that fits still scrolls when the font scale is large or the keyboard is up.
  • Reuse is not negotiable. A redesign changes how a shared primitive looks; it does not license a second hand-rolled copy of it.
  • Kind colour is semantic. Slate blue is a link, sand is a note, moss is a list, and none of the three appears on anything that is not that kind.

More projects

  • Rafiq — Islamic Companion App2026 · React Native
  • Joke Generator2021 · JavaScript
  • Masareef — Personal Spending Tracker2026 · React Native
All projects