jameslittle230/stork
π Impossibly fast web search, made for static sites.
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained β safe to depend on.
Has a license, tests, and CI β clean foundation to fork and modify.
Documented and popular β useful reference codebase to read through.
No critical CVEs, sane security posture β runnable as-is.
- β6 active contributors
- βApache-2.0 licensed
- βCI configured
Show all 6 evidence items βShow less
- βTests present
- β Stale β last commit 3y ago
- β Single-maintainer risk β top contributor 82% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README β live-updates from the latest cached analysis.
[](https://repopilot.app/r/jameslittle230/stork)Paste at the top of your README.md β renders inline like a shields.io badge.
βΈPreview social card (1200Γ630)
This card auto-renders when someone shares https://repopilot.app/r/jameslittle230/stork on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: jameslittle230/stork
Generated by RepoPilot Β· 2026-05-09 Β· Source
π€Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale β STOP and ask the user to regenerate it before proceeding. - Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/jameslittle230/stork shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
π―Verdict
GO β Healthy across all four use cases
- 6 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- β Stale β last commit 3y ago
- β Single-maintainer risk β top contributor 82% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
β Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live jameslittle230/stork
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale β regenerate it at
repopilot.app/r/jameslittle230/stork.
What it runs against: a local clone of jameslittle230/stork β the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in jameslittle230/stork | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit β€ 1072 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of jameslittle230/stork. If you don't
# have one yet, run these first:
#
# git clone https://github.com/jameslittle230/stork.git
# cd stork
#
# Then paste this script. Every check is read-only β no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of jameslittle230/stork and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "jameslittle230/stork(\\.git)?\\b" \\
&& ok "origin remote is jameslittle230/stork" \\
|| miss "origin remote is not jameslittle230/stork (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift β was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "stork-lib/src/index_v3/build/fill_containers.rs" \\
&& ok "stork-lib/src/index_v3/build/fill_containers.rs" \\
|| miss "missing critical file: stork-lib/src/index_v3/build/fill_containers.rs"
test -f "stork-lib/src/index_v3/search.rs" \\
&& ok "stork-lib/src/index_v3/search.rs" \\
|| miss "missing critical file: stork-lib/src/index_v3/search.rs"
test -f "js/main.ts" \\
&& ok "js/main.ts" \\
|| miss "missing critical file: js/main.ts"
test -f "js/wasmManager.ts" \\
&& ok "js/wasmManager.ts" \\
|| miss "missing critical file: js/wasmManager.ts"
test -f "stork-cli/src/main.rs" \\
&& ok "stork-cli/src/main.rs" \\
|| miss "missing critical file: stork-cli/src/main.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1072 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1042d)"
else
miss "last commit was $days_since_last days ago β artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) β safe to trust"
else
echo "artifact has $fail stale claim(s) β regenerate at https://repopilot.app/r/jameslittle230/stork"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
β‘TL;DR
Stork is a full-text search engine for static sites, built in Rust and compiled to WebAssembly. It consists of a CLI tool that pre-indexes content into a .st binary index file, and a JavaScript library that loads that index in the browser to provide instant, interactive search results as users typeβenabling sub-millisecond search without a backend server. Rust monorepo with three crates (stork-lib, stork-cli, stork-wasm in Cargo.toml workspace). js/ contains the browser-side TypeScript library with modules for DOM management (js/dom.ts), WASM loading (js/wasmManager.ts), search result rendering (js/resultToListItem.ts), and configuration (js/config.ts). The CLI generates index files; the JS library consumes them.
π₯Who it's for
Jamstack developers and static site owners (Hugo, Jekyll, Gatsby users) who want to add a polished, fast search experience to blogs and documentation without running a server. Also JavaScript engineers integrating search UI into their sites via the JS library in js/.
π±Maturity & risk
The project is winding downβthe creator announced (in the README) they are stepping back from active development. However, it is production-ready with comprehensive test coverage (Jest + Rust tests), robust CI/CD (GitHub Actions in .github/workflows/), and stable releases on crates.io. Not abandoned, but not actively growing.
Single-maintainer project now in maintenance mode β the creator explicitly stated they're winding down work (see README discussion #360). Risk of stalled PRs, slow bug fixes, and no feature development. No obvious security issues in the dependency graph visible here, but long-term viability is uncertain for new integrations.
Active areas of work
Project is in maintenance mode. No active development visible in the file list. The creator is no longer actively building features; the focus is on keeping existing code stable and fixing critical bugs. Most recent work appears to be test maintenance and CI improvements.
πGet running
git clone https://github.com/jameslittle230/stork.git
cd stork
cargo build --release # Build Rust CLI
cd js && npm install && npm test # Build & test JS library
Daily commands:
For the CLI: cargo run --bin stork-cli -- build --input <config.toml> (see deploy.md for CLI docs). For JS library tests: cd js && npm test. For local dev site: check local-dev/index.html for a static HTML example; serve it with any HTTP server (e.g., python -m http.server in local-dev/).
πΊοΈMap of the codebase
stork-lib/src/index_v3/build/fill_containers.rsβ Core indexing engine that builds the search index from source data; critical for understanding the index generation pipelinestork-lib/src/index_v3/search.rsβ Search execution logic in Rust that powers query matching; essential for understanding query semantics and scoringjs/main.tsβ TypeScript entry point that orchestrates the JavaScript/WebAssembly integration; primary interface for JavaScript consumersjs/wasmManager.tsβ Manages WebAssembly module instantiation and lifecycle; critical for bridging JavaScript and Rust search logicstork-cli/src/main.rsβ CLI entry point for building indexes; shows how users interact with the library to create searchable indexesstork-lib/src/config/mod.rsβ Configuration parsing and validation; defines how users specify indexing behavior and data sourcesjs/entityManager.tsβ Manages DOM entity lifecycle and search result rendering; bridges search results to UI presentation
π οΈHow to make changes
Add a new data source type for indexing
- Create a new reader struct implementing the data source reader trait in stork-lib/src/index_v3/build/fill_intermediate_entries/data_source_readers/ (
stork-lib/src/index_v3/build/fill_intermediate_entries/data_source_readers/mod.rs) - Add configuration options for the new source type in stork-lib/src/config/input.rs (
stork-lib/src/config/input.rs) - Wire the new reader into the fill_intermediate_entries logic to instantiate it based on config (
stork-lib/src/index_v3/build/fill_intermediate_entries/mod.rs) - Update CLI documentation and example configs in local-dev/test-configs/ (
local-dev/test-configs/federalist.toml)
Customize search result presentation in the UI
- Examine the result-to-HTML conversion function (
js/resultToListItem.ts) - Modify the HTML structure or add CSS classes in resultToListItem or entityDom as needed (
js/entityDom.ts) - Handle entity lifecycle events (show, hide, focus) in entityManager (
js/entityManager.ts) - Update tests to validate the new presentation (
js/resultToListItem.test.ts)
Add a new scoring or ranking algorithm
- Add scoring logic to the search module (
stork-lib/src/index_v3/search.rs) - Define configuration options for the new scoring method in stork-lib/src/config/ (
stork-lib/src/config/mod.rs) - Add benchmarks to measure impact on search performance (
stork-lib/benches/basic.rs) - Test with local dev configs to validate ranking changes (
local-dev/test-configs/federalist.toml)
Add a new JavaScript API method or configuration option
- Define the new method signature in the main TypeScript module (
js/main.ts) - Implement the method using existing wasmManager and dom utilities (
js/wasmManager.ts) - Add TypeScript type definitions and JSDoc comments (
js/config.ts) - Write unit tests for the new functionality (
js/main.test.ts)
π§Why these technologies
- Rust (stork-lib) β Provides memory safety, zero-cost abstractions, and blazing-fast index building and search execution; compiles to WebAssembly for browser deployment
- WebAssembly β Executes compiled Rust search logic directly in the browser with near-native performance while maintaining security sandboxing
- TypeScript (JavaScript layer) β Provides type safety and IDE support for the JavaScript-facing API; makes WASM integration idiomatic and maintainable
- TOML (configuration) β Human-readable configuration format for specifying data sources, indexing options, and output paths; parsed server-side before index generation
βοΈTrade-offs already made
-
Build indexes server-side (CLI) rather than in-browser
- Why: Server-side indexing allows sophisticated text processing, supports multiple data source formats, and avoids long user initialization times
- Consequence: Users must run the CLI tool; index files are static artifacts that must be deployed with the website
-
Use static index files rather than dynamic backend search API
- Why: Static indexes work offline, have zero server costs, enable CDN caching, and are ideal for static site generators
- Consequence: Index updates require regenerating and redeploying; incremental updates and real-time indexing are not supported
-
Entire search logic runs in-browser via WASM
- Why: Eliminates network latency for every keystroke, works offline, protects user privacy, and provides instant results
- Consequence: Index must fit in browser memory; very large indexes may cause slowdowns on low-end devices
-
Multiple index format versions (v2, v3) coexist
- Why: Allows gradual migration and backwards compatibility while improving the index format
- Consequence: Added complexity in
πͺ€Traps & gotchas
- WASM initialization is async: The
js/wasmManager.tsqueues search requests until WASM loads; naive users might expect synchronous results. 2. Index file must be pre-built: The.stfile is created offline by the Rust CLI and served separately; there is no server-side indexing. 3. Multiple Stork instances on one page: Each instance needs a uniquedata-stork='name'identifier; sharing identifiers will cause conflicts in the DOM manager. 4. No TypeScript types exported from WASM: The WASM module boundary is opaque; you interact with it viajs/wasmManager.tsonly, not directly.
ποΈArchitecture
π‘Concepts to learn
- WebAssembly (WASM) β The entire search engine runs as a compiled WASM module in the browser (stork-wasm crate); understanding WASM lifecycle and bindings is essential to fixing performance issues or debugging search failures.
- Full-text search indexing (inverted index) β The CLI builds an inverted index (word β document list) that is serialized into the
.stfile; understanding how the index is structured helps explain why Stork can search so fast without a server. - Static site generation (Jamstack) β Stork is purpose-built for static sites (Hugo, Jekyll, Gatsby) where content is known at build time; it exploits this constraint to pre-compute indexes offline.
- Binary serialization (serde in Rust) β The
.stindex file is a binary-serialized data structure (likely using serde + bincode); the Rust-to-JavaScript boundary requires deserializing this format efficiently. - Debouncing and event queuing β The
js/wasmQueue.tsmodule queues search requests while WASM initializes and debounces rapid input changes; critical for smooth UX and avoiding redundant computations. - TypeScript generics and entity management β The
js/entityManager.tsuses TypeScript generics to manage search results as first-class entities; understanding this pattern helps with customizing result rendering and state.
πRelated repos
meilisearch/meilisearchβ Server-side full-text search alternative if you need more dynamic indexing; contrasts with Stork's static, offline-built approach.olivernn/lunr.jsβ Browser-side search library similar in scope but without pre-built indexes; Stork is faster because it compiles the index ahead of time rather than parsing JSON in the browser.algolia/algoliasearch-client-javascriptβ Cloud-hosted search alternative; Stork is for zero-backend sites, Algolia is for teams wanting hosted infrastructure.nextapps-de/winamp-jsβ Another WASM-in-browser project showing similar performance patterns; Stork uses WASM similarly for speed.
πͺPR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for js/wasmQueue.ts and js/wasmManager.ts integration
The WASM queue and manager modules are critical for handling async search operations, but based on the file structure, the test files (wasmQueue.test.ts and wasmManager.test.ts) may lack integration tests. Given that Stork is a performance-critical search library, ensuring the queue properly batches WASM calls and handles edge cases (timeouts, race conditions, concurrent searches) would significantly improve reliability. This is especially important since the project is in maintenance mode and new contributors should focus on stability.
- [ ] Review existing js/wasmQueue.test.ts and js/wasmManager.test.ts to identify coverage gaps
- [ ] Add integration tests for concurrent search requests queuing behavior
- [ ] Add tests for WASM call timeout and error handling scenarios
- [ ] Add tests for queue flushing under various load conditions
- [ ] Verify codecov reflects improved coverage after implementation
Create missing validator tests for js/validators/indexParamValidator.ts
The validators directory contains indexParamValidator.ts but there's no corresponding .test.ts file visible in the file structure. Index parameters are user-facing API inputs, so robust validation is critical. This validator likely handles the index file path/URL that users provide, and thorough tests would catch issues like malformed paths, missing files, or invalid formats before they cause runtime errors.
- [ ] Create js/validators/indexParamValidator.test.ts
- [ ] Add test cases for valid index parameter formats
- [ ] Add test cases for invalid paths, null/undefined values, and type mismatches
- [ ] Add test cases for edge cases like empty strings and special characters
- [ ] Run tests and update codecov.yml if coverage thresholds need adjustment
Add Rust unit tests for stork-boundary/src/lib.rs with specific boundary condition coverage
The stork-boundary workspace member is listed in Cargo.toml but appears to be a separate crate handling boundary/tokenization logic for search indexing. This is a critical componentβboundaries determine where search terms are split. Currently, there's no visible test directory structure for this Rust module. Adding comprehensive tests for UTF-8 boundary handling, edge cases in different languages, and emoji/special character handling would improve index quality and catch regressions.
- [ ] Create stork-boundary/tests/ directory structure
- [ ] Add tests for ASCII, UTF-8 multi-byte, and emoji boundary detection
- [ ] Add tests for common edge cases (punctuation, numbers, hyphenated words)
- [ ] Add tests for international character sets (CJK, Cyrillic, Arabic)
- [ ] Verify tests run in CI via .github/workflows/test.yml and update if needed
πΏGood first issues
- Add test coverage for
js/util.tsβ it has no.test.tsfile visible in the list; write unit tests for any utility functions to improve reliability. - Document the exact
.stindex file format β the Rust side generates these files but there is no spec visible; reverse-engineer and write a spec to help alternative implementations. - Add keyboard navigation tests to
js/entityDom.test.tsβ currently tests only DOM rendering; add Arrow key + Enter tests to ensure accessibility.
βTop contributors
Click to expand
Top contributors
- @jameslittle230 β 82 commits
- @dependabot[bot] β 14 commits
- @kkwteh β 1 commits
- @ArsenArsen β 1 commits
- @jmooring β 1 commits
πRecent commits
Click to expand
Recent commits
efa98daβ Add project update (jameslittle230)b946a78β Update version numbers, add changelog (#334) (jameslittle230)4dbe004β Update dependencies to resolve dependabot (#332) (jameslittle230)a6b1752β Fix timestamp formatting to match documentation (#331) (jameslittle230)8550f1fβ Center SVG x in stork-close-button (#309) (kkwteh)6b44e7eβ Bump crossbeam-utils from 0.8.5 to 0.8.8 (#302) (dependabot[bot])8ec8b1aβ Bump thread_local from 1.1.3 to 1.1.4 (#303) (dependabot[bot])d2df78dβ Release version 1.5.0 (#300) (jameslittle230)8a3d7e9β Add new deploy steps (jameslittle230)f2d239aβ Format deploy.md (jameslittle230)
πSecurity observations
The Stork codebase appears to be a well-structured project with GitHub Actions CI/CD pipelines and testing infrastructure in place. Primary security concerns include: (1) Potential XSS vulnerabilities in DOM manipulation code for search results, (2) WASM module loading security, and (3) Missing explicit security header configurations. The project includes validators and mocks suggesting attention to security testing, but actual implementation details would require code review. The use of LTO and optimized release profiles is good practice. No hardcoded credentials or obvious injection points were identified from the file structure. Overall security posture is moderate; the project would benefit from security-focused code review and ongoing dependency vulnerability scanning.
- Medium Β· Potential XSS Risk in DOM Manipulation β
js/dom.ts, js/entityDom.ts, js/resultToListItem.ts. The presence of files like 'dom.ts', 'entityDom.ts', and 'resultToListItem.ts' that handle DOM manipulation suggest potential XSS vulnerabilities. Without reviewing the actual implementation, if these files use innerHTML or similar unsafe DOM methods with user-controlled search results, they could be vulnerable to XSS attacks. Fix: Audit DOM manipulation code to ensure all user-controlled content is properly sanitized. Use textContent instead of innerHTML where possible. If HTML content is necessary, use a trusted sanitization library like DOMPurify. Ensure search results are properly escaped before insertion into the DOM. - Medium Β· WASM Module Loading Security β
js/wasmManager.ts, js/loaders/indexLoader.ts. The presence of 'wasmManager.ts' and 'wasmQueue.ts' suggests WebAssembly module loading. WASM modules from untrusted sources or loaded without verification could pose security risks, including arbitrary code execution in the browser context. Fix: Implement integrity checking for WASM modules using Subresource Integrity (SRI) hashes. Validate the source of WASM files. Ensure WASM modules are served over HTTPS. Consider code signing for WASM artifacts. - Medium Β· Missing Security Headers Configuration β
Root configuration / deployment setup. No visible security header configuration in the codebase. Static site search interfaces should implement proper CSP, X-Frame-Options, X-Content-Type-Options, and other security headers to prevent common web attacks. Fix: Implement security headers including: Content-Security-Policy (CSP) to prevent XSS, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, X-XSS-Protection: 1; mode=block, and Strict-Transport-Security for HTTPS. Configure these in the web server or deployment platform. - Low Β· Test Server in Production Code β
stork-cli/src/test_server/mod.rs. A test server implementation exists in 'stork-cli/src/test_server/mod.rs'. While this is for development, care must be taken to ensure this is not inadvertently compiled into or exposed through production builds. Fix: Ensure test server code is behind appropriate feature flags and is excluded from release builds. Review build configuration to confirm test code is not included in production distributions. - Low Β· Dependency Audit Needed β
Cargo.lock, package.json, package-lock.json. The Cargo.lock file and dependencies are not visible in the provided content. Rust and JavaScript dependencies should be regularly audited for known vulnerabilities using tools like 'cargo audit' and 'npm audit'. Fix: Regularly run 'cargo audit' to check for vulnerable Rust dependencies and 'npm audit' for JavaScript dependencies. Keep dependencies updated to the latest secure versions. Consider using automated dependency scanning in CI/CD pipeline as shown in .github/workflows. - Low Β· No Visible Input Validation β
js/validators/indexParamValidator.ts, js/searchData.ts. While there are validator files (js/validators/), the validation strategy and completeness cannot be fully assessed from file structure alone. Search input validation is critical to prevent injection attacks. Fix: Implement comprehensive input validation for all user-provided search parameters. Validate index file paths, query strings, and configuration parameters. Use allowlist-based validation where possible. Sanitize all search query input before processing.
LLM-derived; treat as a starting point, not a security audit.
πWhere to read next
- Open issues β current backlog
- Recent PRs β what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals β see the live page for receipts. Re-run on a new commit to refresh.