Skip to content

kubishi/dictionary-static

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

45 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Kubishi Dictionary

An Owens Valley Paiute (Northern Paiute) language dictionary β€” a Vue 3 PWA deployed to Cloudflare Pages with D1 + Vectorize search.

Features

  • πŸ“– Built from .lift XML files (SIL FieldWorks format)
  • πŸ” Hybrid search: D1 FTS5 full-text + Vectorize semantic search when online
  • πŸ“΄ Works offline with TF-IDF fallback from cached data (PWA)
  • πŸŒ“ Light/dark mode with persistent preference
  • πŸ“± Fully responsive design
  • 🎲 Random word discovery and word of the day
  • πŸ€– MCP server for AI assistant integration
  • πŸ”— REST API via Cloudflare Pages Functions

Setup

  1. Install dependencies:
npm install
  1. Place your .lift dictionary file in the project root as dictionary.lift

  2. Build the data files and frontend:

npm run build
  1. Seed the Cloudflare databases:
npx wrangler login                    # authenticate with Cloudflare
npm run seed:d1                       # seed D1 database
VECTORIZE_API_TOKEN=xxx node build-scripts/seed-vectorize.js  # seed Vectorize
  1. Deploy:
npm run deploy
  1. Preview locally:
npm run preview     # runs on :8788 with Cloudflare Functions

Updating Dictionary Data

When you receive a new .lift file:

npm run build:data       # 1. Parse .lift β†’ JSON
npm run seed:d1          # 2. Re-seed D1 (drops and recreates tables)
VECTORIZE_API_TOKEN=xxx node build-scripts/seed-vectorize.js  # 3. Re-seed Vectorize
npm run deploy           # 4. Build and deploy

Project Structure

dictionary-static/
β”œβ”€β”€ build-scripts/              # Build-time data processing & DB seeding
β”‚   β”œβ”€β”€ parse-lift.js           # Parses .lift XML into JSON
β”‚   β”œβ”€β”€ d1-schema.sql           # D1 database schema (FTS5, paiute_forms)
β”‚   β”œβ”€β”€ seed-d1.js              # Seeds D1 from generated JSON
β”‚   └── seed-vectorize.js       # Generates embeddings & seeds Vectorize
β”œβ”€β”€ functions/api/              # Cloudflare Pages Functions
β”‚   β”œβ”€β”€ _db.js                  # D1/Vectorize query helpers
β”‚   β”œβ”€β”€ _shared.js              # Shared utilities (CORS, formatting)
β”‚   β”œβ”€β”€ mcp.js                  # MCP server (JSON-RPC 2.0)
β”‚   β”œβ”€β”€ search.js               # English search (FTS5 + Vectorize)
β”‚   β”œβ”€β”€ search-paiute.js        # Paiute fuzzy search
β”‚   β”œβ”€β”€ search-sentences.js     # Sentence search
β”‚   β”œβ”€β”€ browse.js               # Alphabetical browse
β”‚   β”œβ”€β”€ word/[id].js            # Word lookup
β”‚   β”œβ”€β”€ word-of-the-day.js      # Word of the day
β”‚   β”œβ”€β”€ random-word.js          # Random word
β”‚   └── random-sentence.js      # Random sentence
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ views/                  # Page components
β”‚   β”‚   β”œβ”€β”€ Home.vue            # Search with Words/Sentences tabs
β”‚   β”‚   β”œβ”€β”€ Browse.vue          # Alphabetical browsing
β”‚   β”‚   β”œβ”€β”€ Word.vue            # Word detail page
β”‚   β”‚   β”œβ”€β”€ Pronunciation.vue   # Pronunciation guide
β”‚   β”‚   └── About.vue           # About page
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ data.js             # Loads JSON data for offline use
β”‚   β”‚   β”œβ”€β”€ smart-search.js     # TF-IDF search (offline fallback)
β”‚   β”‚   β”œβ”€β”€ search-api.js       # Online search via API
β”‚   β”‚   └── utils.js            # Paiute fuzzy matching utilities
β”‚   └── router/
β”‚       └── index.js            # Vue Router configuration
β”œβ”€β”€ public/data/                # Generated JSON (gitignored)
└── dictionary.lift             # Source dictionary file (place here)

Search Architecture

Online:  PWA/API/MCP β†’ D1 FTS5 + Vectorize semantic search β†’ hybrid scored results
Offline: PWA β†’ local TF-IDF from cached words.json/sentences.json
  • D1 FTS5: Full-text search with porter stemming on English definitions/glosses
  • Vectorize: Semantic vector search using @cf/baai/bge-base-en-v1.5 embeddings (768 dims, cosine similarity)
  • Hybrid scoring: score = (vectorize_similarity * 0.6) + (fts5_rank * 0.4)
  • Paiute fuzzy: Phonetically-aware matching (k/g, t/d, s/z, u/u equivalence) with Levenshtein distance
  • TF-IDF (offline): Term frequency-inverse document frequency with cosine similarity

Cloudflare Bindings

Binding Service Purpose
DB D1 (kubishi-dictionary) Word/sentence storage, FTS5 search
VECTORIZE_WORDS Vectorize (kubishi-words) Word semantic search (768 dims)
VECTORIZE_SENTENCES Vectorize (kubishi-sentences) Sentence semantic search (768 dims)
AI Workers AI Query embedding generation at search time

API

All endpoints are under /api/.

Endpoint Description
GET /api/search?q=water Search by English meaning/definition
GET /api/search-paiute?q=paa Search by Paiute word (fuzzy matching)
GET /api/word/:id Look up a word by ID
GET /api/browse?letter=T Browse alphabetically by letter
GET /api/word-of-the-day Get the word of the day
GET /api/random-word Get a random word
GET /api/search-sentences?q=mountain Search example sentences
GET /api/random-sentence Get a random sentence

Common query parameters: limit (max results), skip (pagination offset).

MCP Server (AI Integration)

The dictionary exposes an MCP (Model Context Protocol) endpoint at /api/mcp, allowing Claude and other MCP-compatible AI assistants to search and browse the dictionary directly.

Connecting via Claude API

{
  "mcp_servers": [{
    "type": "url",
    "url": "https://kubishi.com/api/mcp",
    "name": "kubishi-dictionary"
  }],
  "tools": [{
    "type": "mcp_toolset",
    "mcp_server_name": "kubishi-dictionary"
  }]
}

Connecting via Claude Desktop

{
  "mcpServers": {
    "kubishi-dictionary": {
      "command": "npx",
      "args": ["mcp-remote", "https://kubishi.com/api/mcp"]
    }
  }
}

Available MCP Tools

Tool Description
search_english Search by English meaning or definition
search_paiute Fuzzy search by Paiute word form
lookup_word Get a word by its ID
browse_words Browse entries alphabetically
get_letter_counts Word counts per starting letter
word_of_the_day Get today's featured word
random_word Get a random dictionary entry
search_sentences Search example sentences
random_sentence Get a random example sentence

Testing with MCP Inspector

npx @modelcontextprotocol/inspector

Select Streamable HTTP and enter the MCP endpoint URL.

.lift File Format

This project expects a standard SIL FieldWorks .lift (Lexicon Interchange FormaT) XML dictionary file. The parser extracts:

  • Lexical entries (words and headwords)
  • Forms in multiple writing systems
  • Senses with definitions and glosses
  • Example sentences with translations
  • Grammatical information (part of speech)
  • Entry dates and GUIDs

Customization

Styling

Edit src/assets/style.css to customize colors and appearance. CSS variables make it easy:

  • --bg-primary, --bg-secondary β€” Background colors
  • --text-primary, --text-secondary β€” Text colors
  • --accent-primary β€” Accent/link color
  • All variables have separate dark mode values

Content

  • Update src/views/About.vue with your credits and information
  • Modify src/views/Pronunciation.vue for your language's pronunciation
  • Edit acknowledgements in src/views/Home.vue

Credits

This site displays data from Glenn Nelson Jr.'s Owens Valley Paiute Dictionary, made possible through the contributions of native speakers and elders.

Built with Vue 3, Vite, Cloudflare D1/Vectorize/Workers AI, and custom hybrid search. Hosted on Cloudflare Pages.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors