This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine.
KathaYantra: The Ghost Is the Story
An open-weight, source-aware atlas for the folklore and urban legends we refuse to lose.
Every culture has stories that refuse to disappear.
Some travel through oral traditions. Some survive in old books, manuscripts, regional archives and newspaper clippings. Others become urban legends: a mysterious road, a figure near a river, an abandoned building, or an encounter retold until it becomes part of a community's memory.
But these stories are scattered. Their sources can be difficult to trace, their cultural context can be lost, and a generative model can confidently invent a historical explanation when the evidence is missing.
I wanted to build something that approached the problem differently.
KathaYantra is a digital folklore archive and interactive geographical atlas for exploring traditional narratives and urban legends across cultures. It uses open-weight AI as an archival assistant—not as an authority that invents the past.
The idea behind Ghost in the Machine is simple: the ghost is the memory carried by a story; the machine is a tool that helps someone find, compare and revisit it.
What I Built
KathaYantra currently organises 300 story records across 15 countries, divided into:
- 150 folklore records
- 150 urban legend records
The archive brings these two kinds of narratives together while keeping their categories distinct. Folklore records represent traditional narratives, myths, supernatural beings and cultural storytelling. Urban legend records represent modern circulating narratives, mysterious accounts and contemporary legends.
The main experience is an interactive world atlas. Visitors can explore the countries represented in the archive, select a country and browse its collection. Country pages bring together available folklore and urban legends, with geographical story discovery where the underlying location information supports it.
KathaYantra also includes a local AI Archivist. Rather than asking a model to freely recall folklore from its training data, the application retrieves relevant records from the archive and uses those records as context for an answer.
The experience
- Explore the atlas. Start with the global map and select a country represented in the archive.
- Enter a country collection. Browse its folklore and urban legend records separately.
- Follow the source. Open a record, inspect its available metadata and follow its source references.
- Ask the Archivist. Ask a question about the archive and retrieve relevant records for a grounded response when the local model is available.
- Compare narratives. Explore similarities across records without treating shared motifs as proof that two traditions have the same origin.
- Keep fiction separate. Creative generation is labelled as AI-generated fiction and stored separately from authentic archive seed records.
Why an atlas?
A list of stories is useful, but geography gives people another way to explore. A visitor can begin with a place, discover the narratives represented in that country's collection, and move from a broad view into an individual record.
The map does not imply that every legend happened at a precisely known point. A story receives a specific map location only when the available record and supporting location information justify that placement. Records without sufficiently reliable locations remain discoverable through their country collection instead of being assigned invented coordinates.
A note on cultural and historical accuracy
Folklore and urban legends are presented as narratives, traditions or reported accounts—not as proof that a supernatural event occurred. A source link is a route back to evidence; it is not a blanket guarantee that every interpretation is correct.
KathaYantra aims to make that distinction visible.
Demo
- Source code: github.com/AnshMeshram/KathaYantra
-
Local API documentation:
http://127.0.0.1:8000/docswhen running the backend locally. - Live website: A public deployment link is not included in this submission draft. Add the verified production URL here if the frontend and backend are deployed and tested.
- Video walkthrough: Add a public demo-video link if available.
The local Gemma 2 workflow depends on an Ollama service reachable by the backend. A deployed frontend does not automatically connect to Ollama running on a developer's laptop. Hosted inference requires a separately configured, reachable model runtime. I do not claim hosted Gemma inference is available unless that deployment has actually been configured and tested.
Code
Repository: AnshMeshram/KathaYantra
The repository contains the FastAPI backend, structured country and story datasets, retrieval services, the Next.js frontend, scripts and project documentation.
The project code is released under the MIT License. That licence applies to the repository's code; it does not automatically relicense third-party story texts, photographs, illustrations or archival materials. Those assets retain their own rights and attribution requirements.
How I Built It
The central engineering decision was to make the archive—not the language model—the source of truth.
Open-weight AI: Gemma 2
KathaYantra uses Gemma 2, served locally through Ollama, for its Archivist workflow.
Gemma 2 is the open-weight model. Ollama is the local model runtime. In the local configuration, the application can use the installed model instead of making a closed, hosted LLM API the foundation of the Archivist.
The retrieval flow
The question-answering workflow is designed around this sequence:
Visitor question
↓
SQLite FTS5 retrieval
↓
BM25 relevance ranking and filters
↓
Relevant story records + available source metadata
↓
Context supplied to Gemma 2 through Ollama
↓
Answer grounded in retrieved archive material
The retrieval layer uses SQLite FTS5 for lexical search and BM25 ranking to identify relevant records. The application assembles retrieved material and available metadata before asking Gemma 2 to generate a response.
The goal is not to make the model sound more certain. It is to make answers traceable to records that a person can inspect.
Data governance comes before generation
A folklore archive has a different responsibility from a free-form story generator. Its records need to preserve the distinction between a traditional narrative, a contemporary legend, an editorial summary, a source reference and a piece of generated fiction.
KathaYantra uses structured records and validation rules to support that separation. Candidate material should be reviewed for source quality and rights before becoming a published archive record. Restricted or uncertain source material must not be treated as freely redistributable simply because it is accessible on the web.
AI-generated stories are kept out of the authentic folklore and urban legend seed collections. Generated fiction carries an explicit marker:
{
"content_origin": "ai_generated_fiction"
}
Generated fiction is stored separately under the processed-fiction area. It is not silently promoted into the cultural archive.
Technology stack
| Layer | Technology | Responsibility |
|---|---|---|
| Frontend | Next.js, React, TypeScript | User interface and navigation |
| Styling | Tailwind CSS | Responsive editorial layouts |
| Geography | Leaflet, React Leaflet, GeoJSON | Interactive 2D world and country maps |
| Backend | Python, FastAPI | REST API and service orchestration |
| Validation | Pydantic | Structured data and request/response validation |
| Archive | JSON seed records | Country, folklore and urban legend records |
| Search | SQLite FTS5 | Local full-text retrieval |
| Ranking | BM25 | Relevance ordering for retrieved records |
| Open-weight AI | Gemma 2 | Archive-grounded answer generation |
| Local inference | Ollama | Runs the model in the local environment |
Run the local AI workflow
The local AI path requires a working Ollama installation and a compatible Gemma 2 model. The first model download requires internet access. Once the model and project data are present locally, local inference does not need to call a third-party hosted LLM API.
Clone the repository and prepare the Python environment:
git clone https://github.com/AnshMeshram/KathaYantra.git
cd KathaYantra
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
Copy-Item .env.example .env
Install and start Ollama, then pull the configured Gemma 2 model:
ollama pull gemma2
ollama serve
In another terminal, build the retrieval index and start FastAPI:
python scripts/build_retrieval_index.py
python -m uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
The API documentation is available at:
http://127.0.0.1:8000/docs
For the frontend, open another terminal:
cd frontend
pnpm install
pnpm run dev
Then open http://localhost:3000.
Check the repository's .env.example for the current model tag and configuration names. The model installed through Ollama must match the configured OLLAMA_MODEL value.
What happens when the model is unavailable?
Ordinary archive browsing and data access should not depend on a running model. The AI health status reports model availability separately. If Ollama is unavailable, the application should report that the inference capability is unavailable rather than disguising a fallback response as a successful Gemma answer.
This distinction also matters in deployment: Vercel can host the Next.js frontend and a Python host can run FastAPI, but neither automatically has access to a developer's local Ollama process. Hosted inference requires a separately configured model runtime.
Why Does Open Innovation Matter?
For a project about cultural memory, the ability to inspect and control the information path matters.
1. The model can run where the archive lives
With Ollama and Gemma 2 installed locally, the Archivist can process questions against local archive data without sending every prompt and retrieved record to a closed, hosted model API. This gives researchers and communities more control over where their material is processed.
This is a property of the local configuration—not a claim that every public deployment is automatically private or offline.
2. The model is not the archive
The seed records, source metadata and retrieval index remain inspectable project data. Gemma 2 can be replaced or reconfigured without making a proprietary model API the owner of the archive's knowledge layer.
3. Retrieval is inspectable
SQLite FTS5 and BM25 provide a local retrieval layer. Developers can inspect which records were retrieved, how filters were applied and what metadata was available to support an answer.
4. Fiction has a separate boundary
Open models make creative experimentation accessible, but the archive should not confuse generated output with traditional cultural material. Separating the generated-fiction store from authentic seed data is an architectural safeguard, not just a disclaimer in the interface.
5. The project can be extended by its community
Contributors can inspect the schemas, improve source validation, expand country coverage, improve accessibility or replace the local model runtime. The project is not locked to one proprietary inference provider.
Open innovation does not make the system automatically accurate. Models can misunderstand retrieved context, and retrieval can miss relevant records. The value is that the components, data boundaries and limitations can be inspected and improved.
My Agent Session
I used Google Antigravity with Gemini 3.8 Flash as a development assistant for repository inspection, implementation and iterative debugging.
A public DevRelay session is not attached to this article. The challenge describes the agent-session share as optional, so I have left out the session embed rather than inserting an invalid or placeholder session ID.
The Spirit of It
I keep returning to one thought: a story can outlive the person who first told it, but only if someone keeps carrying it forward.
The Ghost in the Machine theme gave me a way to think about that relationship. The machine does not need to pretend to be a spirit. It can become a place where stories are organised, connected to their sources and made easier to rediscover.
The connection to Día de los Muertos is about remembrance and care for what came before. KathaYantra approaches that idea through preservation: not flattening different cultures into one spooky aesthetic, not treating every legend as a proven event, and not allowing a model to invent a source just to complete an answer.
The archive is still growing. Some records have more complete provenance than others. Some stories can be connected to a mapped location; others should remain unmapped until evidence supports a more precise placement. Those gaps are not invitations to fabricate. They are part of the work that remains.
The machine should help us remember. It should not rewrite what we remember.
Prize Categories
Entering: Best Use of Gemma
KathaYantra uses Google's open-weight Gemma 2 model through Ollama for its local AI Archivist workflow.
I am not claiming other partner categories unless the corresponding partner technology is genuinely integrated into the project. DevRelay is an optional way to share an agent session; it is not itself a Week 4 prize category.
Feedback and Contributions
I would especially welcome contributions around:
- Folklore source discovery and bibliographic metadata.
- Cultural review and country-specific context.
- Rights-aware image attribution.
- Geographical data quality.
- SQLite FTS5 and retrieval evaluation.
- Local Gemma 2 inference and grounded-response evaluation.
- Accessibility and frontend performance.
Explore the project: GitHub — KathaYantra.
If you could preserve one story from your community in a digital archive, what would it be?
Built for Hacktoberfest 2026 — Open-Source AI Challenge, Week 4: Ghost in the Machine.
Top comments (0)