• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
laurynas

laurynas

saulyte

Public
Like
saulyte
Home
Code
7
.claude
1
backend
1
frontend
3
.vtignore
CLAUDE.md
README.md
deno.json
Branches
1
Pull requests
Remixes
History
Environment variables
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
CLAUDE.md
Code
/
CLAUDE.md
Search
6/13/2025
Viewing readonly version of main branch: v113
View latest version
CLAUDE.md

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is a Photography Weather Dashboard called "Kur saulytė?" - a dense, mobile-first weather website designed for photographers to quickly check upcoming weather conditions with focus on cloud cover, visibility, and lighting conditions. The app provides hourly weather data for 7 days with photography-specific scoring and golden hour detection.

Technology Stack

  • Runtime: Deno (Val Town platform)
  • Backend: Hono web framework
  • Frontend: React 19 with TypeScript
  • Styling: CSS with responsive grid layouts
  • Data Source: Open-Meteo KNMI API (no API key required)

Project Structure

├── backend/
│   └── index.ts          # Hono server with Open-Meteo SDK integration
├── frontend/
│   ├── index.html        # Main HTML page
│   ├── index.tsx         # React app with weather dashboard UI
│   └── style.css         # Mobile-optimized styles with responsive grid
├── deno.json            # Deno configuration
└── README.md

Key Architecture Components

Backend (backend/index.ts)

  • Hono server with error unwrapping for better debugging
  • Static file serving using Val Town utilities (serveFile, readFile)
  • Three main API endpoints:
    • /api/weather?lat={lat}&lon={lon} - Weather data with photography insights
    • /api/location - Auto-detect location from IP with Amsterdam fallback
    • /api/geocode?q={query} - Search locations by city/area name
  • Photography scoring algorithm that calculates 1-10 ratings based on:
    • Cloud cover percentage (main factor)
    • Visibility in kilometers
    • Precipitation levels
    • Golden hour timing (±1 hour from sunrise/sunset)

Frontend (frontend/index.tsx)

  • React 18.2.0 with TypeScript interfaces
  • Responsive grid layout: 6 → 8 → 12 → 24 columns based on screen size
  • Key features:
    • Auto-location detection with manual override
    • Real-time city/area search with geocoding
    • Past day minimization (auto-collapses with toggle)
    • Golden hour highlighting with special visual indicators
    • Cloud layer visualization (low/mid/high altitude)
    • Photography score bars and condition emojis

Core Data Flow

  1. Location Detection: Auto-detect via IP or manual search/coordinates
  2. Weather Fetch: Query Open-Meteo KNMI API with comprehensive hourly data
  3. Photography Analysis: Generate insights with scoring algorithm
  4. UI Rendering: Display in responsive grid with day/night distinction

Development Commands

Since this is a Val Town project, there are no traditional build commands. Development happens directly on the platform.

Val Town Standard Libraries

When extending this project, you can use Val Town's hosted services:

Blob Storage

Create val
import { blob } from "https://esm.town/v/std/blob"; await blob.setJSON("myKey", { hello: "world" }); let data = await blob.getJSON("myKey"); let keys = await blob.list("app_"); await blob.delete("myKey");

SQLite Database

Create val
import { sqlite } from "https://esm.town/v/stevekrouse/sqlite"; const TABLE_NAME = 'weather_cache_1'; // Create table - change table name when modifying schema await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( id INTEGER PRIMARY KEY AUTOINCREMENT, location TEXT NOT NULL, data TEXT NOT NULL, timestamp INTEGER )`); const result = await sqlite.execute(`SELECT * FROM ${TABLE_NAME} WHERE location = ?`, ["Amsterdam"]);

Email Notifications

Create val
import { email } from "https://esm.town/v/std/email"; await email({ subject: "Weather Alert", text: "Perfect photography conditions detected!", html: "<h1>Perfect photography conditions detected!</h1>" });

OpenAI Integration

Create val
import { OpenAI } from "https://esm.town/v/std/openai"; const openai = new OpenAI(); const completion = await openai.chat.completions.create({ messages: [{ role: "user", content: "Describe this weather for photography" }], model: "gpt-4o-mini", max_tokens: 100, });

Key Development Patterns

Val Town Specific

  • Use https://esm.sh for all imports to ensure browser/server compatibility
  • Pin React dependencies to version 18.2.0
  • Always include /** @jsxImportSource https://esm.sh/react@19 */ at top of React files
  • Use environment variables with Deno.env.get() for secrets (never bake into code)

Photography Logic

  • Golden Hour Detection: ±1 hour window around sunrise/sunset times
  • Scoring Algorithm: 10-point scale with cloud cover as primary factor
  • Day/Night Distinction: Only show detailed data and scores for daylight hours
  • Condition Mapping:
    • Excellent (☀️): <20% clouds
    • Very Good (🌤️): 20-40% clouds
    • Good (⛅): 40-60% clouds
    • Fair (☁️): 60-80% clouds
    • Poor (☁️): >80% clouds
    • Golden Hour (🌅): Special case for optimal lighting

UI/UX Patterns

  • Mobile-first design with responsive breakpoints
  • Stable grid positioning - time always at top, cloud % prominent
  • Toned-down color palette with colored left borders for scanning
  • Progressive enhancement - works without JavaScript for basic weather
  • Past day minimization - auto-collapse old data with expand option

Important Constraints

Platform Limitations (Val Town)

  • Text files only (no binary uploads)
  • Serverless Deno environment
  • No Node.js APIs available
  • Cannot use alert(), prompt(), or confirm()
  • Use return new Response(null, { status: 302, headers: { Location: "/path" }}) for redirects
  • DO NOT use Deno KV module for storage
  • Use Response.redirect() is broken - use manual redirect headers instead
  • Add <script src="https://esm.town/v/std/catch"></script> to HTML for client-side error debugging

Code Standards

  • TypeScript required with strict interfaces
  • Functional programming preferred over classes
  • No external images - use emojis, Unicode symbols, or icon fonts
  • Error handling: Let errors bubble up with context rather than catching/logging
  • Never include secrets in code - always use environment variables
  • Prefer official SDKs over writing API calls directly
  • Comments: Only explain complex logic, avoid commenting obvious operations
  • Complete solutions: Provide functional implementations, not skeleton code

Hono Framework Specifics

  • NEVER use serveStatic middleware - it doesn't work on Val Town
  • Always use Val Town utilities: import { readFile, serveFile } from "https://esm.town/v/std/utils/index.ts"
  • NEVER import CORS middleware - Val Town handles CORS automatically
  • For cookies: import { deleteCookie, getCookie, setCookie } from "npm:hono/cookie"
  • Always add error unwrapping:
    Create val
    app.onError((err, c) => { throw err; });

Data Sources and APIs

  • Weather: Open-Meteo KNMI API (free, no API key)
  • Geocoding: Open-Meteo Geocoding API (free, no API key)
  • Location: ip-api.com for IP-based location detection
  • Fallback: Amsterdam coordinates (52.3676, 4.9041) if detection fails

Val Town Trigger Types

This project uses HTTP triggers, but Val Town supports multiple trigger types:

HTTP Triggers (Current Implementation)

Create val
export default async function (req: Request) { return new Response("Hello World"); }

Cron Triggers (For Scheduled Tasks)

Create val
export default async function () { // Could be used for weather data caching or alerts }

Email Triggers (For Email Processing)

Create val
export default async function (email: Email) { // Could process weather alert subscription emails }

Utility Functions

Always import with version pins:

Create val
import { readFile, serveFile, listFiles } from "https://esm.town/v/std/utils@85-main/index.ts";

Important: These utilities ONLY run on the server. Pass data to client via HTML injection or API calls.

Testing and Deployment

This is a Val Town project that auto-deploys on save. No traditional CI/CD pipeline.

For local development testing:

  • Test location detection with different IP ranges
  • Verify geocoding search with various city names and coordinates
  • Test responsive design across mobile/tablet/desktop breakpoints
  • Validate photography scoring algorithm with edge cases (100% clouds, 0% clouds, etc.)

Common Val Town Gotchas

  1. SQLite Schema Changes: Change table names instead of using ALTER TABLE
  2. Shared Code: Code in shared/ must work in both frontend and backend (no Deno keyword)
  3. File Handling: Only text files supported, use readFile helpers for project files
  4. Images: Use AI image generation: <img src="https://maxm-imggenurl.web.val.run/description" />
  5. Default Styling: Use TailwindCSS via <script src="https://cdn.twind.style" crossorigin></script>
FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
ExploreDocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Terms of usePrivacy policyAbuse contact
© 2025 Val Town, Inc.