Skip to content

Conversation

@MANASMATHUR
Copy link
Contributor

@MANASMATHUR MANASMATHUR commented Jan 31, 2026

TinyFish - SiliconSignal
SiliconSignal is a high-precision monitoring platform designed to detect logistics risks, lead-time shifts, and lifecycle transitions in real-time. By leveraging the Tinyfish web agent (Mino), it extracts live signals directly from foundry bulletins and primary distributor channels.
Deployment:- https://silicon-signal.vercel.app

@coderabbitai
Copy link

coderabbitai bot commented Jan 31, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

Adds a new silicon-signal Next.js application and related infrastructure: frontend app with landing, dashboard, and UI components; a POST /api/scan server route implementing multi-source browser- and fetch-based part scanning, signal extraction, merging, and risk scoring; types and a lightweight history store with sample history data; build/config files (tsconfig, next.config, ESLint, PostCSS, package.json); global styles and assets. Exports include the scan POST handler, several React components, types, and history-store functions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as /api/scan
    participant Cache
    participant History as History Store
    participant Browser as Headless Browser
    participant Dist1 as DigiKey
    participant Dist2 as Mouser
    participant Dist3 as Other Vendors
    participant Risk as Risk Analyzer

    Client->>API: POST /api/scan (part_number, manufacturer)
    API->>API: Validate input
    API->>Cache: Check cache for part
    alt Cache Hit
        Cache-->>API: Cached result
        API-->>Client: Return cached result
    else Cache Miss
        API->>History: Load historical snapshots
        History-->>API: Return history

        API->>Browser: Launch headless browser (fallback: fetch)
        Browser->>Dist1: Navigate & fetch page
        Dist1-->>Browser: Page content / JSON-LD
        Browser->>Browser: Parse DOM & JSON-LD -> extract signals
        Browser->>Dist2: Navigate & fetch page
        Dist2-->>Browser: Page content / JSON-LD
        Browser->>Browser: Parse DOM & JSON-LD -> extract signals
        Browser->>Dist3: Navigate & fetch page
        Dist3-->>Browser: Page content / JSON-LD
        Browser->>Browser: Parse DOM & JSON-LD -> extract signals
        Browser-->>API: Source signals & agent logs

        API->>API: Merge signals across sources
        API->>Risk: Compute consolidated risk & confidence
        Risk->>History: Compare with historical trends
        History-->>Risk: Historical context
        Risk-->>API: Risk analysis

        API->>History: Save new snapshot
        History-->>API: Snapshot stored
        API->>Cache: Store result with TTL
        Cache-->>API: Cached
        API-->>Client: Return ScanResult (signals, risk, evidence, timing)
    end
Loading
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Silicon Signal cookbook project' directly and clearly summarizes the main change: adding a new project directory (silicon-signal) to the cookbook repository.
Description check ✅ Passed The description is directly related to the changeset, explaining that SiliconSignal is a monitoring platform using Tinyfish/Mino agents, which aligns with the new silicon-signal project files being added.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🤖 Fix all issues with AI agents
In `@README.md`:
- Line 41: Fix the typo in the README table row for the project labeled
"[summer-school-finder]": replace the incorrect text "sch`ool" in the
description string "Discover and compare summer sch`ool programs from
universities around the world" with the correct "school" so the description
reads "Discover and compare summer school programs from universities around the
world".

In `@silicon-signal/README.md`:
- Line 3: Replace the bare URL on the README's "Live link:" line with a Markdown
link so it uses proper link syntax; for example, change the text that currently
reads "Live link: https://silicon-signal.vercel.app/" to use bracketed link text
and parentheses (e.g., "Live link: [Silicon
Signal](https://silicon-signal.vercel.app/)") so markdownlint MD034 is
satisfied.
- Around line 26-28: The fenced code block containing the environment variable
example (the block with "MINO_API_KEY=your_tinyfish_key") lacks a language tag
and triggers MD040; add the language identifier "dotenv" to the opening fence
(i.e., change the triple-backtick that precedes the MINO_API_KEY line to include
"dotenv") so the snippet is fenced as a dotenv code block.

In `@silicon-signal/src/app/api/scan/route.ts`:
- Around line 551-553: The regex used to validate part_number currently allows a
backslash due to the sequence "\\", which is unintended; update the validation
to disallow backslashes by removing the backslash from the character class and
ensure the hyphen is placed at the end (e.g., use a character class like
[A-Za-z0-9._/+ -] with the hyphen last) in the check that tests part_number so
invalid backslashes are rejected while preserving the intended allowed
characters.
- Around line 6-62: Remove the duplicated interface declarations (RiskAnalysis,
ScanResult, SourceSignal, SignalSummary, ConfidenceInfo) from route.ts and
replace them with a single import of those types from the shared types module;
specifically, delete the interface blocks shown in the diff and add an import
type statement that brings in RiskAnalysis, ScanResult, SourceSignal,
SignalSummary and ConfidenceInfo from the shared types module so the file uses
the canonical definitions instead of duplicating them.

In `@silicon-signal/src/components/Header.tsx`:
- Around line 3-11: The Header component uses client-only APIs (the onClick
handler that sets window.location.href) so either mark the component as a client
component by adding the directive 'use client' at the top of the Header file
(Header component) or make it server-safe by replacing the clickable div (the
element with onClick and the window.location.href usage) with a native anchor
element (<a href="/">) that preserves the same children and styles and removes
the onClick/window reference; update any related imports/props if needed.

In `@silicon-signal/src/components/ScanForm.tsx`:
- Around line 3-25: The handleSubmit function in ScanForm uses the identifier
React.FormEvent but React is not imported (with "jsx":"react-jsx" there is no
default React binding); fix by importing the event type from React and updating
the signature: add an import like "import type { FormEvent } from 'react'" (or
import React as needed) and change handleSubmit's parameter to use FormEvent (or
the imported type) so the TypeScript reference to React.FormEvent is resolved;
ensure this import sits with the other React imports at the top of ScanForm.tsx.

In `@silicon-signal/src/components/SignalOverview.tsx`:
- Around line 13-18: In the SignalOverview component JSX there is an invalid
nesting: a <div> placed inside the inline <span> that renders the live status;
replace that inner <div> with a <span> (preserving the clsx class string "w-1.5
h-1.5 rounded-full" and conditional classes "bg-accent"/"bg-border") so the
status indicator is valid inline HTML; update the JSX where the outer span uses
clsx(...) and the nested element created for the dot indicator to be a span
instead of div.

In `@silicon-signal/src/components/SiliconWafer.tsx`:
- Around line 1-2: This file is missing the Next.js client boundary directive
required for framer-motion; add the literal string 'use client' as the very
first line in SiliconWafer.tsx (before any imports) so the component and its use
of motion from 'framer-motion' run as a client component; ensure the directive
appears above the import of motion and any other imports in the file.

In `@silicon-signal/src/lib/store.ts`:
- Around line 27-79: saveSnapshot performs a read-modify-write (via attemptSave
and currentHistoryFile) without any locking, which can cause lost updates under
concurrent writes; fix by making writes atomic: when writing inside attemptSave,
write the JSON to a temporary file (e.g., same dir + unique suffix) and then
atomically rename/replace the target file (fs.renameSync) to avoid
partial/overwritten data, and optionally add a short retry/backoff or simple
lock-file mechanism around attemptSave to reduce race windows; if you choose not
to implement concurrency control, add a clear comment/docstring on saveSnapshot
explaining the race condition limitation and recommending atomic rename or
external locking for production.
🧹 Nitpick comments (10)
silicon-signal/src/components/HistoricalTrend.tsx (1)

6-12: Clamp history scores before plotting to avoid out-of-range rendering.

If a score is outside 0–100, the path can render off-canvas. Clamping keeps the chart stable without changing data semantics elsewhere.

♻️ Suggested change
-    const points = history.length > 1 ? history.map((h, i) => {
-        const x = (i / (history.length - 1)) * 240 + 20;
-        const y = 90 - (h.score / 100) * 80;
-        return { x, y };
-    }) : [];
+    const clampScore = (score: number) => Math.min(100, Math.max(0, score));
+    const points = history.length > 1 ? history.map((h, i) => {
+        const x = (i / (history.length - 1)) * 240 + 20;
+        const y = 90 - (clampScore(h.score) / 100) * 80;
+        return { x, y };
+    }) : [];
silicon-signal/src/components/ScanResultCard.tsx (2)

4-4: Unused import: Calendar

The Calendar icon is imported but never used in the component.

🧹 Remove unused import
-import { ExternalLink, AlertTriangle, Calendar, CheckCircle, Activity, DollarSign, Globe } from 'lucide-react';
+import { ExternalLink, AlertTriangle, CheckCircle, Activity, DollarSign, Globe } from 'lucide-react';

23-23: Set explicit value for aria-hidden

The aria-hidden attribute should have an explicit boolean or string value for clarity.

🧹 Suggested fix
-            <div className="absolute -top-20 -right-20 w-64 h-64 bg-cyan-500/10 rounded-full blur-3xl group-hover:bg-cyan-500/20 transition-all duration-1000" aria-hidden />
+            <div className="absolute -top-20 -right-20 w-64 h-64 bg-cyan-500/10 rounded-full blur-3xl group-hover:bg-cyan-500/20 transition-all duration-1000" aria-hidden="true" />
silicon-signal/src/components/PlatformView.tsx (1)

34-37: Consider checking response status before parsing JSON

The current flow parses JSON before checking res.ok. If the server returns a non-JSON error (e.g., 502 Bad Gateway with HTML), res.json() will throw, and the error message will be a parse error rather than the actual HTTP error.

🛡️ Suggested improvement for robustness
-            const data = await res.json();
-            if (!res.ok) {
-                throw new Error(data?.error || 'Scan failed');
-            }
-            setResult(data);
+            if (!res.ok) {
+                const data = await res.json().catch(() => ({}));
+                throw new Error(data?.error || `Scan failed (${res.status})`);
+            }
+            const data = await res.json();
+            setResult(data);
silicon-signal/src/lib/store.ts (1)

81-94: Fallback behavior may skip valid data in other files

getHistory stops at the first successfully parsed file, even if that file doesn't contain the requested partNumber. If the part's history exists only in a later file (e.g., data/history.json), it won't be found.

This is likely acceptable for the demo's use case but worth noting.

silicon-signal/src/types.ts (1)

1-5: Consider using a union type for level

Using a union type for level would provide better type safety and autocompletion:

🧹 Suggested improvement
+export type RiskLevel = 'LOW' | 'MEDIUM' | 'HIGH';
+
 export interface RiskAnalysis {
     score: number;
-    level: string;
+    level: RiskLevel;
     reasoning: string;
 }
silicon-signal/src/app/api/scan/route.ts (4)

616-627: Multiple @ts-ignore comments for Chromium types

The type mismatches between puppeteer-core and @sparticuz/chromium are common. Consider using type assertions with as unknown as X for slightly safer typing, or adding a brief comment explaining why these ignores are necessary.


786-799: Browser cleanup could use finally block

The browser cleanup is split between the happy path (line 786) and error handling (lines 792-798). Using a finally block would ensure cleanup happens regardless of which path is taken.

🧹 Consider wrapping browser operations in try-finally
let browser: Browser | undefined;
try {
    browser = await launchBrowser();
    // ... browser operations
} finally {
    if (browser) {
        try {
            await browser.close();
        } catch {
            // ignore close errors
        }
    }
}

1076-1089: Cache eviction removes oldest by insertion, not by TTL

The eviction logic removes entries in insertion order, not by expiration time. This means a recently used entry that was inserted early could be evicted before an expired entry inserted later. For a demo this is fine, but worth noting if caching is enabled in production.


534-1111: POST handler is quite long (~580 lines)

The handler orchestrates many concerns: validation, browser management, data fetching, signal parsing, risk calculation, caching, and history. For a cookbook demo this is acceptable, but consider extracting logical sections into helper functions for maintainability:

  • launchBrowser() - browser initialization logic
  • fetchSignalsWithBrowser() - browser-based data collection
  • computeRiskAnalysis() - risk scoring logic
  • buildScanResult() - result assembly

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@silicon-signal/src/components/SignalOverview.tsx`:
- Around line 5-9: The "Data Confidence" metric in the metrics array is
hardcoded to 95; update the Data Confidence value to use the actual scan result
confidence (use result.confidence?.score or result?.confidence?.score ??
<fallback>) instead of 95, e.g. replace the numeric literal in the Data
Confidence entry inside the metrics constant so it reads the ScanResult
confidence score and preserves existing status/color logic.
🧹 Nitpick comments (2)
silicon-signal/src/app/api/scan/route.ts (2)

554-571: Consider adding type declarations or explicit typing for chromium integration.

Multiple @ts-ignore comments suppress TypeScript errors for the @sparticuz/chromium integration. While this is a common workaround, it reduces type safety. Consider:

  1. Adding a local type declaration file for the chromium module
  2. Using explicit type assertions with comments explaining the expected types
  3. Checking if newer versions of @sparticuz/chromium have improved type definitions
♻️ Example type declaration approach

Create silicon-signal/src/types/chromium.d.ts:

declare module '@sparticuz/chromium' {
    const chromium: {
        executablePath(): Promise<string>;
        args: string[];
        defaultViewport: { width: number; height: number };
        headless: boolean | 'new';
    };
    export default chromium;
}

621-665: Consider logging suppressed errors to agent logs for observability.

Multiple empty catch blocks silently swallow errors during DOM extraction and page navigation. While graceful degradation is appropriate here, logging these failures to agentLogs would aid debugging without affecting control flow.

♻️ Example improvement for one catch block
                         } catch {
-                            // optional
+                            agentLogs.push(`${logPrefix} DOM extraction from search page skipped.`);
                         }

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.

1 participant