{"id":50720196,"url":"https://github.com/4ssh1/fable-weaver","last_synced_at":"2026-06-09T23:01:58.289Z","repository":{"id":351773513,"uuid":"1211441086","full_name":"4ssh1/fable-weaver","owner":"4ssh1","description":"Every choice writes your legacy. An AI-driven interactive fiction app built with React, TypeScript, and Llama 3.","archived":false,"fork":false,"pushed_at":"2026-06-09T19:56:16.000Z","size":162,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T21:23:30.718Z","etag":null,"topics":["generative-ai","groq","interactive-fiction","llm","react","typescript"],"latest_commit_sha":null,"homepage":"https://fable-weaver.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4ssh1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-15T11:53:53.000Z","updated_at":"2026-06-09T19:56:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/4ssh1/fable-weaver","commit_stats":null,"previous_names":["4ssh1/fable-weaver"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/4ssh1/fable-weaver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ssh1%2Ffable-weaver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ssh1%2Ffable-weaver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ssh1%2Ffable-weaver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ssh1%2Ffable-weaver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4ssh1","download_url":"https://codeload.github.com/4ssh1/fable-weaver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ssh1%2Ffable-weaver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34129072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generative-ai","groq","interactive-fiction","llm","react","typescript"],"created_at":"2026-06-09T23:01:57.577Z","updated_at":"2026-06-09T23:01:58.284Z","avatar_url":"https://github.com/4ssh1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🔮 Fable Weaver: Choose Your Adventure\n\nAn interactive, AI-powered \"Choose Your Own Adventure\" web application. Users can select predefined themes or type their own custom prompts to generate entirely unique, branching narratives with dynamic UI feedback, atmospheric animations, and consequence-driven gameplay.\n\n![React](https://img.shields.io/badge/React-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB)\n![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge\u0026logo=typescript\u0026logoColor=white)\n![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=for-the-badge\u0026logo=tailwind-css\u0026logoColor=white)\n![Python](https://img.shields.io/badge/Python-14354C?style=for-the-badge\u0026logo=python\u0026logoColor=white)\n![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-D71F00?style=for-the-badge\u0026logo=sqlite\u0026logoColor=white)\n![Groq API](https://img.shields.io/badge/Groq_LLM-f39c12?style=for-the-badge\u0026logo=openai\u0026logoColor=white)\n\n---\n\n\u003cimg width=\"1877\" height=\"830\" alt=\"image\" src=\"https://github.com/user-attachments/assets/81a975b3-dc2a-48ca-98bd-3ac91423b7a0\" /\u003e\n\n---\n\n## 🏗️ System Architecture\n\nThe application is split into a React-based frontend engine and a Python/SQLAlchemy backend (found in the [`choose-your-adventure`](https://github.com/4ssh1/choose-your-adventure) repository). \n\nInstead of generating the story node-by-node on the fly, the system generates the **entire branching narrative tree** upfront. This ensures narrative consistency, guarantees winning/losing paths, and allows for zero-latency node traversal on the client side.\n\n### How It Works\n\n1. **Prompt \u0026 Job Creation:** The user submits a theme (e.g., \"The Haunted Manor\"). The frontend sends this to the backend, which spawns an asynchronous background job.\n2. **LLM Generation:** The backend queries the Groq API (using `llama-3.3-70b-versatile`). It uses strict system prompts and Pydantic models to force the LLM to output a deeply nested, multi-level JSON tree with guaranteed ending conditions.\n3. **Data Flattening \u0026 Persistence:** Because SQL databases are relational, the backend intercepts the deeply nested JSON tree and iterates through it. It saves each scene as a distinct `StoryNode` and maps the relationships, effectively \"flattening\" the tree into a highly queryable dictionary of nodes.\n4. **Client-Side Engine:** Once polling confirms the background job is complete, the frontend fetches the complete, flattened story object. The React app then takes over entirely, rendering the text via a typewriter effect and handling the logic to jump from node ID to node ID based on user input.\n\n---\n\n## 📡 Frontend-Backend Communication\n\nThe frontend communicates with the `choose-your-adventure` backend using an asynchronous polling mechanism to accommodate the time it takes the LLM to write a full branching story.\n\n* **`POST /api/jobs`**: The frontend sends the selected theme. The backend immediately returns a `job_id`.\n* **`GET /api/jobs/{job_id}`**: The frontend polls this endpoint every few seconds while rendering an atmospheric loading screen. \n* **`GET /api/stories/{story_id}`**: Once the job status is `completed`, the frontend fetches the full story payload.\n\n### The Data Contract\nTo bridge the gap between relational databases and a graph-like narrative, the backend serves the story in a flattened format. The frontend relies on this structure to traverse the game:\n\n```json\n{\n  \"title\": \"The Haunted Manor\",\n  \"root_node\": {\n    \"id\": 40,\n    \"content\": \"You stand before the crumbling entrance...\",\n    \"is_ending\": false,\n    \"is_winning\": false,\n    \"options\": [\n      { \"node_id\": 41, \"text\": \"Investigate the study\" },\n      { \"node_id\": 64, \"text\": \"Explore the hallway\" }\n    ]\n  },\n  \"all_nodes\": {\n    \"40\": { \"id\": 40, \"content\": \"...\", \"options\": [...] },\n    \"41\": { \"id\": 41, \"content\": \"...\", \"options\": [...] }\n  }\n```\n\nWhen a user clicks an option, the frontend looks up the corresponding node_id within the all_nodes dictionary to load the next scene.\n\n### 🎮 Gameplay Features \u0026 UX\nThe frontend isn't just a text reader; it acts as a lightweight RPG engine:\n\n- The Fate Meter: Behind the scenes, choices carry weight. A visual fate meter shifts colors (Green -\u003e Yellow -\u003e Red) based on the calculated risk of the user's path.\n\n- Candles (Lives): The UI displays 5 lit candles. Every choice made snuffs out a candle, enforcing the backend constraint that users must survive at least 3-5 choices to reach an ending.\n\n- Dynamic Atmospherics: Custom CSS animations control floating ash particles, shimmering cards, UI screen shakes on \"bad\" choices, and dynamic accent colors based on the user's chosen theme.\n\n### Prerequisites\nNode.js (v18+)\n\n### Clone the repository\n\n```bash\ngit clone https://github.com/4ssh1/fable-weaver.git\ncd fable-weaver\n```\n\nInstall dependencies\n\n```bash\nnpm install\n```\n\nSet your backend API URL in .env\n\nVITE_API_BASE_URL=http://localhost:8000\nCode snippet\n\n```bash\nnpm run dev\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4ssh1%2Ffable-weaver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4ssh1%2Ffable-weaver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4ssh1%2Ffable-weaver/lists"}