paper-aquarium logo

paper-aquarium

Бумажная раскраска превращается в 3D-рыбу: ребёнок раскрашивает лист, фотографирует телефоном — и рыбка плывёт в аквариуме на большом экране. Node без зависимостей + three.js.

Developer ToolsJavaScriptMIT 257 50
Website GitHub

What is it?

What it is

A home game for children that bridges physical coloring sheets and a digital aquarium on a big screen. Children print A4 sheets, color them with markers, photograph with a phone, and their drawings become 3D fish swimming in a web-based aquarium built with three.js.

Why it exists

To provide a creative, screen-time hybrid experience that combines traditional coloring with digital animation, inspired by teamLab's Sketch Aquarium, while prioritizing child privacy with no accounts, local-network-only access, and password-protected irreversible actions.

Who should use it

Families with young children (ages 3-10) seeking interactive art activitiesSchools and kindergartens looking for creative digital projectsDevelopers interested in marker-based computer vision and 3D renderingCreative technologists studying texture extraction from hand-drawn imagesEvent organizers planning children's interactive installationsUsers who want to self-host a family-friendly web application

Who should avoid it

Non-technical users wanting an out-of-the-box experienceUsers without budget for the required 3D fish model pack (CGTrader)Those seeking a mobile app (this is web-based requiring server setup)Users unwilling to work with Docker, Node.js, and command-line toolsAnyone expecting a fully functional product without purchasing assets separatelyUsers on shared hosting without ability to run Node servers

Stars over time

No change stars in the last 1 day

257257
Aug 30, 2026Aug 30, 2026

How it works

A quick walkthrough in plain English

How paper-aquarium works

Step 1 of 3

You interact with it

Open paper-aquarium, send a request, or connect it to your stack.

Features

A4 coloring sheet to 3D fish pipeline via phone photo
Corner markers for species encoding and perspective correction
Plain Node.js server with zero runtime dependencies
Three.js based 3D aquarium scene
Trilingual support (English, Russian, Polish)
Internationalization via assets/i18n.js and data-t attributes
12 A4 coloring sheets in three languages with manifest
Aquarium volume follows camera frustum instead of box
Auto fish orientation from tail animation analysis
Menu with capture, ready-made fish, food, sheets, background, removal
QR code, link, and five-digit TV code for multi-screen access
Embedded pages (?embed=1) for capture, background, sheets
SHOWCASE mode with AQUA_DEMO_TANK variable
10-character aquarium code serving as address
Password-free capture and feeding for child-friendly use
Password-protected admin actions (delete, rename, background)
Five-digit TV code (5 min TTL, memory-only) for TV screens
Environment variable limits for multi-tenant deployment
File size limits: 3 MB fish, 6 MB background, 12 MB request body
Serves only listed static folders, 404 for everything else
Data stored in data/tanks/<code>/ with meta, settings, fish, backgrounds
30-day trash retention (AQUA_TRASH_DAYS) before permanent deletion
Terms and data page with GDPR rights and contact
Server keeps no access log (proxy may)
MIT licensed code
Toolchain: silhouettes, sheet maker, PDF, capture test, pack converter
Data folder not in repo, is family-specific backup

Advantages

  • Zero dependencies, easy deployment with plain Node
  • Child-friendly: no accounts, password-free capture/feeding
  • Trilingual with automatic device language detection
  • Secure by design: codes are long, passwords protected by growing pause
  • Showcase mode helps newcomers discover live aquariums
  • Flexible model pipeline: any .glb/.gltf can be added manually
  • Full toolchain for customizing sheets, silhouettes, and packs
  • Data privacy: server stores no access logs
  • Trash recovery system respects children's drawings
  • Docker/Traefik deployment ready with environment variables

Disadvantages

  • Fish models must be purchased separately, not included or redistributable
  • FBX-to-glTF conversion requires Windows and PowerShell
  • Conversion script tailored to Windows System.Drawing API
  • Only 12 species supported in coloring sheets (matching models)
  • Limited to species with existing coloring sheets; new ones require rebuild
  • Server serves only explicitly listed static folders (restrictive)
  • Password travels in plain text X-Tank-Pass header (needs HTTPS proxy)
  • Environment variable limits prevent abuse on public servers
  • Conversion drops 2 of 30 pack fish (no embedded textures/empty geometry)
  • Trash retention could accumulate data on long-running public servers

Installation

docker

docker compose -f docker-compose.prod.yml --env-file .env up -d --build

native

node server.js

compose

docker compose -f docker-compose.prod.yml --env-file .env up -d --build

FAQ

What are the system requirements to run Paper Aquarium?

You need Node.js 18 or newer. There are no npm dependencies to install — the server is plain Node with zero dependencies, and three.js is bundled in the vendor/ folder. Just clone the repository and run 'node server.js' to start the aquarium on http://localhost:8000.

How do I get the fish models into the aquarium?

The fish models are not included in the repository because they are a purchased pack with a license that forbids redistribution. You must buy the 'Coral Reef Fish Collection animated — Game Ready pack 8' by JosKata on CGTrader, then place the fbx folder into a directory (e.g., 'купил 3д рыбок/fbx/'). Convert them to glTF using the provided PowerShell script (tools/convert-pack.ps1) which requires installing fbx2gltf. The converted models go into assets/models/pack/. Without the models, the aquarium starts but stays empty.

How does the colouring sheet recognition work?

Each A4 colouring sheet has four black 6×6 markers in the corners. The 16 inner cells of each marker encode the fish species and corner number. During capture, the system detects these markers by sweeping brightness thresholds, undoes the perspective distortion, cuts the drawing along the species contour from the manifest, and trims a strip along the printed line to create a clean texture. The markers must remain uncoloured for recognition to work.

How do I deploy Paper Aquarium to the internet?

Use the provided Dockerfile and docker-compose.prod.yml. Copy .env.example to .env and set your DOMAIN, then run 'docker compose -f docker-compose.prod.yml --env-file .env up -d --build'. The setup uses Traefik as a reverse proxy on an external 'web' network for HTTPS, domain, and certificate handling. The model pack is mounted as a volume and never enters the Docker image. See DEPLOY.md for detailed deployment steps.

How does access control work for aquariums?

There are no user accounts. Each aquarium has a 10-character code (also its URL) and an optional password. With just the code, you can watch the aquarium, add fish, feed them, and change the background. The password is required to delete fish, delete the aquarium, or rename it. Capture and feeding are deliberately password-free so children can use them easily. Passwords are stored as salted scrypt hashes and travel in the X-Tank-Pass header (HTTPS is mandatory on public servers).

What data is stored and how is privacy handled?

All data lives in data/tanks/<code>/ directories containing meta.json, settings.json, fish drawings, backgrounds, and preview images. Deleted items move to trash/ and data/trash-tanks/ for 30 days (configurable via AQUA_TRASH_DAYS) before permanent deletion. The server keeps no access logs — it only records anonymous events like 'a fish was added to aquarium X'. For public servers, there is a /terms.html page explaining data storage, retention, GDPR rights, and deletion procedures. The entire data/ folder is not part of the repository and serves as the backup.

Loading documentation…
View on GitHub

Featured in Videos

YouTube tutorials and walkthroughs for paper-aquarium

Alternatives

Similar projects ranked by category, topics, and text overlap.

Compare