<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chris</title>
    <description>The latest articles on DEV Community by Chris (@chrisbuildsonline).</description>
    <link>https://dev.to/chrisbuildsonline</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3499535%2F2881d626-dfa8-4d58-9743-75d025b9f7e7.png</url>
      <title>DEV Community: Chris</title>
      <link>https://dev.to/chrisbuildsonline</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chrisbuildsonline"/>
    <language>en</language>
    <item>
      <title>Building 1000 Candles: A Digital Memorial That Taught Me About Scale, Optimization, and Remembrance</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Thu, 20 Nov 2025 17:12:25 +0000</pubDate>
      <link>https://dev.to/chrisbuildsonline/building-1000-candles-a-digital-memorial-that-taught-me-about-scale-optimization-and-remembrance-3ok3</link>
      <guid>https://dev.to/chrisbuildsonline/building-1000-candles-a-digital-memorial-that-taught-me-about-scale-optimization-and-remembrance-3ok3</guid>
      <description>&lt;p&gt;When I started building 1000 Candles for the Kiroween Hackathon, I thought I was just creating a cool 3D visualization. What I ended up with was something much more meaningful. A digital space where people can light virtual candles in memory of loved ones, and a deep dive into the challenges of building real-time, scalable web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept: A Graveyard of Light
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftj626mqwk5dkb9isrp3m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftj626mqwk5dkb9isrp3m.gif" alt=" " width="600" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea was simple but powerful. Create a haunting 3D graveyard where users can light candles with personal dedications. Each candle would glow with realistic flame physics, positioned among hundreds of others, creating a collective memorial that grows over time.&lt;/p&gt;

&lt;p&gt;But as any developer knows, simple ideas rarely stay simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack: Choosing the Right Tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt37d613mdr04gg2dgzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt37d613mdr04gg2dgzq.png" alt=" " width="316" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built 1000 Candles with Next.js 14, Three.js, and React Three Fiber for the 3D rendering. I wrote custom GLSL shaders for the flame effects because I wanted them to look really realistic. For the database, I used SQLite locally and Turso for production since it works great with serverless. Tailwind CSS handled the styling, and I added Tone.js for spatial audio to make it more immersive.&lt;/p&gt;

&lt;p&gt;The choice of Three.js was obvious. I needed real-time 3D rendering with good performance. But the database choice? That's where things got interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge #1: The Polling Problem
&lt;/h2&gt;

&lt;p&gt;Users needed to see new candles appear in real-time. My first approach? Poll the database every 5 seconds.&lt;/p&gt;

&lt;p&gt;With 100 concurrent users, that's 1,200 requests per minute, or 72,000 requests per hour. Each request fetches 200+ candle records. That's 14.4 million row reads per hour!&lt;/p&gt;

&lt;p&gt;On Turso, that would cost around $20 per month. Not terrible, but not great for a hackathon project.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Optimization Journey
&lt;/h3&gt;

&lt;p&gt;I explored several solutions. Server-Sent Events would be real-time but keeps serverless functions alive which costs money on Vercel. WebSockets would be perfect but they're not supported on Vercel serverless. Third-party services like Pusher or Ably are great but cost $29 to $49 per month.&lt;/p&gt;

&lt;p&gt;None of these felt right for a memorial site that should be simple and sustainable.&lt;/p&gt;

&lt;p&gt;Here's what I built. A metadata table with a single row storing the last candle timestamp. A lightweight endpoint that returns just this timestamp. localStorage to cache the last known timestamp. And smart polling that only fetches full data when the timestamp changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge #2: Making It Beautiful
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpckxo604lur1tjvfkqh8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpckxo604lur1tjvfkqh8.gif" alt=" " width="720" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The technical challenges were one thing, but this was a memorial site. It needed to feel special.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom GLSL Shaders
&lt;/h3&gt;

&lt;p&gt;I wrote custom vertex and fragment shaders for the candle flames:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Flickering flame effect&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;flicker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;glow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;flameColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;// Orange&lt;/span&gt;
  &lt;span class="kt"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;// Yellow&lt;/span&gt;
  &lt;span class="n"&gt;glow&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;flicker&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each flame flickers independently, creating a mesmerizing effect when you see hundreds of them together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Particle Systems
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feysqd0t0ebt2q2i7uqob.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feysqd0t0ebt2q2i7uqob.gif" alt=" " width="434" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I added atmospheric effects. Fireflies drifting through the scene. Falling leaves for autumn ambiance. Floating ash particles. Ground fog using volumetric techniques. And stars twinkling in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spatial Audio
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujh9233vhwh1e8jwsjac.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujh9233vhwh1e8jwsjac.gif" alt=" " width="594" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using Tone.js, I implemented spatial audio. Ambient wind sounds. Crackling fire positioned at each candle. Distant owl hoots. Rustling leaves. The audio responds to camera position, creating an immersive 3D soundscape.&lt;/p&gt;

&lt;p&gt;Lesson learned: Technical excellence means nothing if the experience doesn't move people.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge #3: Content Moderation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6c4m8g3x6rrj6c94mo8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6c4m8g3x6rrj6c94mo8s.png" alt=" " width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a public memorial. I needed to ensure respectful content without manual review.&lt;/p&gt;

&lt;p&gt;I integrated Pollinations AI for content moderation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;moderateContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dedication&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Is this memorial dedication appropriate and respectful?
  Dedication: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dedication&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
  From: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"

  Respond with YES or NO and a brief reason.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://text.pollinations.ai/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Parse AI response and validate&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system checks for inappropriate content and validates against spam patterns. If the AI is down, it fails open and allows the content through. Better to let something through than block legitimate memorials. It also provides helpful error messages when something is rejected.&lt;/p&gt;

&lt;p&gt;Lesson learned: AI moderation isn't perfect, but it's a good first line of defense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge #4: Rate Limiting
&lt;/h2&gt;

&lt;p&gt;To prevent abuse, I implemented server-side rate limiting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User sessions table&lt;/span&gt;
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;user_sessions &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;user_fingerprint&lt;/span&gt; &lt;span class="nx"&gt;TEXT&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;last_candle_lit_at&lt;/span&gt; &lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;daily_candle_count&lt;/span&gt; &lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;last_reset_date&lt;/span&gt; &lt;span class="nx"&gt;TEXT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use browser fingerprinting which is privacy-conscious. Daily limits are configurable via environment variables. Everything resets automatically at midnight. And when users hit the limit, they get helpful error messages showing exactly when they can light another candle.&lt;/p&gt;

&lt;p&gt;Lesson learned: Rate limiting is essential, but make it transparent and user-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The User Experience
&lt;/h2&gt;

&lt;p&gt;When you visit 1000 Candles, you see an intro sequence with typing animation. Then the 3D graveyard appears with a blood moon and atmospheric effects. Click "Light a Candle" to open the ritual modal. Enter your dedication and name. Watch your candle appear with a smooth camera animation. You can explore other candles with hover tooltips. And search for specific memorials by pressing F.&lt;/p&gt;

&lt;p&gt;The experience is designed to be respectful with somber colors and gentle animations. It's immersive with the 3D environment and spatial audio. It's accessible with keyboard shortcuts and mobile-friendly controls. And it's performant, running at 60fps even with over 1000 candles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Optimizations
&lt;/h2&gt;

&lt;p&gt;To render 1000+ candles at 60fps, I implemented:&lt;/p&gt;

&lt;h3&gt;
  
  
  Frustum Culling
&lt;/h3&gt;

&lt;p&gt;Only render candles visible to the camera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frustum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Frustum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;frustum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFromProjectionMatrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectionMatrix&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;candles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candle&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frustum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;containsPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Render this candle&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Level of Detail (LOD)
&lt;/h3&gt;

&lt;p&gt;Reduce geometry for distant candles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;distanceTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; 
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;lowPolyGeometry&lt;/span&gt; 
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;highPolyGeometry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Instancing
&lt;/h3&gt;

&lt;p&gt;Reuse geometries for multiple candles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instancedMesh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InstancedMesh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;candleCount&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: Smooth 60fps with over 1000 candles on mid-range hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Stuff
&lt;/h3&gt;

&lt;p&gt;Abstraction is powerful. The database adapter saved me countless hours. I learned to optimize for the common case because 99% of polls don't need full data. I also learned to measure before optimizing because I almost over-engineered the solution. Serverless has constraints but they force you to think differently. And localStorage is seriously underrated. It's simple, fast, and works everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Stuff
&lt;/h3&gt;

&lt;p&gt;Performance is a feature. Users notice lag, especially in 3D. Atmosphere matters. The audio and particles make it special. You have to respect the subject. This is a memorial, not a game. Accessibility counts. Keyboard shortcuts and mobile support aren't optional. And less is more. I removed features that didn't serve the core experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal Stuff
&lt;/h3&gt;

&lt;p&gt;Scope creep is real. I almost added multiplayer cursors which would have been cool but totally unnecessary. Deadlines help. The hackathon forced me to ship instead of endlessly tweaking. Community feedback is gold. Early testers found issues I completely missed. Documentation matters. Future me will thank present me. And most importantly, have fun. This was a joy to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;p&gt;After launch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;60fps&lt;/strong&gt; average framerate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;99.5% reduction&lt;/strong&gt; in database reads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0.10/month&lt;/strong&gt; database costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0 downtime&lt;/strong&gt; on Vercel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Countless memories&lt;/strong&gt; preserved&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Visit &lt;a href="https://1000candles.online" rel="noopener noreferrer"&gt;1000candles.online&lt;/a&gt; and light a candle for someone you remember.&lt;/p&gt;

&lt;p&gt;The code is open source: &lt;a href="https://github.com/chrisbuildsonline/1000candles" rel="noopener noreferrer"&gt;github.com/chrisbuildsonline/1000candles&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19kzs7lpe3hhbl06ndsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19kzs7lpe3hhbl06ndsu.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm considering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Candle colors&lt;/strong&gt; - Let users choose flame colors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared candles&lt;/strong&gt; - Multiple people can contribute to one candle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export memories&lt;/strong&gt; - Download a screenshot of your candle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seasonal themes&lt;/strong&gt; - Different atmospheres for holidays&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile app&lt;/strong&gt; - Native iOS/Android with AR features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But for now, I'm happy with what it is: a simple, beautiful space for remembrance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building 1000 Candles taught me that the best projects are the ones that solve real problems, even if that problem is just "I want a beautiful place to remember someone."&lt;/p&gt;

&lt;p&gt;The technical challenges were fun to solve, but what matters most is that people are using it. They're lighting candles for grandparents, friends, pets, and even abstract concepts like "hope" and "peace."&lt;/p&gt;

&lt;p&gt;That's the magic of the web: you can build something meaningful, deploy it globally, and watch it touch lives you'll never meet.&lt;/p&gt;

&lt;p&gt;If you're working on a hackathon project, remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start with why&lt;/strong&gt; - What problem are you solving?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ship early&lt;/strong&gt; - Perfect is the enemy of done&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize later&lt;/strong&gt; - But measure first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make it beautiful&lt;/strong&gt; - People remember how it feels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Have fun&lt;/strong&gt; - That's what hackathons are for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading, and thank you to the Kiroween Hackathon organizers for the inspiration.&lt;/p&gt;

&lt;p&gt;Now go light a candle. 🕯️&lt;/p&gt;




</description>
      <category>kiro</category>
      <category>webdev</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>HumanReplies: AI Social Replies for Everyone (No Paywall, No Barriers)</title>
      <dc:creator>Chris</dc:creator>
      <pubDate>Mon, 15 Sep 2025 15:51:38 +0000</pubDate>
      <link>https://dev.to/chrisbuildsonline/humanreplies-ai-social-replies-for-everyone-no-paywall-no-barriers-1amh</link>
      <guid>https://dev.to/chrisbuildsonline/humanreplies-ai-social-replies-for-everyone-no-paywall-no-barriers-1amh</guid>
      <description>&lt;h1&gt;
  
  
  HumanReplies: AI Replies for Everyone
&lt;/h1&gt;

&lt;p&gt;What if every social media user, no matter where they live or how much they spend, could access truly helpful AI tools to engage in conversations?  &lt;/p&gt;

&lt;p&gt;That question inspired me to create &lt;strong&gt;HumanReplies&lt;/strong&gt;. It makes fast, contextual, and customizable AI replies available to anyone—completely free, with privacy built in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Accessibility Matters
&lt;/h2&gt;

&lt;p&gt;Most AI tools are locked behind paywalls, subscriptions, or technical setups that make them inaccessible to everyday people. That’s a shame, because automation and smart assistance aren’t just for “power users.” They can help all of us participate more, respond faster, and keep up with the pace of real conversations.  &lt;/p&gt;

&lt;p&gt;With HumanReplies, I wanted to prove a different path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No paywall&lt;/strong&gt;  Every feature is free: reply generation, tone customization, analytics.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple setup&lt;/strong&gt;  Install the Chrome extension, log in, and you’re ready. No credit card, no hidden trial.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privacy first&lt;/strong&gt;  Nothing you write is stored. Only minimal usage stats are kept, and they’re visible to you.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open values&lt;/strong&gt;  Built in public, with transparency. You can see what’s coming next.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How I Used Kiro
&lt;/h2&gt;

&lt;p&gt;Kiro was the reason I could move fast enough to ship this project during the hackathon.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It generated boilerplate for my FastAPI backend, including secure API routes and authentication.
&lt;/li&gt;
&lt;li&gt;It scaffolded database models and endpoints from short specs, saving days of manual coding.
&lt;/li&gt;
&lt;li&gt;It automated setup tasks and let me focus on what mattered: making HumanReplies simple and accessible.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I experimented with other AI coding tools like Claude Code and ChatGPT for brainstorming, but they couldn’t keep up with the hackathon’s requirements—especially around spec-to-code fidelity and backend integrations. Kiro became my main IDE because it actually delivered production-ready results.  &lt;/p&gt;




&lt;h2&gt;
  
  
  The Result: Open, Accessible, Useful for All
&lt;/h2&gt;

&lt;p&gt;HumanReplies is my submission to &lt;strong&gt;#kiro&lt;/strong&gt;. It proves that AI UX can be accessible, ethical, and fun for everyone—not just for big spenders or people willing to trade their privacy.  &lt;/p&gt;

&lt;p&gt;I hope you’ll check it out and see how it makes replying online faster, more human, and more engaging.  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://humanreplies.com" rel="noopener noreferrer"&gt;Chrome Extension &amp;amp; Demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
    </item>
  </channel>
</rss>
