DEV Community

hinezi
hinezi

Posted on

I built a collaborative pixel art game in a bottle — with 0 npm dependencies

Dear Stranger collaborative pixel art card

🌊 What is Dear Stranger?

I recently launched Dear Stranger (dearst.app) — a cozy, anonymous, collaborative pixel art web game.

The concept is inspired by the old tradition of casting a message in a bottle into the ocean:

  1. Cast a bottle: You start by drawing a few pixel strokes on a small canvas (or choose from 8 classic masterpieces like Van Gogh's Starry Night or Monet).
  2. Drift across the sea: Your bottle travels across the world to strangers.
  3. Collaborate: 2 to 4 strangers take turns painting their fair share.
  4. Returns home: Once complete, the bottle journeys back to everyone who participated, complete with a celebratory replay of each painter's strokes and a travel map showing the countries it sailed through!

Play it directly in your browser (no sign-up required):
👉 https://dearst.app


🛠️ The Tech Stack: Exactly 0 npm dependencies

As web developers in 2026, our node_modules folders often weigh hundreds of megabytes just to render a button. For Dear Stranger, I set a personal challenge:

Can we build a full-featured, persistent, real-time multiplayer collaborative web app with ZERO external npm dependencies?

The answer is yes.

1. Pure Vanilla JS on the Frontend

  • Zero build tools: No Webpack, Vite, or Babel. Browsers have supported native ES modules for years.
  • HTML5 Canvas & SVG: Custom pixel manipulation, touch-enabled zooming/panning, and color palette sampling.
  • Dynamic Voyage Map: Natural Earth 1:50m geographic landmass rasterized into an ultra-compact dot grid rendered with pure SVG paths and beacons.

2. Node.js Built-in Standard Library on the Backend

  • Built on Node's native HTTP server and node:crypto.
  • Pure Web Push: RFC 8291 payload encryption and RFC 8292 VAPID signatures implemented purely with node:crypto — no web-push npm package required.
  • SQLite with WAL mode: Fast, zero-config persistent storage with foreign keys and immediate transactions.

3. Internationalization (i18n) from Day One

The game natively supports 5 languages:

  • 🇰🇷 Korean
  • 🇺🇸 English
  • 🇫🇷 French
  • 🇯🇵 Japanese
  • 🇨🇳 Chinese

Even the system NPC (Lighthouse · Keeper) and world country labels dynamically localize using the native Intl.DisplayNames API!


🎨 Game Design: Solving the "Trolling & Slacking" Problem

Collaborative art on the internet is notorious for two problems: trolls overwriting others' work and slackers drawing 1 pixel and dumping the rest on the next person.

Here is how Dear Stranger solves it through game mechanics:

  1. The 75% Fair Share Quota: Each painter receives an equal allocation of the remaining blank cells. You must fill at least 75% of your quota before the game lets you send the bottle onward.
  2. No Overwriting: Pixels already laid down by earlier strangers are immutable and locked.
  3. Report & Restoration (Kintsugi for pixels): If someone draws something offensive, any player can report that layer. The offender's layer is immediately hidden, and a blank space is created so another stranger can step in to restore the painting!

🖼️ What's next?

We launched with 8 classic museum masterpieces in both guided tracing mode and 64-pixel challenge mode. We plan to continuously add more classical artworks and community features.

Feel free to pick up a bottle, paint a few pixels, and see where your art travels:

🌊 Play the game: https://dearst.app

I’d love to hear your thoughts, feedback, and questions in the comments below!

Top comments (2)

Collapse
 
wordforge_jp profile image
WordForge •

0 npm dependenciesで、Web Pushの暗号化までnode:cryptoで実装された点に驚きました。依存関係を増やさない選択が、長期の運用やセキュリティ面でも効いてきそうです。75%のFair Share Quotaと上書き禁止の組み合わせも、「1ピクセルだけ描いて押し付ける」問題を仕組みで解決していて面白いと思いました。質問ですが、通報されたレイヤーの復旧は、参加者が任意のピクセルを描き直せる仕組みですか?それとも元の下絵に戻す形ですか?

Collapse
 
playonemore profile image
hinezi •

温かいコメントと技術的な部分まで細かく見ていただき、本当にありがとうございます!Web Pushの暗号化(RFC 8291)も外部ライブラリに頼らず標準モジュールだけで組み上げたので、そこに気づいて評価していただけてとても嬉しいです。

ご質問の「通報されたレイヤーの復旧」についてですが、結論から言うと【参加者が任意のピクセルを描き直せる仕組み】になっています!

具体的には以下のような流れです:

  1. 通報が一定数集まると、該当する荒らしレイヤーのみが非表示になり、その部分がキャンバスの「空白(穴)」になります(他の善良なレイヤーはそのままロック保護されます)。
  2. まだこの絵に参加していない第三の見知らぬプレイヤーが「復元(Restore)」として小瓶を引き取ることができます。
  3. 自由画の場合:参加者が自身のインスピレーションで空白部分に自由にピクセルを描き足し、絵を完成させます。
  4. 名画モードの場合:原画のカラーパレットと一致率基準(70% / 30%)を満たすように空白を補完します。

機械的に下絵にロールバックするのではなく、「傷ついた作品を別の見知らぬ誰かが手作業で修復してあげる」という温かい協同体験を目指してこのような仕様にしました。

興味を持っていただき、重ねて感謝申し上げます!