DEV Community

AMAN BASOR
AMAN BASOR

Posted on

Week-4 DEV challenge

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission 👻🌼

What I Built

I built the 🎃 Horror Story Generator — a fully browser-based web app that lets you craft personalized, spine-chilling horror stories powered by Google’s open Gemma models via the Gemini API.

The “Ghost in the Machine” theme hit me immediately: what if the machine itself became the storyteller? What if you could whisper a few details into it — a name, a place, a face — and it breathed life into your worst nightmare? That’s the ghost: an intelligence hiding inside your browser, conjuring darkness on command.

You give it characters (with names and descriptions you define), choose a creepy setting like “an abandoned hospital” or “a fog-drenched village”, pick how long you want the terror to last, and hit 🕯️ Generate Horror Story. Then you watch the story stream out token by token — like something typing at you from the other side.

Features:

🔍 Auto-detection of Gemma models — pastes your API key and the app queries the Gemini API live, ranking and pre-selecting the best available Gemma model (prefers gemma-3-27b-it down to gemma-3-1b-it)
🧑‍🤝‍🧑 Custom characters — add, edit, or remove characters with names and descriptions
📏 Story length control — Short (~200 words) to Epic (~2000 words)
🏚️ Custom setting — you define the atmosphere
⌨️ Real-time streaming — SSE streaming so the story types itself out with a blinking cursor
🎨 Full horror aesthetic — floating red ember particles, Creepster typography, deep dark UI
Code

link - https://github.com/amanbasor/horror-story-generator

How I Built It

The project is built entirely with vanilla HTML, CSS, and JavaScript — zero frameworks, zero build tools, zero dependencies to install. Just open index.html and it works.

The open-source AI at the core: Google Gemma

Gemma is Google’s family of open-weight models derived from the same research behind Gemini. They’re open — you can run them locally with tools like Ollama or LM Studio, inspect their weights, fine-tune them, and deploy them however you want. In this app, I use them through the Gemini API (which gives free-tier access), but the model itself is open-weight.

How the AI integration works:

Model discovery — On API key input, the app hits generativelanguage.googleapis.com/v1beta/models and filters for Gemma models that support generateContent, then ranks them by capability (27B → 12B → 4B → 1B) and auto-selects the best one available to you.
Prompt engineering — A structured prompt is built from the user’s characters, setting, and length preference. It instructs Gemma to write with suspense, realistic dialogue, vivid sensory detail, and an unsettling twist — and to lead with a creative horror title.
Streaming via SSE — The app calls models/model, reads the response body as a ReadableStream, decodes SSE events chunk by chunk, and renders each token to the story box in real time — complete with a blinking cursor while it’s typing.
GitHub Copilot assisted throughout the development — helping autocomplete event handler logic, refine the SSE parsing loop, and suggest CSS animation keyframes for the particle system and streaming cursor.

Stack:

HTML5 / CSS3 / Vanilla JS (ES2020+)
Fetch API + ReadableStream (for SSE)
Google Gemini API (models.list + streamGenerateContent)
Gemma open-weight models (auto-detected)
Google Fonts (Creepster for the horror title, Inter for body)
Why Does Open Innovation Matter?

A closed API would have handed me one model, at one price, with no insight into what’s running under the hood.

Open Gemma changed the entire shape of what I built:

  1. Model flexibility without a rewrite. Because Gemma models are queryable and openly listed, I could write a live auto-detection system. The app doesn’t hardcode a model name — it asks the API “what Gemma models do you have?” and adapts. A closed system would never let me do that; I’d be locked to whatever name the provider exposes.

  2. Free-tier access with open-weight backing. The free Gemini API tier gives access to Gemma models. That meant I could build and ship this without spending a rupee. A closed GPT-4 equivalent would have made this project financially inaccessible for a student building on weekends.

  3. Trust and transparency. When the story takes a dark, creative turn, I know the family of model behind it. Open weights mean the research community can audit, fine-tune, and understand the model’s behavior. That matters for creative tools where you want predictable, imaginative (not harmful) output.

  4. Local inference as the future escape hatch. Right now the app uses the cloud API — but because Gemma is open-weight, a user could swap the endpoint to a local Ollama instance running gemma3:27b and the app would work identically, completely offline. That’s only possible because the model isn’t locked behind a proprietary wall.

Open innovation didn’t just make this cheaper. It made it architecturally better — more adaptive, more transparent, and more future-proof.

The Spirit of It

The first time I tested the finished streaming feature, I typed in two characters — Anya (a curious college student) and Mr. Hollow (a mysterious old caretaker) — set the location to “an abandoned university library after midnight”, and hit generate.

I watched the title appear first: “The Catalogue of Lost Souls”

Then the story started typing itself. Sentence by sentence. A flickering light. Footsteps on the floor above. Anya finding a book with her own name on the spine — dated 1987.

Nobody was in the room with me. It was past 1 AM. And for a second — just a second — I genuinely didn’t want to scroll down to see how it ended.

That’s the ghost in the machine. It was there the whole time.

Prize Categories
Gemma — The app is built around Google’s open Gemma models as its AI core, with live model auto-detection, capability-ranked model selection, and SSE-streamed story generation using Gemma via the Gemini API.
GitHub Copilot — GitHub Copilot was used throughout development to assist with JavaScript logic, SSE stream parsing, and CSS animations, accelerating the build significantly.

Top comments (0)