{"slug": "explobook-turning-books-into-real-world-adventures", "title": "ExploBook: Turning Books into Real-World Adventures", "summary": "A developer built ExploBook, an open-source web app that pairs AI-driven book recommendations with real-world \"expeditions\" inspired by each book's themes. The pnpm workspace combines a Next.js 15/React 19 frontend with a Node.js/Express TypeScript API, using Clerk for authentication, MongoDB Atlas for storage, and Mastra workflows that call a local Ollama instance running nomic-embed-text for embeddings and gemma3:4b-it-q4_K_M for structured recommendation explanations, with deterministic fallbacks when inference is unavailable.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass](https://dev.to/challenges/hacktoberfest-week1-2026-10-05)*\n\nI built ExploBook around a question I wanted book discovery to ask: what if the story you read could inspire something you experience in the real world?\n\n**ExploBook doesn't just recommend books. It turns reading into a reason to step outside. Discover your next story, reflect on what you've read, and embark on real-world quests inspired by your reading journey.**\n\n**Read a story. Live the adventure. Touch grass.**\n\nI made ExploBook for readers who want more meaningful reading habits and for anyone looking for a reason to explore beyond their screens. A recommendation is only the first step. The book starts the adventure; the real world completes it.\n\nMy goal is to make the screen the shortest part of the experience. AI helps readers discover a catalogue book, prepare an expedition connected to its themes, and make sense of field notes after the reader returns. I didn't want to build a chatbot whose conversation is the destination. The intended destination is outside.\n\nThe AI features depend on a reachable local Ollama instance. If model inference is unavailable or its output cannot be used, some services return deterministic fallback content; that fallback should not be mistaken for Gemma-generated content. Atlas, Clerk, and optional integrations also require network access and configuration.\n\n**GitHub repository:** [kachamsiddarth/ExploBook](https://github.com/kachamsiddarth/ExploBook)\n\nThe repository contains the web app, Express API, shared TypeScript schemas, and project documentation. The root [README](https://github.com/kachamsiddarth/ExploBook/blob/main/README.md) has local setup instructions, model requirements, and the current environment variable names.\n\nI built ExploBook as a pnpm workspace with a Next.js 15 and React 19 frontend, styled with Tailwind CSS, and a Node.js/Express API written in TypeScript. Clerk provides web and API authentication. MongoDB Atlas stores the catalogue, user profiles, reading sessions, expeditions, Orbs, and optional voice cache entries.\n\nThe frontend calls the Express API. Protected endpoints use the authenticated Clerk identity to load or update only that reader's data. The recommendation, expedition-generation, and expedition-completion workflows are registered on the API's Mastra instance and executed through Mastra's workflow runner.\n\nFor a recommendation, `POST /api/v1/recommendations` (or the public `GET /api/v1/recommendations/public` route) calls the registered `book-recommendation-workflow` through Mastra's `createRun()` and `start()`. For signed-in requests, the route loads the reader's stored preferences. The recommendation orchestrator asks Ollama's `nomic-embed-text` model for a query embedding through Ollama's `/api/embeddings` endpoint, then searches for candidate books.\n\nWhen the Atlas index is available, the repository sends a `$vectorSearch` aggregation against `books.embedding` using the `vector_index` index, configured for 768-dimensional cosine similarity. The search returns catalogue documents, not free-form titles from the model. If Atlas Vector Search is not available, the repository can compare stored embeddings with cosine similarity in application code; if no usable vectors are found, it can query the catalogue with database filters.\n\nFor each candidate, [`gemma.service.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/gemma.service.ts) sends the book's title, authors, genres, themes, and description—plus reader context when present—to Ollama's `/api/generate` endpoint with `gemma3:4b-it-q4_K_M`. It asks for structured explanation fields: why the book may fit, why it could prompt the reader to step outside, and a suggested atmosphere. The service parses those fields and marks an offline template as `fallback_offline` when inference fails or the response is malformed. The response's book identity and metadata remain those of the retrieved catalogue document.\n\n`POST /api/v1/expeditions/generate` invokes the registered `expedition-generation-workflow` in [`mastra.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/mastra.ts). Its Mastra step loads the selected book and reader profile from MongoDB. The frontend can request a one-time browser location; if permission is granted and `SERPAPI_KEY` is configured, [`serpapi.service.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/serpapi.service.ts) calls SerpApi's Google Maps search with an expedition-type-specific query, such as parks for nature quests or libraries for literary quests. The service normalizes the search results, and the workflow attaches the first returned candidate to the expedition. Without coordinates, a configured key, or returned places, the quest proceeds without a named destination.\n\n[`expedition.service.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/expedition.service.ts) sends Gemma the book metadata and expedition context and prompts it to return a structured mission: a title, supported expedition type, duration, objective, instructions, and book connection. Its prompt explicitly asks for phone-away activities and rules out trespassing, dangerous stunts, and hazardous terrain. The service parses and checks the returned structure; if inference or parsing fails, it creates a deterministic book-themed observation/walk concept instead. The workflow saves the resulting expedition in MongoDB.\n\nAfter the reader returns, `POST /api/v1/expeditions/:id/reflection` starts the registered `expedition-completion-workflow`. [` reflection.service.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/reflection.service.ts) sends Gemma the saved expedition and book details plus the reader's submitted notes, observations, and surprises. It can return thematic resonance, curiosity signals, key observations, bounded Reader DNA affinity suggestions, and Orb title/theme ideas. The reflection service restricts which DNA fields can change and clamps the suggested deltas. If the model is unavailable or its response is unusable, a deterministic reflection-analysis fallback is used.\n\nThe model does not award points or write database records itself. The same completion workflow uses TypeScript application logic to calculate XP and level progression, choose Orb rarity and color, create an Orb record, update the expedition, and persist XP/outdoor-time totals and any accepted DNA delta.\n\nElevenLabs is a separate optional integration, called through `POST /api/v1/expeditions/:id/voice` and implemented in [`elevenlabs.service.ts`](https://github.com/kachamsiddarth/ExploBook/blob/main/apps/api/src/services/voice/elevenlabs.service.ts). It builds a short script from the saved expedition's title, objective, up to four instructions, duration, and book connection, sends it to ElevenLabs text-to-speech using the configured voice and model, and caches the MP3 response in MongoDB's `voiceGenerations` collection. It introduces an already-generated expedition; it does not create the quest. The voice request requires `ELEVENLABS_API_KEY`.\n\nThe API includes conditional Sentry SDK initialization, but although a capture helper is present, there are no active call sites in the current source. I do not count Sentry as an implemented partner-facing product workflow.\n\n```\nReader\n  │\n  ▼\nNext.js + React ──────► Clerk Authentication\n  │\n  │ HTTP / JSON\n  ▼\nExpress API\n  │\n  ▼\nMastra Workflows\n  │\n  ├────► Book Recommendations\n  │          ├────► Gemma 3 4B IT (Ollama)\n  │          ├────► Embeddings (nomic-embed-text)\n  │          └────► MongoDB Atlas Vector Search\n  │\n  └────► Expedition Generation & Completion\n               ├────► Gemma 3 4B IT (Ollama)\n               ├────► MongoDB Atlas\n               ├────► SerpApi (optional: real-world places)\n               └────► ElevenLabs (optional: audio briefings)\n\nExpedition Completed\n  │\n  ▼\nReflection → XP + Levels + Orbs\n  │\n  ▼\nReader DNA Evolves\n  │\n  ▼\nNext Personalized Book Recommendation\n```\n\nThis division keeps the model in a supporting role: it generates and interprets language within application-provided context, while TypeScript and the repositories own request validation, identity checks, persistence, progression rules, and the expedition safety prompt. Model output is not treated as proof of a real-world action.\n\nExploBook uses the open-weight Gemma 3 4B IT model through Ollama for recommendation explanations, expedition concepts, and expedition-reflection analysis. During development, the model can run on the machine hosting Ollama instead of sending generation requests to a closed hosted language-model API. I can inspect and adjust the prompts, choose the model and runtime configuration, and see how the workflow uses the returned output.\n\nMastra's open-source workflow framework also makes the application orchestration inspectable: recommendation retrieval, expedition generation, and expedition completion are explicit registered workflows rather than an opaque chat loop.\n\nThat control has trade-offs. Local inference needs suitable hardware and can be slower or unavailable; some flows then use fallback behavior. The whole application is not offline: authentication and persistent data use Clerk and MongoDB Atlas, and nearby places and voice briefings use network services when configured.\n\n**The open-weight model is not the destination of this project. It is the engine that helps turn a digital reading experience into a real-world activity.** AI helps prepare and personalize the experience; the intended outcome is the reader stepping away from the device.\n\nI used an AI coding agent during development to help investigate reported API issues, inspect implementation details, and prepare project documentation..\n\n`gemma.service.ts`, `expedition.service.ts`, and `reflection.service.ts` call the configured Gemma model through Ollama to explain retrieved catalogue books, turn a book's themes into constrained quest instructions, and interpret the reader's expedition notes.`mastra.ts` registers `book-recommendation-workflow`, `expedition-generation-workflow`, and `expedition-completion-workflow`; recommendation and expedition route handlers invoke them with Mastra's workflow runner rather than bypassing orchestration.`book.repository.ts` runs `$vectorSearch` against the `vector_index` index on 768-dimensional `books.embedding` vectors when that Atlas index is available.`serpapi.service.ts` uses browser-granted one-time coordinates and the server-side `SERPAPI_KEY` to search Google Maps for places matched to the quest type, normalize place names, addresses, coordinates, and map links, and return candidates for the workflow to store with the expedition. This enrichment is optional; it is not required to generate a generic quest.`elevenlabs.service.ts`, exposed at `POST /api/v1/expeditions/:id/voice`, turns the saved quest's objective and instructions into an MP3 briefing using the configured ElevenLabs voice/model and caches the audio in MongoDB. It is a pre-departure briefing, not a conversational assistant or quest generator.", "url": "https://wpnews.pro/news/explobook-turning-books-into-real-world-adventures", "canonical_source": "https://dev.to/siddarth_652dabeeca26cfc1/explobook-turning-books-into-real-world-adventures-9n3", "published_at": "2026-10-09 17:12:56+00:00", "updated_at": "2026-10-09 17:21:35.152648+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-products", "ai-tools", "generative-ai"], "entities": ["ExploBook", "Ollama", "Mastra", "MongoDB Atlas", "Clerk", "Next.js", "React", "Gemma 3"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/explobook-turning-books-into-real-world-adventures", "markdown": "https://wpnews.pro/news/explobook-turning-books-into-real-world-adventures.md", "text": "https://wpnews.pro/news/explobook-turning-books-into-real-world-adventures.txt", "jsonld": "https://wpnews.pro/news/explobook-turning-books-into-real-world-adventures.jsonld"}}