Skip to content

Add demand forecast dashboard PWA with TimesFM & TabFM integration - #1

Open
yankubota wants to merge 1 commit into
masterfrom
claude/admiring-brown-jwa551
Open

Add demand forecast dashboard PWA with TimesFM & TabFM integration#1
yankubota wants to merge 1 commit into
masterfrom
claude/admiring-brown-jwa551

Conversation

@yankubota

Copy link
Copy Markdown
Owner

Summary

Implements a complete demand forecast dashboard PWA for small retailers, designed to support zero-shot demand prediction using TimesFM 2.5 (BigQuery AI.FORECAST) and TabFM (stockout risk classification). The application provides a single-screen interface for store managers to make daily ordering decisions with human-in-the-loop approval.

Key Changes

  • Core Dashboard UI (src/app/page.tsx): Single-screen layout displaying KPIs (tomorrow's forecast, recommended order quantity, high-risk SKU count), 28-day forecast chart, and risk-sorted SKU table
  • Domain Types (src/lib/types.ts): Type definitions mirroring TimesFM and TabFM output shapes (ForecastPoint, SkuForecast, RiskClass, StoreSummary)
  • Forecast Logic (src/lib/forecast.ts): Inventory-driven decision aids including:
    • Days-of-stock calculation
    • Risk classification (high/mid/low based on coverage thresholds)
    • Recommended order quantity with safety stock (Z=1.645 for 95% service level)
    • Daily sigma estimation from 95% prediction intervals
  • Sample Data Layer (src/lib/data.ts): Deterministic PRNG-based generation of 42-SKU M5 dataset (CA_1 store) with realistic demand patterns, weekday/weekend seasonality, and category-specific variation
  • Components:
    • ForecastChart.tsx: Dependency-free SVG chart (28-day point forecast + 95% interval band)
    • RiskSkuTable.tsx: Pre-sorted SKU table with risk badges and inventory metrics
    • OrderAlert.tsx: Prominent reorder banner for high-risk items (< 3 days stock)
    • KpiCard.tsx, Header.tsx, RiskBadge.tsx: Supporting UI elements
  • PWA Support:
    • Service Worker (public/sw.js): Network-first for forecasts, cache-first for assets, offline fallback
    • Web manifest (public/manifest.webmanifest): Installable app configuration
    • PwaRegister.tsx: Client-side service worker registration
  • Styling: Tailwind CSS with custom color scale (risk levels, brand, surface/ink hierarchy)
  • Build Config: Next.js 14 (App Router), TypeScript strict mode, PostCSS/Autoprefixer

Notable Implementation Details

  • Reproducible Demo: Deterministic PRNG (mulberry32) seeded by SKU ID ensures consistent data across renders
  • Backend-Agnostic: UI depends only on src/lib/types.ts; data layer can be swapped for real BigQuery/TabFM APIs without UI changes
  • Human-in-the-Loop Design: Forecasts shown as 95% intervals (not point estimates); all reorder decisions require manual approval
  • Transparent Logic: Safety stock and risk classification are simple, auditable formulas (not black-box ML)
  • Accessibility: Semantic HTML, ARIA labels, Japanese localization (JST timestamps, Japanese UI text)
  • API Route (src/app/api/forecast/route.ts): Static endpoint returning dashboard payload, ready for dynamic backend integration

Data Source

Uses Kaggle M5 Forecasting dataset (Walmart sales, academic use with attribution). Sample numbers are deterministic demo data; production will use real inventory and forecast outputs.

https://claude.ai/code/session_01CpFyNhmV7kXeb7V6JXJdV9

企画書「TimesFM × TabFM ゼロショット需給予測アプリ」のアプリ層(スライド11・12)を
Next.js 14 + TypeScript + Tailwind の PWA として実装。

- 1画面で意思決定: 明日の予測販売数(95%区間)/推奨発注数/欠品リスク高SKU数
- 発注推奨アラート(在庫3日分未満・リスク高い順・Human-in-the-loop注記)
- 28日予測チャート(自作SVG・点予測+95%予測区間バンド)
- SKU別テーブル(リスク高い順ソート)
- データ層は AI.FORECAST(TimesFM) / TabFM 出力の形に整合(BigQuery接続はTODO)
- 決定的PRNGによる再現可能なM5/CA_1サンプルデータ
- PWA: manifest + Service Worker(インストール可・オフライン対応)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CpFyNhmV7kXeb7V6JXJdV9
@cursor

cursor Bot commented Jul 10, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
test Ready Ready Preview, Comment Jul 10, 2026 3:07pm

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a84f1b31cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Serves the dashboard payload. Mirrors what a thin BigQuery-backed API would
// return, so the client can move to `fetch('/api/forecast')` unchanged once the
// real TimesFM + TabFM pipeline is wired in.
export const dynamic = "force-static";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep forecast API from being statically cached

This endpoint is documented as the path that will serve fresh BigQuery/TabFM forecast data, but force-static makes Next prerender/cache the route at build time. In the production path with daily inventory or forecast updates, network requests to /api/forecast will continue returning the build-time payload until a redeploy, so the dashboard can show stale ordering recommendations despite the network-first service worker. Use dynamic rendering/no-store or an explicit short revalidation window for this forecast API.

Useful? React with 👍 / 👎.

Comment thread src/components/Header.tsx
Comment on lines +13 to +15
const genLabel = `${gen.getFullYear()}/${gen.getMonth() + 1}/${gen.getDate()} ${String(
gen.getHours()
).padStart(2, "0")}:${String(gen.getMinutes()).padStart(2, "0")}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Format JST timestamps with a fixed timezone

When this server component renders on Vercel/Node in UTC or any host not configured for Asia/Tokyo, new Date(generatedAt) is converted to the host timezone before getHours(), while the UI still appends JST. For example, 2026-07-10T21:00:00+09:00 renders as 12:00 JST on a UTC server, misleading operators about forecast freshness. Format with Intl.DateTimeFormat using timeZone: 'Asia/Tokyo' or otherwise preserve the JST offset.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants