DEV Community

Cover image for Building Thermal Guilt: A Solana-First Gamified Energy App
Harish Kotra (he/him)
Harish Kotra (he/him)

Posted on

Building Thermal Guilt: A Solana-First Gamified Energy App

DEV Weekend Challenge: Earth Day

This is a submission for Weekend Challenge: Earth Day Edition

What I Built

I built Thermal Guilt: a gamified smart-energy dashboard that turns HVAC efficiency into a social + economic game.

The core mechanic is a “thermal ghost” for each household:

  • If your usage is significantly above neighborhood behavior, your ghost trends red and your leaderboard rank drops.
  • If you stay efficient, you earn $COOL rewards on Solana Devnet.

My goal was to make energy behavior change feel immediate and engaging, not passive. Instead of just showing charts, the app combines:

  • peer pressure (anonymized leaderboard),
  • AI coaching (personalized suggestions),
  • and crypto rewards (verifiable claim flow).

It’s playful on purpose, but technically serious underneath.

Demo

Code

How I Built It

I implemented Thermal Guilt as a monorepo with shared domain logic and provider adapters so each integration is replaceable without rewriting app logic.

Architecture

  • Frontend: Next.js 14 App Router + Tailwind + Framer Motion + Recharts
  • Backend: Node.js + Express + TypeScript
  • Shared logic: score + ghost + reward rules in one package reused by UI and API
  • AI: Backboard orchestration + Gemini analysis
  • Auth: Auth0 user auth + M2M + scoped access model
  • Blockchain: Solana Devnet + SPL token claim flow (wallet-signed)

Core implementation decisions

  1. Single-source scoring logic I put score and reward logic in a shared package to prevent drift between what users see and what payouts do.
export function scoreToTokenReward(score: number): number {
  if (score >= 95) return 100;
  if (score >= 85) return 50;
  if (score >= 70) return 20;
  if (score >= 50) return 5;
  return 0;
}
Enter fullscreen mode Exit fullscreen mode
  1. Wallet-signed on-chain claims (non-custodial UX) The backend prepares and partially signs claim transactions using treasury authority. The user signs in Phantom/Backpack, then backend relays the signed tx.
const txPayload = await apiPost("/api/solana/claim/transaction", { walletAddress, score });
const tx = Transaction.from(Buffer.from(txPayload.serializedTransaction, "base64"));
const signed = await wallet.signTransaction(tx);
await apiPost("/api/solana/claim/submit", {
  signedTransaction: signed.serialize().toString("base64")
});
Enter fullscreen mode Exit fullscreen mode
  1. Provider adapter pattern
    I isolated integrations into service adapters (auth0, backboard, gemini, solana, snowflake) so I can switch providers or fallback modes cleanly.

  2. Fast local onboarding
    Snowflake is currently disabled by default for easy local execution. The app still runs fully with simulated energy data and real Solana claims on Devnet.

  3. Mint bootstrap automation
    I added a one-shot script to create $COOL mint + treasury ATA + initial supply:

npm --workspace @thermal-guilt/api run solana:bootstrap-mint -- --supply 10000000 --decimals 6
Enter fullscreen mode Exit fullscreen mode

This prints .env values to paste directly.

APIs implemented

  • /api/energy/current
  • /api/energy/history
  • /api/ai/chat
  • /api/ai/ghost-analysis
  • /api/leaderboard/*
  • /api/solana/claim/transaction
  • /api/solana/claim/submit

UX

  • Animated thermal ghost card
  • Neighborhood heatmap-style ghost map
  • AI coach panel
  • Wallet connect + token claim
  • Leaderboard + score trend visuals

Prize Categories

I’m submitting this project to:

  • Best Use of Backboard
  • Best Use of Auth0 for Agents
  • Best Use of Google Gemini
  • Best Use of Solana
  • Best Use of GitHub Copilot

(Snowflake integration is implemented in the architecture and service layer, and can be switched on with env configuration. )

Output Demo

Top comments (0)