Constellation of Hope - Build Small

Community Article
Published June 15, 2026

The moment that made me build it

A small, contemplative web app you could share with someone going through something hard, or with yourself at 2am, and feel a little less alone in. The result is Constellation of Hope — a Hugging Face Space where every wish becomes a star in a Three.js sky, every star has a saying, and every saying can be spoken aloud in a whisper. The idea is simple, and not a place you might spend a ton of time on but taking a moment and wishing for the best is always a self reminder.

What it does

CleanShot 2026-06-15 at 12.49.21

The interaction loop is intentionally simple.

You type a wish into a box: "I hope my family finds peace this year." You press a button labeled Release your wish to the stars. A small modal floats up — your wish drifts toward the stars… — while the model thinks. A few seconds later, a new star appears somewhere on a sphere of soft, pulsing lights, and the camera glides over to meet it. A halo flickers around it, golden, until you click it. Click and a card opens: your wish, the poetic saying the model wrote for it, the category it belongs to (Shape · self-change, Boon · gifts, Journey · travel, Bond · connections, or Tribute · giving), and the date it joined the sky. Press Play wisdom and a banner appears at the top of the form: Now whispering. The saying is read aloud in a soft voice that's been deliberately quieted, the way you might read a poem to someone half-asleep.

CleanShot 2026-06-15 at 12.49.28

Wishes that arrive vulgar or cruel are quietly reshaped into a kinder form before they become stars — the model rewrites them, and a Gentle Pause modal shows you the original and the rewrite side by side. Wishes that arrive as gibberish prompt a different modal that just asks, gently, for a real hope. The sky only ever holds wishes that feel like wishes.

Nearby stars connect into small constellations of up to five, drawn in pale lines that fade into the dust. Colors are deterministic by category, so over time the sky reads as five themed regions — a galaxy of gifts here, a constellation of journeys there.

Behind the constellation

The stack is deliberately small.

The UI is Gradio 6, which handles the wish form, the modals, the audio bridge, and the state. The starscape is a custom Gradio component that wraps a Three.js scene; it watches Gradio's component value and diffs against an internal Map of star groups, adding new meshes as they arrive from the server.

Each star is drawn with a hand-written GLSL shader. The core is a smooth sphere with a Fresnel rim — brighter at the silhouette, dimmer where it faces the camera — which gives the impression of a small atmosphere. On top of that, a three-octave value-noise fBm samples the star's local surface to create gentle dappled highlights, drifting slowly with time so each star shimmers rather than sits. Every star gets a unique random seed in its uniforms so the pulses are phase-offset; the sky breathes, but never in unison.

Two models do the actual cognitive work, both small enough to live on Hugging Face's free ZeroGPU tier:

Role Model
Moderation, categorization, and poetic generation Qwen/Qwen2.5-1.5B-Instruct
Whispered text-to-speech hexgrad/Kokoro-82M

Qwen does two passes per wish: a single combined call that returns both the moderation verdict (POSITIVE / NEGATIVE / NONSENSE) and the thematic category, plus a separate generation call for the saying. Both are wrapped in @spaces.GPU so the GPU only spins up when there's actually work to do — important on a free tier.

Kokoro is the TTS layer. I picked the af_nicole voice, dropped the speed to 0.85×, and multiplied the output amplitude by 0.55. There's no literal whisper mode, but the combination feels close enough — a voice that's trying not to wake anyone.

Persistence lives at /data/stars.json on a Hugging Face Persistent Storage volume, written atomically so a crash mid-save can't corrupt the constellation. Without that volume the code falls back to an in-container file and the sky resets on every restart, which I learned the hard way.

The model we didn't ship

The first version of this app was supposed to run on NVIDIA Nemotron 3 Nano 4B FP8 — it was the right size and the right vibe. It also turned out to be a Mamba-hybrid model, which meant it needed mamba-ssm and causal-conv1d to run under transformers. Those are CUDA-compiled extensions. The HF Spaces build image doesn't ship nvcc, so they can't compile from source; and pre-built wheels don't yet exist for the torch==2.12.0+cu130 that the ZeroGPU runtime installs.

I spent an evening trying to make it work. I considered switching to a Dockerfile-based Space with vLLM (NVIDIA's recommended path), but vLLM holds a model in VRAM continuously and ZeroGPU loans a GPU per-call — they're architecturally incompatible. The pragmatic answer was the boring one: swap to a model the runtime can actually serve. Qwen2.5-1.5B-Instruct loaded in seconds with no extra dependencies, and the output is — honestly — indistinguishable for this use case. A 1.5B instruct model is more than enough to write a one-sentence poetic saying about a stranger's hope.

The takeaway I'd offer: when you're picking a model for a Space, the architecture matters more than the headline benchmarks. Pure transformers ship in five minutes; anything exotic — Mamba, MoE, custom kernels — will eat your weekend.

What's next

A few ideas I'm holding loosely:

  • Shareable star permalinks (?star=<id>) so a wish can travel beyond the Space.
  • Category-clustered placement so each theme has its own visual region of the sky.
  • A soft ambient bed under the whisper, so the TTS feels less abrupt.

If you build one, I'd love to see it. And if you want to try the app — type a wish, watch a star appear, and listen to what it has to say.


🌌 Try it: huggingface.co/spaces/cdr6934/ConstellationOfHope 💫 Source: open on the Space's Files tab.

Community

Sign up or log in to comment