Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
See how today's temperature compares to the same date over the past 50 years for your location.
LifestyleTypeScript · HTMLGitHub @turnpieceOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Temperature history chart
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗A web application that shows how today's temperature (or this week's, month's, or year's) compares to the same period across the past 50 years, for any supported location.
/feed and accessible via the Snapshots link in the sidebar; filterable by period (daily/weekly/monthly/yearly)Clone the repository:
git clone [repository-url]
cd TempHist
Install dependencies:
npm install
Create a .env file:
VITE_API_BASE=/api
VITE_TEST_TOKEN=your_test_token_here
API_BASE=http://localhost:8000
API_BASE is the address of the TempHist API. With http://localhost:8000 you'll need the API running locally — follow its setup instructions. Alternatively, point it at the dev or staging API to avoid running the API locally:
API_BASE=https://devapi.temphist.com
Start the local dev server (in separate terminals):
npm run dev # Vite dev server — hot reload, no OG injection
The app is available at http://localhost:5173.
There are two ways to run the frontend locally, depending on what you're testing:
| Mode | Command | Port | Hot reload | API proxy | OG tag injection |
|---|---|---|---|---|---|
| Dev (daily use) | npm run dev | 5173 | ✅ | via Vite | ❌ |
| Prod-like (OG testing) | npm run start:local | 3000 | ❌ | ✅ | ✅ |
npm run dev — use this for everyday development, like if you're updating the styles or content. Vite serves source files directly and watches for changes: edits to .scss styles, TypeScript, or HTML are reflected in the browser instantly without a build step or page reload. API calls are proxied to http://localhost:8000 automatically.
npm run start:local — use this when testing social sharing or OG image previews (e.g. Share to Notes in Safari). It serves the built dist/ files, proxies /api to localhost:8000, and injects og:image / og:title tags server-side for /s/:id share URLs.
Note:
npm run start:localserves the last build. Runnpm run buildfirst if you've changed source files since the last build.
Note:
npm startrunsserver.js, the production server. It has no API proxy and is not suitable for local development.
To test OG sharing locally:
npm run build # build latest source into dist/
npm run start:local # serve on localhost:3000 with OG injection
# then visit http://localhost:3000/s/<share-id> in Safari and share
| Variable | Required | Description |
|---|---|---|
VITE_API_BASE | Yes | API base URL. Dev: /api (relative — proxied by Vite or server-local.js). Prod: https://api.temphist.com |
VITE_ENABLE_SNAPSHOTS | No | Set to false to disable the Snapshots feed and splash-screen carousel entirely. Defaults to true. When false the nav link is hidden at build time and all related JS is tree-shaken from the production bundle. |
VITE_TEST_TOKEN | Dev only | Test token injected by server-local.js when Firebase auth is unavailable |
VITE_APPCHECK_DEBUG_TOKEN | Dev only | Firebase App Check debug token UUID. Register it once in Firebase Console → App Check → Manage debug tokens. Omit to let Firebase generate a new one (you'll be prompted to register it on first run). |
PORT | No | Server port (default: 3000). Set automatically by Railway in production |
API_BASE | Dev only | TempHist API URL used by server-local.js. Set to http://localhost:8000 to run the API locally, or point at https://devapi.temphist.com / https://stagingapi.temphist.com to skip running it locally. |
npm run type-check # TypeScript check
npm run build # Outputs to dist/
Deploy the dist/ directory to your web root.
Pushes to main → production auto-deploy via GitHub webhook.
Pushes to develop → dev/staging auto-deploy.
For manual deployment:
git checkout main && git pull
npm install && npm run build
# copy dist/ to web root
For Apache hosts (e.g. SiteGround), add a .htaccess to serve clean URLs:
RewriteEngine On
# Remove .html extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]
# Redirect .html URLs to clean versions
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R=301]
VITE_RECAPTCHA_SITE_KEY in .envsrc/firebase.tsIn dev mode, the app sets FIREBASE_APPCHECK_DEBUG_TOKEN so Firebase generates a debug token instead of requiring reCAPTCHA. On first run you'll see this in the browser console:
App Check debug token: <uuid>. You will need to add it to your app's App Check settings in the Firebase console for it to work.
Register that UUID in Firebase Console → App Check → Apps → [your web app] → Manage debug tokens, then add it to .env:
VITE_APPCHECK_DEBUG_TOKEN=<your-debug-token-uuid>
Without this, anonymous sign-in can fail or hang. After 12 s the app shows a "couldn't connect" / "privacy settings" message with a Retry button (on the home page and on share pages) rather than loading forever.
/analytics endpoint as recent_errors entries with error_type auth_signin or app_check_token, the Firebase error code in message, and endpoint share or spa. See src/auth/signIn.ts and recordAuthFailure in src/analytics/analytics.ts.npm test # run all tests
npm run test:coverage # with coverage report
npm run test:watch # watch mode
npm run test:ui # browser UI
src/
main.ts # App entry point, router, auth, location init
share.ts # Share page logic (fetch metadata, render chart)
chart/
chart.ts # Chart creation, bar colours, tooltip handler
views/
today.ts # Today view — fetch, render, location display
period.ts # Week/Month/Year views (shared renderer)
about.ts # About page content builder
feed.ts # Snapshots feed page — card builder, pagination, filter bar
utils/
uiHelpers.ts # Shared DOM helpers: location display, stats rendering
location.ts # Country code → flag, location slug lookup
types/
index.ts # TypeScript type definitions
services/ # Location detection, carousel, API interactions
api/ # API client functions
templates/
header.html # Site header partial (included at build time)
nav.html # Sidebar nav partial (Snapshots link hidden when VITE_ENABLE_SNAPSHOTS=false)
styles.scss # Global styles
index.html # Main SPA shell
about.html # Standalone about page
privacy.html # Standalone privacy page
feed.html # Standalone Snapshots feed page
server.js # Production proxy + OG tag injection
server-local.js # Local dev proxy with test token injection
Session analytics are submitted to POST /v1/analytics in two situations:
beforeunload) — when the tab closes or navigates awayEach submission includes session-level counters (api_calls, api_failure_rate, retry_attempts, location_failures, error_count) plus richer fields captured from the initial daily load:
| Field | Source |
|---|---|
response_time_ms | Wall-clock time for the daily temperature fetch (async job creation → result) |
cache_hit | X-Cache: HIT/MISS header on the job result response (null if header absent) |
canonical_location | Location string returned by the API (may differ from what was requested) |
requested_location | window.tempLocation at the time of the fetch |
selection_method | How the location was chosen: own_location (browser geolocation), carousel (manual pick), popular (app default) |
user_agent | navigator.userAgent |
Current limitation — period views not instrumented. When the user navigates to Past week / Past month / Past year, those fetches increment the api_calls counter (so failures are captured) but their individual response times and cache hit status are not recorded. If period view latency becomes a concern, extend period.ts to populate window.TempHist.analytics.lastRequestMetadata after each fetch (mirroring the pattern in src/views/today/fetchHistoricalData.ts) and call sendAnalytics() after each load.
MIT License — Copyright (c) 2025 Turnpiece