Skip to content

Repository files navigation

StoryVault

StoryVault is a private, local-first archive search app for imported story collections.

The app keeps the source archive on disk, extracts readable text into a local SQLite database, builds a full-text search index, and gives you a quiet reader/search interface for exploring the collection.

Quick Start

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
npm install
npm run dev:api

In a second terminal:

npm run dev:web

Open http://127.0.0.1:5173.

For a single-server run after building the frontend:

npm run build
storyvault serve

Open http://127.0.0.1:8765.

Sharing On Your Local Network

StoryVault is private by default. To let other people on the same trusted Wi-Fi or LAN view it, build the frontend and run the single-server app on all network interfaces:

npm run build
npm run serve:lan

Find this Mac's local network IP:

ipconfig getifaddr en0

Other devices on the same network can then open:

http://YOUR_LOCAL_IP:8765

For example, if the IP is 192.168.86.107, use:

http://192.168.86.107:8765

Keep this mode limited to networks and people you trust. StoryVault does not have user accounts or a password gate yet, so anyone who can reach the LAN URL can browse the imported archive through the app.

For development with hot reloading over the LAN, run these in two terminals:

npm run dev:api
npm run dev:web:lan

Then open http://YOUR_LOCAL_IP:5173 from another device.

Friendly local name

Your Mac also has a Bonjour/mDNS name. You can see it with:

scutil --get LocalHostName

If that prints MacBook-Air-Miguel, other devices may be able to open:

http://MacBook-Air-Miguel.local:8765

To make the app reachable as storyvault.local, change the Mac's local hostname:

sudo scutil --set LocalHostName storyvault

Then open:

http://storyvault.local:8765

The bare name http://storyvault:8765 is less reliable because it needs local DNS or per-device hosts-file setup. For that, reserve this Mac's IP address in your router and add a DNS/hosts entry:

192.168.86.107 storyvault

The default archive path is:

/Users/miguel/Projects/story-search/download/www.asstr-mirror.org/files

Useful Commands

storyvault scan --limit 1000
storyvault scan --reset
storyvault search "slow atmospheric science fiction"
storyvault embeddings status
storyvault embeddings index --limit 5000
storyvault embeddings index --all --provider fastembed
storyvault serve
pytest
npm run build

Deep Search

The web UI has two search modes:

  • Fast uses document-level SQLite FTS plus local semantic reranking.
  • Deep runs as a background search job. It combines local embedding matches, passage-level FTS matches, and document-level fallbacks, then returns ranked matches with evidence snippets, confidence, and a short reason.

New imports write passage chunks into the local SQLite index. If you already have an older import without chunks, Deep Search still works by slicing top candidate stories into passages on demand.

Local Embeddings

StoryVault can build a private local embedding index for story passages. The app stores vectors in SQLite and uses them in Deep Search as a hybrid signal alongside FTS.

The default install includes a lightweight hash embedder so the feature works without extra packages. For better semantic matching, install the optional local model dependency:

python -m pip install -e ".[embeddings]"

Then build embeddings from the web UI's Semantic index controls or from the CLI:

storyvault embeddings status
storyvault embeddings index --limit 5000
storyvault embeddings index --all --provider fastembed

fastembed downloads its model files locally the first time it runs. Set these environment variables to control the provider/model:

STORYVAULT_EMBEDDINGS_PROVIDER=fastembed
STORYVAULT_EMBEDDING_MODEL=BAAI/bge-small-en-v1.5

Data

StoryVault stores local app data in ~/Library/Application Support/StoryVault/storyvault.sqlite3 by default.

Avoid keeping the SQLite database, .venv, or node_modules in an iCloud/Dropbox "online only" folder. If macOS or a cloud backup provider offloads those files, SQLite can fail at startup with sqlite3.OperationalError: disk I/O error.

Set these environment variables to override paths:

STORYVAULT_DATA_DIR=/path/to/data-folder
STORYVAULT_DB=/path/to/storyvault.sqlite3
STORYVAULT_ARCHIVE=/path/to/archive

If an older project-local .storyvault/storyvault.sqlite3 was offloaded, either mark the project folder as available offline in Finder/Dropbox or let StoryVault rebuild the index in the default app-data folder by running a fresh import from the UI.

1.0 Scope

  • Import .txt, .text, .html, .htm, and likely text files with no extension.
  • Preserve original file paths and source metadata.
  • Extract clean text for reading.
  • Parse common ASSTR-style headers such as title, author, summary, keywords, rating, and date.
  • Build an SQLite FTS5 index for local candidate retrieval.
  • Build optional local passage embeddings and use them for hybrid Deep Search.
  • Support conversational search phrasing, local semantic concept expansion/reranking, author filters, negative terms, and length hints.
  • Provide a local web UI for importing, searching, filtering, and reading.
  • Capture internal archive links so index pages and chapter/story pages can navigate to linked imported documents.

Future versions can add local embedding models, Tauri packaging, richer dedupe review, manual tagging, and saved reading state.

About

Private local-first archive search and reader app

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages