Skip to content

feat: Add FabLens - Eco-Friendly & Skin-Safe Fabric Checker#151

Open
yashasvij-19 wants to merge 17 commits intoLamatic:mainfrom
yashasvij-19:new-main
Open

feat: Add FabLens - Eco-Friendly & Skin-Safe Fabric Checker#151
yashasvij-19 wants to merge 17 commits intoLamatic:mainfrom
yashasvij-19:new-main

Conversation

@yashasvij-19
Copy link
Copy Markdown

@yashasvij-19 yashasvij-19 commented Apr 30, 2026

PR Checklist

1. Contribution Type

  • Kit (kits/fablens/)

2. General Requirements

  • PR is for one project only
  • No secrets or API keys committed
  • Folder name uses kebab-case
  • Changes documented in README.md

3. File Structure

  • .env.example with placeholder values
  • Flow exported from Lamatic Studio

4. Validation

  • npm install && npm run dev works locally
  • No unrelated files modified
  • kits/fablens/.gitignore — Ignore Lamatic outputs, node_modules, and local env files.

Documentation & agent behavior

  • kits/fablens/README.md — Kit overview: FabLens Fabric Impact Analyzer, workflow, tech stack, setup (copy .env.example, npm install, npm run dev), required env vars, supported sites, limitations, and roadmap.
  • kits/fablens/agent.md — Agent docs: URL-based fabric analyzer, guardrails, integrations, quickstart, failure modes, scope and future plans.
  • kits/fablens/constitutions/default.md — Assistant identity, safety constraints, data handling, and tone guidelines.

App-level files

  • kits/fablens/apps/.gitignore — Ignore .vercel.
  • kits/fablens/apps/.env.example — Example env with LAMATIC_API_KEY and Lamatic host/project/workflow placeholders.
  • kits/fablens/apps/package.json — App manifest and scripts (dev/build/start); deps pinned (Next.js 16.2.4, React 19.2.4, lucide-react).
  • kits/fablens/apps/next.config.ts — Next.js typed config export.
  • kits/fablens/apps/tsconfig.json — TypeScript config with strict settings and path aliasing.
  • kits/fablens/apps/next-env.d.ts — Next.js type declarations.
  • kits/fablens/apps/postcss.config.mjs — PostCSS config enabling Tailwind and Autoprefixer.
  • kits/fablens/apps/tailwind.config.js — Tailwind content globs and theme placeholder.

Frontend (Next.js App Router)

  • kits/fablens/apps/app/page.tsx — Client Home: URL input, POST /api/analyze (10s client timeout), displays materials list, eco/skin scores, expandable details, and negatives.
  • kits/fablens/apps/app/layout.tsx — RootLayout: imports globals, configures Google fonts, exports metadata (title "FabLens", icon "/logo.png"), and wraps page children.
  • kits/fablens/apps/app/globals.css — Tailwind imports, CSS custom properties, base styles.

Backend / API / Lib

  • kits/fablens/apps/app/api/analyze/route.ts — POST /api/analyze handler: validates LAMATIC_API_KEY and URL, calls Lamatic workflows (server-side 12s AbortController), safe-parses LLM JSON output, extracts/normalizes/deduplicates materials, partitions known vs unknown via materialDB, computes ecoScore/skinScore + reasons, optionally calls a secondary scoring workflow for unknowns, clamps scores, and returns structured JSON with error handling.
  • kits/fablens/apps/lib/materialDB.ts — Exports MaterialData type and materialDB lookup with per-material sustainability and skin-safety attributes.

Flows, prompts, and model config

  • kits/fablens/flows/fabric-material-analyzer.ts — Flow export (meta, inputs, references, nodes, edges).
    • Node types present:
      • triggerNode (graphqlNode) — API request trigger (schema: { question, url }).
      • dynamicNode (scraperNode_601) — Scraper node (Firecrawl) fetching only main content, excludes nav/footer/header/script/style, accepts selectable credentials.
      • dynamicNode (LLMNode_449) — LLM/generative node using a system prompt to extract materials; model selected via model-config reference.
      • responseNode (graphqlResponseNode_147) — Maps LLM generatedResponse → API response.answer.
    • Edges: trigger → scraper → LLM → response, plus a trigger→response responseEdge for GraphQL wiring.
    • High-level flow: accept product URL → scrape main content → run LLM with a strict system prompt that must output valid JSON { materials: [...] } and follow extraction rules (list material names only, split blends, no extra text) → return the JSON as the workflow answer.
  • kits/fablens/prompts/fabric-material-analyzer_llmnode-449_system_0.md — System prompt enforcing JSON-only output and strict material-extraction rules (split blends, handle rayon/viscose rules, no extraneous text).
  • kits/fablens/model-configs/fabric-material-analyzer_llmnode-449_generative-model-name.ts — Model config referencing groq/meta-llama/llama-4-scout with credential binding.

Kit metadata

  • kits/fablens/lamatic.config.ts — Kit metadata (name, version 1.0.0, author, single step mapping).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds the FabLens kit: documentation, Lamatic flow and model configs, a Next.js App Router frontend, a POST /api/analyze endpoint that calls Lamatic workflows, a local material database and scoring logic, plus build/tooling and dev config files for running a fabric material analyzer.

Changes

FabLens kit (single DAG: flow → extraction → API → frontend → config/docs)

Layer / File(s) Summary
Flow & Prompt Definitions
kits/fablens/flows/fabric-material-analyzer.ts, kits/fablens/prompts/..._system_0.md, kits/fablens/model-configs/...generative-model-name.ts
New Lamatic flow that scrapes a product URL, runs an LLM node with a JSON-only system prompt to extract material names, and model config binding to Groq/llama-4-scout.
Kit Metadata & Constitution
kits/fablens/lamatic.config.ts, kits/fablens/constitutions/default.md
Adds kit manifest (name, version, steps) and a default assistant constitution file.
API: Extraction & Scoring
kits/fablens/apps/app/api/analyze/route.ts
New POST /api/analyze handler: validates env/API key and URL, calls Lamatic executeWorkflow with timeout, robustly parses AI JSON output, extracts/normalizes/deduplicates materials, partitions known vs unknown via materialDB, computes eco/skin scores and reason/negative arrays from known data, optionally invokes a secondary Lamatic workflow for unknowns, and returns structured JSON with clamped scores and notes; includes error handling for missing key, invalid URL, empty disclosures, and generic failures.
Material DB
kits/fablens/apps/lib/materialDB.ts
Introduces MaterialData type and materialDB lookup keyed by material name with biodegradability and categorical attributes used by scoring logic.
Frontend App Router
kits/fablens/apps/app/layout.tsx, kits/fablens/apps/app/page.tsx, kits/fablens/apps/app/globals.css
Adds Next.js root layout with fonts/metadata, global Tailwind-compatible CSS variables and base styles, and a client Home page that POSTs to /api/analyze, handles timeouts, and renders materials, eco/skin scores, expandable reason lists, negatives, and notes.
Build / Tooling
kits/fablens/apps/package.json, kits/fablens/apps/tsconfig.json, kits/fablens/apps/next.config.ts, kits/fablens/apps/next-env.d.ts, kits/fablens/apps/postcss.config.mjs, kits/fablens/apps/tailwind.config.js
New app manifest and config files: Next.js/React dependencies and scripts, strict TypeScript config and path aliasing, Next config and type wiring, PostCSS export with Tailwind/autoprefixer, and Tailwind content config.
Docs, Env, Ignore
kits/fablens/README.md, kits/fablens/agent.md, kits/fablens/apps/.env.example, kits/fablens/.gitignore, kits/fablens/apps/.gitignore
Adds README and agent docs describing architecture, setup, required env variables and limitations; provides .env.example with Lamatic placeholders and .gitignore entries for generated/node/local files and .vercel.
Styling / Globals
kits/fablens/apps/app/globals.css, kits/fablens/apps/tailwind.config.js, kits/fablens/apps/postcss.config.mjs
Adds Tailwind layer directives and root CSS variables, plus PostCSS and Tailwind configuration for the app.

Suggested reviewers

  • amanintech
  • d-pamneja
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add FabLens - Eco-Friendly & Skin-Safe Fabric Checker' clearly and specifically describes the main change: introducing a new kit called FabLens with its core functionality for analyzing fabric environmental and health impact.
Description check ✅ Passed The PR description addresses all major sections of the template: contribution type (Kit), general requirements (single project, no secrets, kebab-case naming, README documentation), file structure (.env.example, Lamatic flow export), and validation steps (local testing, no unrelated files).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

PR Validation Results

New Contributions Detected

  • Kit: kits/fablens/model-configs
  • Kit: kits/fablens/agent.md
  • Kit: kits/fablens/constitutions
  • Kit: kits/fablens/apps
  • Kit: kits/fablens/.gitignore
  • Kit: kits/fablens/README.md
  • Kit: kits/fablens/prompts
  • Kit: kits/fablens/flows
  • Kit: kits/fablens/lamatic.config.ts

Check Results

Check Status
No edits to existing projects ✅ Pass
Required root files present ❌ Fail
Flow folder structure valid ✅ Pass
No changes outside contribution dirs ✅ Pass

Errors

  • ❌ Missing config.json in kits/fablens/model-configs
  • ❌ Missing README.md in kits/fablens/model-configs
  • ❌ Missing flows/ directory in kits/fablens/model-configs
  • ❌ Missing config.json in kits/fablens/agent.md
  • ❌ Missing README.md in kits/fablens/agent.md
  • ❌ Missing flows/ directory in kits/fablens/agent.md
  • ❌ Missing config.json in kits/fablens/constitutions
  • ❌ Missing README.md in kits/fablens/constitutions
  • ❌ Missing flows/ directory in kits/fablens/constitutions
  • ❌ Missing config.json in kits/fablens/apps
  • ❌ Missing README.md in kits/fablens/apps
  • ❌ Missing flows/ directory in kits/fablens/apps
  • ❌ Missing config.json in kits/fablens/.gitignore
  • ❌ Missing README.md in kits/fablens/.gitignore
  • ❌ Missing flows/ directory in kits/fablens/.gitignore
  • ❌ Missing config.json in kits/fablens/README.md
  • ❌ Missing README.md in kits/fablens/README.md
  • ❌ Missing flows/ directory in kits/fablens/README.md
  • ❌ Missing config.json in kits/fablens/prompts
  • ❌ Missing README.md in kits/fablens/prompts
  • ❌ Missing flows/ directory in kits/fablens/prompts
  • ❌ Missing config.json in kits/fablens/flows
  • ❌ Missing README.md in kits/fablens/flows
  • ❌ Missing flows/ directory in kits/fablens/flows
  • ❌ Missing config.json in kits/fablens/lamatic.config.ts
  • ❌ Missing README.md in kits/fablens/lamatic.config.ts
  • ❌ Missing flows/ directory in kits/fablens/lamatic.config.ts

🛑 Please fix the errors above before this PR can be merged.

Refer to CONTRIBUTING.md and CLAUDE.md for the expected folder structure.

Copy link
Copy Markdown
Contributor

@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: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
kits/fablens/apps/app/globals.css (1)

1-27: ⚠️ Potential issue | 🟠 Major

Configure CSS linting for Tailwind v4 directives in the fablens kit.

This file correctly uses Tailwind v4 syntax (@import "tailwindcss", @theme inline), but the root biome.json CSS linter has no Tailwind configuration. Biome will report these directives as unknown at-rules, blocking CI. Other kits (medical-assistant, poster-generator) solve this with .stylelintrc.json containing Tailwind rule overrides. Add equivalent Tailwind configuration to kits/fablens/apps/ to align with the codebase standard, or update root biome.json to globally recognize Tailwind v4 directives.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/globals.css` around lines 1 - 27, The CSS linter is
flagging Tailwind v4 directives (`@import` "tailwindcss" and `@theme` inline) in
globals.css because there is no Tailwind config in the linter; add a
stylelint/biome override for Tailwind v4 directives similar to other kits by
creating a .stylelintrc.json (or updating biome.json) in the app directory to
recognize at-rules like "tailwind", "apply", "variants", "responsive", and
"layer" (or include the same rule overrides used in the
medical-assistant/poster-generator kits) so the linter accepts the Tailwind v4
syntax used in globals.css.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/fablens/agent.md`:
- Around line 5-60: Remove all unresolved artifact references like "[file:2]"
and "[file:4]" throughout the FabLens README (e.g., within the "FabLens" intro,
"Purpose", "Material Analysis Flow", "Environment Setup", "Required Environment
Variables", "Quickstart", "Common Failure Modes", and "Scope" sections) and
ensure the file ends with a single trailing newline; keep the surrounding text
intact and preserve variable names such as LAMATIC_API_KEY and
FABLENS_WORKFLOW_ID and section headings while deleting only the bracketed file
tokens.

In `@kits/fablens/apps/app/api/analyze/route.ts`:
- Line 37: Validate and constrain the incoming url extracted from await
req.json() before forwarding: ensure the parsed value is a non-empty string, use
the URL constructor to parse it and verify protocol is either "http:" or
"https:", reject anything else (respond 400) and optionally enforce sensible
length/hostname checks; perform this validation in the same handler before the
code that forwards the value (the place where you currently pass url onward
at/near the forwarding call on line 58), so only validated URLs are used by the
workflow or fetch.
- Around line 40-62: Wrap the outbound Lamatic fetch calls in an AbortController
with a clear timeout: create an AbortController, start a timer (e.g., 10000 ms)
that calls controller.abort(), pass controller.signal into fetch options, and
clear the timer after the fetch completes or errors; apply this pattern to the
fetch that assigns to response (the GraphQL POST) and to the other Lamatic fetch
later in the file so both requests time out instead of hanging. Ensure you
import/use global AbortController (or polyfill) and handle abort errors where
the code currently awaits the fetch.
- Around line 92-97: Guard and normalize the incoming materials before doing
array ops: check Array.isArray on parsed.materials, parsed.fabric, and
parsed.textiles (falling back to [] if none is an array), then filter to keep
only string entries and trim/filter out empty strings; assign that cleaned array
to rawMaterials (or a new normalizedMaterials) and use that normalized variable
where rawMaterials is consumed (references around the current map/filter usage
at the later block). Ensure no direct assumption that parsed.* fields are arrays
and replace any direct uses with the validated, string-filtered array.
- Around line 41-47: Hardcoded Lamatic deployment values (the GraphQL URL host,
"x-project-id" and the workflow identifiers referenced around lines 41–47 and
56–57 in route.ts) must be moved to environment variables and validated at
runtime; replace the literal URL with a constructed URL using a new LAMATIC_HOST
env var (e.g., `${process.env.LAMATIC_HOST}/graphql`), replace the hardcoded
project/workflow IDs with process.env.LAMATIC_PROJECT_ID and
process.env.LAMATIC_WORKFLOW_ID, and keep using process.env.LAMATIC_API_KEY for
Authorization; add a single early check (module init or the request handler that
currently performs the fetch) that throws or returns an error immediately if any
of LAMATIC_HOST, LAMATIC_PROJECT_ID, LAMATIC_WORKFLOW_ID, or LAMATIC_API_KEY are
missing so the service fails fast and surfaces misconfiguration.
- Around line 174-179: The fallback is invoking the extraction workflowId
"55a58aab-872b-463f-94b1-e0fbfc1c2056" while only sending a question (variable
unknown), causing a contract mismatch; update the call in route.ts (where
executeWorkflow is used and workflowId is set) to either use the dedicated
unknown-material scoring workflow ID (replace
"55a58aab-872b-463f-94b1-e0fbfc1c2056" with the scoring workflow's ID) or change
the fallback payload to match the extraction workflow contract (e.g., include
the required URL/fields), and verify references to workflowId and unknown across
the codebase to ensure consistency.

In `@kits/fablens/apps/app/page.tsx`:
- Around line 53-58: The URL text input currently rendered with value={url} and
onChange={(e) => setUrl(e.target.value)} has no accessible label; add one by
giving the input an id (e.g., id="url") and adding a corresponding <label
htmlFor="url"> (e.g., "URL" or "Enter URL") placed before the input (or, if you
prefer not to render a visible label, add aria-label="URL" directly to the
input); ensure the label text is descriptive and keep the existing props (value,
onChange, className) unchanged.
- Line 88: Replace the emoji prefixes in the two JSX status lines (the paragraph
rendering "🌱 Eco Friendly: {data.ecoScore}%" and the other status paragraph at
the second occurrence) with lucide-react icons: add an import from
'lucide-react' (e.g., import { Leaf, /* other icon */ } from 'lucide-react') at
the top of page.tsx, then replace the emoji characters in those <p> elements
with the corresponding icon components (e.g., <Leaf className="h-5 w-5
inline-block mr-2" />), keeping spacing and existing text ({data.ecoScore}%
etc.) and matching existing styling classes.

In `@kits/fablens/apps/next-env.d.ts`:
- Line 3: Remove the direct import of the build artifact
"./.next/dev/types/routes.d.ts" from next-env.d.ts and replace it with the
standard triple-slash reference type directives used across other kits: include
only reference types for "next" and "next/types/global" (and add
"next/image-types/global" if the project uses the Next Image types) so the file
no longer depends on a .next build artifact that breaks fresh installs.

In `@kits/fablens/apps/package.json`:
- Around line 16-21: The devDependencies list uses caret ranges and must be
pinned to exact versions: update "@tailwindcss/postcss", "@types/node",
"@types/react", "@types/react-dom", "tailwindcss", and "typescript" to the exact
resolved version strings (no ^ or ~) by copying the versions from the repo
lockfile (pnpm-lock.yaml / package-lock.json / yarn.lock) or from the workspace
root if that is canonical; replace e.g. "@types/node": "^20" with "@types/node":
"20.x.y" (the exact value from the lockfile) for each dependency, save
package.json, and run the package manager install to regenerate the lockfile so
the kit has pinned devDependencies.

In `@kits/fablens/constitutions/default.md`:
- Around line 3-17: Add a blank line after each second-level heading to satisfy
markdownlint MD022: insert an empty line immediately after the headings "##
Identity", "## Safety", "## Data Handling", and "## Tone" in the default.md
content so each heading is followed by a single blank line before the subsequent
paragraph or list.

In `@kits/fablens/flows/fabric-material-analyzer.ts`:
- Around line 20-25: The flow currently ignores the configurable credentials
input by hardcoding "my-firecrawl-creds"; locate the node configuration under
scraperNode_601 that references the literal "my-firecrawl-creds" and replace it
with the configurable credentials value (use the flow/input reference for the
"credentials" field, e.g. read inputs.credentials or node.inputs.credentials
depending on the flow runtime) so the scraper uses the declared "credentials"
input instead of a fixed ID.
- Line 93: The configuration currently sets skipTLsVerification: true which
disables TLS verification for scraper calls; change that setting to
skipTLsVerification: false (or remove the override so the default secure
behavior is used) in the scraper/client config, ensure any code paths that
construct the scraper/http client (look for the object containing the
skipTLsVerification property) do not disable certificate checks, and if a
temporary exception is required document it with a timestamped TODO and add a
test or runtime assertion to prevent committing skipTLsVerification: true
long-term.

In `@kits/fablens/prompts/fabric-material-analyzer_llmnode-449_system_0.md`:
- Line 29: Add a single trailing newline at the end of the markdown file
fabric-material-analyzer_llmnode-449_system_0.md to satisfy MD047; open the file
and ensure the last line ends with a newline character (no other content
changes), then save the file so the EOF contains exactly one trailing newline.

In `@kits/fablens/README.md`:
- Around line 33-38: Update the Environment Variables table in
kits/fablens/README.md to include the missing FABLENS_WORKFLOW_ID entry: add a
new row with `FABLENS_WORKFLOW_ID` as the Variable and a brief Description
(e.g., "Workflow ID used by FabLens to select the processing workflow") so the
README documents all required runtime configuration alongside `LAMATIC_API_KEY`;
ensure formatting matches the existing Markdown table style.
- Around line 39-46: Add a blank line after the "Supported Sites" and "Future
Plans" headings and ensure the README.md ends with exactly one newline; locate
the headings "Supported Sites" and "Future Plans" and insert an empty line
immediately after each heading line (fixing MD022), then trim or add the final
newline so the file ends with a single trailing newline (fixing MD047).

---

Outside diff comments:
In `@kits/fablens/apps/app/globals.css`:
- Around line 1-27: The CSS linter is flagging Tailwind v4 directives (`@import`
"tailwindcss" and `@theme` inline) in globals.css because there is no Tailwind
config in the linter; add a stylelint/biome override for Tailwind v4 directives
similar to other kits by creating a .stylelintrc.json (or updating biome.json)
in the app directory to recognize at-rules like "tailwind", "apply", "variants",
"responsive", and "layer" (or include the same rule overrides used in the
medical-assistant/poster-generator kits) so the linter accepts the Tailwind v4
syntax used in globals.css.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4bfddb84-eb2b-48d2-aeaa-894b68ea0254

📥 Commits

Reviewing files that changed from the base of the PR and between 6e60d64 and d321d06.

⛔ Files ignored due to path filters (2)
  • kits/fablens/apps/package-lock.json is excluded by !**/package-lock.json
  • kits/fablens/apps/public/logo.png is excluded by !**/*.png
📒 Files selected for processing (19)
  • kits/fablens/.gitignore
  • kits/fablens/README.md
  • kits/fablens/agent.md
  • kits/fablens/apps/.env.example
  • kits/fablens/apps/app/api/analyze/route.ts
  • kits/fablens/apps/app/globals.css
  • kits/fablens/apps/app/layout.tsx
  • kits/fablens/apps/app/page.tsx
  • kits/fablens/apps/lib/materialDB.ts
  • kits/fablens/apps/next-env.d.ts
  • kits/fablens/apps/next.config.ts
  • kits/fablens/apps/package.json
  • kits/fablens/apps/postcss.config.mjs
  • kits/fablens/apps/tsconfig.json
  • kits/fablens/constitutions/default.md
  • kits/fablens/flows/fabric-material-analyzer.ts
  • kits/fablens/lamatic.config.ts
  • kits/fablens/model-configs/fabric-material-analyzer_llmnode-449_generative-model-name.ts
  • kits/fablens/prompts/fabric-material-analyzer_llmnode-449_system_0.md

Comment thread kits/fablens/agent.md
Comment on lines +5 to +60
FabLens is an intelligent consumer tool that helps users make informed clothing purchases by analyzing textile materials from product URLs. It provides a factual, transparent breakdown of environmental impact and skin safety so users can better understand what a garment is made of and what that means in practical terms. [file:2][file:4]

## Purpose

FabLens exists to make fabric information easier to understand. Many fashion product pages mention materials without explaining their real-world implications, so FabLens translates those materials into clear insights about biodegradability, chemical processing, breathability, and irritation risk. [file:2][file:4]

## Flows

### Material Analysis Flow

- **Trigger:** The user pastes a clothing product URL into the FabLens interface. [file:2]
- **Process:** FabLens scrapes the product page, extracts listed material information, checks known fabrics against a local material database, and uses AI fallback analysis for unknown materials. [file:2]
- **Response:** The system returns a structured explanation of each material’s environmental characteristics and skin-safety considerations, including both positives and negatives. [file:2]
- **Dependencies:** This flow depends on Lamatic orchestration, Firecrawl scraping, and the configured AI model. [file:2]

## Guardrails

- FabLens should present factual information, not moral judgments or guilt-based messaging. [file:2]
- FabLens should not assign simplistic scores when the product goal is transparent explanation. [file:2]
- FabLens should clearly distinguish between known material database results and AI fallback analysis. [file:2]
- FabLens should avoid making unsupported claims when the source page does not provide enough material detail. [file:2]

## Integration Reference

FabLens uses Lamatic AI for flow orchestration and analysis, Firecrawl for webpage scraping, Next.js for the frontend application, Tailwind CSS for styling, and Groq with `llama-4-scout` as the language model layer. [file:2]

## Environment Setup

The application requires a Lamatic API key for operation, and the kit configuration also defines a workflow environment key named `FABLENS_WORKFLOW_ID`. [file:2][file:4]

### Required Environment Variables

| Variable | Description |
|---|---|
| `LAMATIC_API_KEY` | Your Lamatic API key from Lamatic Studio. [file:2] |
| `FABLENS_WORKFLOW_ID` | The workflow ID used by the configured Lamatic kit step. [file:4] |

## Quickstart

1. Navigate to `kits/fablens/apps`. [file:2]
2. Copy `.env.example` to `.env.local`. [file:2]
3. Add your `LAMATIC_API_KEY`. [file:2]
4. Install dependencies with `npm install`. [file:2]
5. Start the development server with `npm run dev`. [file:2]

## Common Failure Modes

| Symptom | Likely Cause | Fix |
|---|---|---|
| No material analysis returned | The target site does not list material information clearly. [file:2] | Try a product page that includes fabric details in plain text. [file:2] |
| No scrape results | The target site has scraper protection. [file:2] | Test with supported or simpler sites such as independent brands. [file:2] |
| Flow does not run correctly | Missing API key or workflow configuration. [file:2][file:4] | Verify `LAMATIC_API_KEY` and `FABLENS_WORKFLOW_ID` are set correctly. [file:2][file:4] |

## Scope

FabLens is currently designed for clothing product pages and works best on sites that expose material details in readable text. Support for furniture, cosmetics, image-based material detection, percentage-weighted scoring, and a larger material database are planned for future versions. [file:2] No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mission cleanup: remove unresolved [file:*] reference artifacts.

These labels are undefined (MD052) and render as broken references; also add a single trailing newline at EOF (MD047).

Proposed direction
-FabLens is an intelligent consumer tool ... practical terms. [file:2][file:4]
+FabLens is an intelligent consumer tool ... practical terms.

Apply the same cleanup for all [file:2] / [file:4] occurrences across this document.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FabLens is an intelligent consumer tool that helps users make informed clothing purchases by analyzing textile materials from product URLs. It provides a factual, transparent breakdown of environmental impact and skin safety so users can better understand what a garment is made of and what that means in practical terms. [file:2][file:4]
## Purpose
FabLens exists to make fabric information easier to understand. Many fashion product pages mention materials without explaining their real-world implications, so FabLens translates those materials into clear insights about biodegradability, chemical processing, breathability, and irritation risk. [file:2][file:4]
## Flows
### Material Analysis Flow
- **Trigger:** The user pastes a clothing product URL into the FabLens interface. [file:2]
- **Process:** FabLens scrapes the product page, extracts listed material information, checks known fabrics against a local material database, and uses AI fallback analysis for unknown materials. [file:2]
- **Response:** The system returns a structured explanation of each materials environmental characteristics and skin-safety considerations, including both positives and negatives. [file:2]
- **Dependencies:** This flow depends on Lamatic orchestration, Firecrawl scraping, and the configured AI model. [file:2]
## Guardrails
- FabLens should present factual information, not moral judgments or guilt-based messaging. [file:2]
- FabLens should not assign simplistic scores when the product goal is transparent explanation. [file:2]
- FabLens should clearly distinguish between known material database results and AI fallback analysis. [file:2]
- FabLens should avoid making unsupported claims when the source page does not provide enough material detail. [file:2]
## Integration Reference
FabLens uses Lamatic AI for flow orchestration and analysis, Firecrawl for webpage scraping, Next.js for the frontend application, Tailwind CSS for styling, and Groq with `llama-4-scout` as the language model layer. [file:2]
## Environment Setup
The application requires a Lamatic API key for operation, and the kit configuration also defines a workflow environment key named `FABLENS_WORKFLOW_ID`. [file:2][file:4]
### Required Environment Variables
| Variable | Description |
|---|---|
| `LAMATIC_API_KEY` | Your Lamatic API key from Lamatic Studio. [file:2] |
| `FABLENS_WORKFLOW_ID` | The workflow ID used by the configured Lamatic kit step. [file:4] |
## Quickstart
1. Navigate to `kits/fablens/apps`. [file:2]
2. Copy `.env.example` to `.env.local`. [file:2]
3. Add your `LAMATIC_API_KEY`. [file:2]
4. Install dependencies with `npm install`. [file:2]
5. Start the development server with `npm run dev`. [file:2]
## Common Failure Modes
| Symptom | Likely Cause | Fix |
|---|---|---|
| No material analysis returned | The target site does not list material information clearly. [file:2] | Try a product page that includes fabric details in plain text. [file:2] |
| No scrape results | The target site has scraper protection. [file:2] | Test with supported or simpler sites such as independent brands. [file:2] |
| Flow does not run correctly | Missing API key or workflow configuration. [file:2][file:4] | Verify `LAMATIC_API_KEY` and `FABLENS_WORKFLOW_ID` are set correctly. [file:2][file:4] |
## Scope
FabLens is currently designed for clothing product pages and works best on sites that expose material details in readable text. Support for furniture, cosmetics, image-based material detection, percentage-weighted scoring, and a larger material database are planned for future versions. [file:2]
FabLens is an intelligent consumer tool that helps users make informed clothing purchases by analyzing textile materials from product URLs. It provides a factual, transparent breakdown of environmental impact and skin safety so users can better understand what a garment is made of and what that means in practical terms.
## Purpose
FabLens exists to make fabric information easier to understand. Many fashion product pages mention materials without explaining their real-world implications, so FabLens translates those materials into clear insights about biodegradability, chemical processing, breathability, and irritation risk.
## Flows
### Material Analysis Flow
- **Trigger:** The user pastes a clothing product URL into the FabLens interface.
- **Process:** FabLens scrapes the product page, extracts listed material information, checks known fabrics against a local material database, and uses AI fallback analysis for unknown materials.
- **Response:** The system returns a structured explanation of each material's environmental characteristics and skin-safety considerations, including both positives and negatives.
- **Dependencies:** This flow depends on Lamatic orchestration, Firecrawl scraping, and the configured AI model.
## Guardrails
- FabLens should present factual information, not moral judgments or guilt-based messaging.
- FabLens should not assign simplistic scores when the product goal is transparent explanation.
- FabLens should clearly distinguish between known material database results and AI fallback analysis.
- FabLens should avoid making unsupported claims when the source page does not provide enough material detail.
## Integration Reference
FabLens uses Lamatic AI for flow orchestration and analysis, Firecrawl for webpage scraping, Next.js for the frontend application, Tailwind CSS for styling, and Groq with `llama-4-scout` as the language model layer.
## Environment Setup
The application requires a Lamatic API key for operation, and the kit configuration also defines a workflow environment key named `FABLENS_WORKFLOW_ID`.
### Required Environment Variables
| Variable | Description |
|---|---|
| `LAMATIC_API_KEY` | Your Lamatic API key from Lamatic Studio. |
| `FABLENS_WORKFLOW_ID` | The workflow ID used by the configured Lamatic kit step. |
## Quickstart
1. Navigate to `kits/fablens/apps`.
2. Copy `.env.example` to `.env.local`.
3. Add your `LAMATIC_API_KEY`.
4. Install dependencies with `npm install`.
5. Start the development server with `npm run dev`.
## Common Failure Modes
| Symptom | Likely Cause | Fix |
|---|---|---|
| No material analysis returned | The target site does not list material information clearly. | Try a product page that includes fabric details in plain text. |
| No scrape results | The target site has scraper protection. | Test with supported or simpler sites such as independent brands. |
| Flow does not run correctly | Missing API key or workflow configuration. | Verify `LAMATIC_API_KEY` and `FABLENS_WORKFLOW_ID` are set correctly. |
## Scope
FabLens is currently designed for clothing product pages and works best on sites that expose material details in readable text. Support for furniture, cosmetics, image-based material detection, percentage-weighted scoring, and a larger material database are planned for future versions.
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 5-5: Reference links and images should use a label that is defined
Missing link or image reference definition: "file"

(MD052, reference-links-images)


[warning] 9-9: Reference links and images should use a label that is defined
Missing link or image reference definition: "file"

(MD052, reference-links-images)


[warning] 33-33: Reference links and images should use a label that is defined
Missing link or image reference definition: "file"

(MD052, reference-links-images)


[warning] 56-56: Reference links and images should use a label that is defined
Missing link or image reference definition: "file"

(MD052, reference-links-images)


[warning] 56-56: Reference links and images should use a label that is defined
Missing link or image reference definition: "file"

(MD052, reference-links-images)


[warning] 60-60: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/agent.md` around lines 5 - 60, Remove all unresolved artifact
references like "[file:2]" and "[file:4]" throughout the FabLens README (e.g.,
within the "FabLens" intro, "Purpose", "Material Analysis Flow", "Environment
Setup", "Required Environment Variables", "Quickstart", "Common Failure Modes",
and "Scope" sections) and ensure the file ends with a single trailing newline;
keep the surrounding text intact and preserve variable names such as
LAMATIC_API_KEY and FABLENS_WORKFLOW_ID and section headings while deleting only
the bracketed file tokens.

Comment thread kits/fablens/apps/app/api/analyze/route.ts Outdated
Comment thread kits/fablens/apps/app/api/analyze/route.ts Outdated
Comment thread kits/fablens/apps/app/api/analyze/route.ts Outdated
Comment thread kits/fablens/apps/app/api/analyze/route.ts Outdated
Comment on lines +20 to +25
"scraperNode_601": [
{
"name": "credentials",
"label": "Credentials",
"type": "select"
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission-critical: stop bypassing the selectable scraper credential.

Line 83 hardcodes "my-firecrawl-creds" while Lines 20-25 define a configurable credentials input. This will fail in environments where credential IDs differ and makes the declared input effectively unused.

Also applies to: 83-83

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/flows/fabric-material-analyzer.ts` around lines 20 - 25, The
flow currently ignores the configurable credentials input by hardcoding
"my-firecrawl-creds"; locate the node configuration under scraperNode_601 that
references the literal "my-firecrawl-creds" and replace it with the configurable
credentials value (use the flow/input reference for the "credentials" field,
e.g. read inputs.credentials or node.inputs.credentials depending on the flow
runtime) so the scraper uses the declared "credentials" input instead of a fixed
ID.

],
"includeTags": [],
"onlyMainContent": true,
"skipTLsVerification": true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission-critical: re-enable TLS verification for scraper calls.

Line 93 sets skipTLsVerification: true, which weakens transport security and increases MITM risk. Default this to false unless there is a documented, time-bounded exception.

Suggested patch
-        "skipTLsVerification": true
+        "skipTLsVerification": false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"skipTLsVerification": true
"skipTLsVerification": false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/flows/fabric-material-analyzer.ts` at line 93, The configuration
currently sets skipTLsVerification: true which disables TLS verification for
scraper calls; change that setting to skipTLsVerification: false (or remove the
override so the default secure behavior is used) in the scraper/client config,
ensure any code paths that construct the scraper/http client (look for the
object containing the skipTLsVerification property) do not disable certificate
checks, and if a temporary exception is required document it with a timestamped
TODO and add a test or runtime assertion to prevent committing
skipTLsVerification: true long-term.

"note": "No material information found on page"
}
Return ONLY valid JSON.
No explanation. No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mission polish: add trailing newline at EOF.

Line 29 currently triggers MD047; add a single trailing newline.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 29-29: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/prompts/fabric-material-analyzer_llmnode-449_system_0.md` at
line 29, Add a single trailing newline at the end of the markdown file
fabric-material-analyzer_llmnode-449_system_0.md to satisfy MD047; open the file
and ensure the last line ends with a newline character (no other content
changes), then save the file so the EOF contains exactly one trailing newline.

Comment thread kits/fablens/README.md
Comment on lines +33 to +38
## Environment Variables

| Variable | Description |
|----------|-------------|
| `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission-critical docs gap: add FABLENS_WORKFLOW_ID to environment variables.

The setup table is incomplete; users can miss a required config and fail runtime setup.

Proposed patch
 | Variable | Description |
 |----------|-------------|
 | `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |
+| `FABLENS_WORKFLOW_ID` | Workflow ID used by the FabLens Lamatic step |
As per coding guidelines, "Every kit must have a `README.md` that documents setup, environment variables, and usage".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Environment Variables
| Variable | Description |
|----------|-------------|
| `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |
## Environment Variables
| Variable | Description |
|----------|-------------|
| `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |
| `FABLENS_WORKFLOW_ID` | Workflow ID used by the FabLens Lamatic step |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/README.md` around lines 33 - 38, Update the Environment
Variables table in kits/fablens/README.md to include the missing
FABLENS_WORKFLOW_ID entry: add a new row with `FABLENS_WORKFLOW_ID` as the
Variable and a brief Description (e.g., "Workflow ID used by FabLens to select
the processing workflow") so the README documents all required runtime
configuration alongside `LAMATIC_API_KEY`; ensure formatting matches the
existing Markdown table style.

Comment thread kits/fablens/README.md Outdated
Copy link
Copy Markdown
Contributor

@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: 5

♻️ Duplicate comments (10)
kits/fablens/README.md (1)

53-71: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Markdown formatting violations from previous review remain unresolved.

## Supported Sites (Line 53), ## Future Plans (Line 60), and ## Limitations (Line 67) are missing blank lines below (MD022), and the file lacks a trailing newline (MD047). These were flagged in the prior review cycle.

📝 Proposed fix
 ## Supported Sites
+
 Works best with product pages that clearly list materials:
 
 ## Future Plans
+
 - Percentage-weighted scoring
...
 ## Limitations
+
 - Sites with bot protection (e.g. H&M, Amazon) may fail
 - Missing material data → no analysis
 - Compound materials (e.g. polycotton) may not always resolve accurately
-- No percentage-weighted scoring
+- No percentage-weighted scoring
+
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/README.md` around lines 53 - 71, The README.md has Markdown
style violations: add a single blank line after each top-level heading
"Supported Sites", "Future Plans", and "Limitations" so those headings are
followed by an empty line (fixes MD022), and ensure the file ends with a
trailing newline character (fixes MD047); update the sections in
kits/fablens/README.md accordingly so each heading is followed by one blank line
and the file ends with a newline.
kits/fablens/apps/app/api/analyze/route.ts (5)

105-109: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

rawMaterials assigned without Array.isArray guard — will throw at runtime if the model returns a non-array.

parsed.materials || parsed.fabric || parsed.textiles || [] is typed as string[] but not validated. If the LLM returns "materials": "cotton, polyester" (a string), line 123's .map(normalizeMaterial) will iterate over individual characters. This was flagged in the previous review cycle and remains unresolved.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 105 - 109, The
assignment to rawMaterials assumes parsed.materials|fabric|textiles is an array
but can be a string; update the logic where rawMaterials is set (the symbol
rawMaterials in route.ts) to first check Array.isArray(...) for
parsed.materials, parsed.fabric, parsed.textiles and use the first array found,
otherwise if a string is found split by commas (or wrap a non-empty string into
a single-item array) and trim entries; ensure the downstream call to
normalizeMaterial still receives a string[] so .map(normalizeMaterial) won't
iterate characters of a string.

173-197: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

AI fallback invokes the material-extraction workflow, not a scoring workflow — contract mismatch.

callLamatic(...) at line 176 uses the same hardcoded workflowId (55a58aab-...) as the primary extraction call, but sends only a question string (no url). The extraction workflow expects a URL to scrape; receiving a plain text question about unknown materials is a contract mismatch that will silently produce empty or malformed scoring data. This was flagged in the previous review cycle and remains unresolved.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 173 - 197, The AI
fallback is calling callLamatic with the material-extraction workflow (same
hardcoded workflowId used elsewhere) but sending a plain text question, causing
a contract mismatch and bad results; update the fallback in the
unknown-materials branch to invoke the scoring workflow (use the correct scoring
workflowId instead of the extraction workflowId `55a58aab-...`) and send the
payload fields that workflow expects (pass the extracted materials as the proper
input field(s) — e.g., a materials list or `question`/`materials` param per the
scoring workflow contract) so the response contains ecoScore/skinScore JSON
compatible with the existing parsing logic around parsedAI and safeJSONParse.

82-86: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Both callLamatic invocations lack timeouts — requests can hang indefinitely.

Neither the primary extraction call (line 82) nor the AI fallback call (line 176) has an AbortController timeout, leaving server-side request workers blocked until the remote endpoint decides to respond. This was flagged in the previous review cycle and remains unresolved.

Also applies to: 174-178

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 82 - 86, The two
calls to callLamatic (the primary "extract materials" invocation and the AI
fallback call used later) can hang indefinitely; add an AbortController-based
timeout around each call: create an AbortController, start a setTimeout that
calls controller.abort() after a sensible timeout (e.g., 5–15s), pass
controller.signal into callLamatic (or into the underlying fetch/options used by
callLamatic), and clear the timer on success; ensure callLamatic (or its caller)
propagates abort errors so they can be handled/translated into a proper timeout
error instead of leaving the worker blocked.

36-60: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Hardcoded Lamatic host, project ID, and workflow ID — still not externalized.

The deployment-specific host URL (line 38), x-project-id (line 44), and workflowId (line 53) are all hardcoded. This was flagged in the previous review cycle and remains unresolved. Critically, this also means the env vars LAMATIC_HOST, LAMATIC_PROJECT_ID, and LAMATIC_WORKFLOW_ID documented in the README are silently ignored — users who follow the setup guide will be left confused.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 36 - 60, The
callLamatic function currently hardcodes the Lamatic host URL, x-project-id
header and workflowId; update callLamatic to read process.env.LAMATIC_HOST (for
the full GraphQL endpoint), process.env.LAMATIC_PROJECT_ID (for the x-project-id
header) and process.env.LAMATIC_WORKFLOW_ID (for the variables.workflowId) with
sensible fallbacks or fail-fast errors if missing, ensure Authorization still
uses process.env.LAMATIC_API_KEY, and keep the rest of the GraphQL body intact;
reference the function name callLamatic and the header key "x-project-id" and
variable name "workflowId" when making the changes.

62-79: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

URL input forwarded to Lamatic without protocol validation — SSRF risk.

body?.url is only checked for truthiness (line 74). Any non-empty string — including file://, http://internal-host/, or other non-HTTP schemes — is forwarded to the Lamatic workflow. This was flagged in the previous review cycle and remains unresolved.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 62 - 79, The POST
handler currently accepts any non-empty body?.url and forwards it to Lamatic,
which allows non-HTTP schemes and enables SSRF; update the POST function to
parse and validate the incoming URL using the URL constructor (or equivalent)
and enforce an http or https scheme only, returning a 400 JSON response when
parsing fails or when the protocol is not "http:" or "https:"; additionally,
consider rejecting IPs/hosts in private address ranges if you want stricter SSRF
protection.
kits/fablens/apps/app/page.tsx (3)

88-115: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Emoji status icons still violate the lucide-react icon convention.

Lines 90 and 115 use raw emoji (🌱, 🧴) instead of lucide-react components. lucide-react is already declared as a dependency. This was flagged in the previous review cycle and remains unaddressed. As per coding guidelines, "Use lucide-react for icons throughout kits."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/page.tsx` around lines 88 - 115, Replace the raw emoji
icons with lucide-react icon components: locate the eco section rendering the
line containing "🌱 Eco Friendly: {data.ecoScore}%" and the skin section
rendering "🧴 Skin Friendly: {data.skinScore}%", import appropriate icons from
'lucide-react' (e.g., Leaf or Sprout for eco and Bottle or Soap for skin) and
render those components inline next to the label; ensure any props
(size/className) match existing styling and remove the emoji characters,
updating the JSX around data.ecoScore, data.skinScore, and the showEco-related
markup as needed.

22-42: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

AbortController timeout still missing — fetch can hang indefinitely.

The finally block was added (good), but there is still no AbortController-based timeout. A stalled network request will leave the app in a perpetual loading state from the user's perspective. This was flagged in the previous review cycle.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/page.tsx` around lines 22 - 42, The analyze function
can hang because fetch has no timeout; add an AbortController inside analyze,
pass controller.signal to fetch, and start a timeout (e.g., via setTimeout) that
calls controller.abort() after a reasonable interval; ensure you clear the
timeout when fetch completes or errors, handle the abort case in the catch to
setData({ note: 'Request timed out' }) or similar, and still call
setLoading(false) in the finally block so setLoading, setData, and the
AbortController/timeout are coordinated.

59-64: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

URL input has no accessible label — screen readers cannot identify the field.

No <label>, aria-label, or aria-labelledby is associated with this input. This was flagged in the previous review cycle and remains unresolved.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/page.tsx` around lines 59 - 64, The URL input lacks an
accessible label; update the input in app/page.tsx to include either a visible
<label> tied to the input via an id (e.g., id="url-input" and <label
htmlFor="url-input">URL</label>) or add an appropriate
aria-label/aria-labelledby attribute so screen readers can identify it; ensure
you keep the existing value={url} and onChange={(e) => setUrl(e.target.value)}
behavior and use the same id/label text to maintain accessibility and clarity.
kits/fablens/apps/package.json (1)

16-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

devDependencies caret ranges — version pinning still violated.

All six devDependencies still use unpinned caret ranges (^4, ^20, ^19, ^5), which was flagged in the previous review cycle but remains unaddressed. Each entry must be pinned to an exact resolved version. As per coding guidelines, "Each kit must have its own package.json with pinned dependency versions".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/package.json` around lines 16 - 22, The devDependencies in
package.json are still using caret ranges; update each entry
(`@tailwindcss/postcss`, `@types/node`, `@types/react`, `@types/react-dom`, tailwindcss,
typescript) to a pinned exact version (e.g. replace "^4" / "^20" / "^19" / "^5"
with the resolved semver like "4.0.1" etc.) so no caret ranges remain; after
editing package.json, run the package manager to regenerate lockfile
(npm/yarn/pnpm) and commit the updated lockfile to ensure deterministic
installs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/fablens/apps/app/globals.css`:
- Around line 11-17: The Biome parser chokes on the Tailwind v4 at-rule "@theme
inline"; to fix, suppress the Biome parse rule for that block or disable Biome
CSS linting for this file: add a block-level Biome ignore comment targeting
parse/noUnknownAtRule immediately above the "@theme inline" block (so the Biome
parser will skip that at-rule), or update the project's Biome config to exempt
this CSS file from CSS linting—target the "@theme inline" block or file so
linting no longer fails in CI.

In `@kits/fablens/apps/app/page.tsx`:
- Around line 18-20: The expand/collapse booleans (showEco, showSkin, showNeg)
are not reset when analyze() starts a new request; update the analyze() start
logic so that, alongside the existing setData(null) call, you also call
setShowEco(false), setShowSkin(false), and setShowNeg(false) to clear prior UI
state before fetching new analysis.
- Around line 48-52: Replace the raw <img> with Next.js' Image component: add
"import Image from 'next/image'" at the top of page.tsx, then replace the img
element with <Image src="/logo.png" alt="fablens-logo" className="w-60 h-auto
border-[`#587c47`] border-2 rounded-xl" width={240} height={240} /> (adjust
width/height to match the tailwind w-60 sizing or use layout strategies like
fill if preferred) so Next's optimization, lazy-loading and sizing are used.

In `@kits/fablens/apps/package.json`:
- Line 11: Update the package.json dependency entry for lucide-react to the
pinned version "1.14.0" (replace the caret range "^1.14.0"), and then either
remove lucide-react from dependencies if it's not used or replace the emoji
strings in page.tsx (the "🌱" and "🧴" occurrences) with the appropriate
lucide-react icon components and import them at the top of page.tsx (e.g.,
import { IconName } from 'lucide-react'), ensuring the imports and usages match
the actual icon component names so the dependency is actually consumed.

In `@kits/fablens/README.md`:
- Around line 46-51: The README lists LAMATIC_HOST, LAMATIC_PROJECT_ID, and
LAMATIC_WORKFLOW_ID but route.ts still uses hardcoded values, so update
kits/fablens/apps/app/api/analyze/route.ts to read those values from process.env
(use process.env.LAMATIC_HOST, process.env.LAMATIC_PROJECT_ID,
process.env.LAMATIC_WORKFLOW_ID) instead of the hardcoded host/project/workflow
constants; ensure you keep the existing LAMATIC_API_KEY read from process.env
and add sensible validation or error messages in the same initialization block
(the constants/variables around where the hardcoded host, projectId, and
workflowId are defined and used).

---

Duplicate comments:
In `@kits/fablens/apps/app/api/analyze/route.ts`:
- Around line 105-109: The assignment to rawMaterials assumes
parsed.materials|fabric|textiles is an array but can be a string; update the
logic where rawMaterials is set (the symbol rawMaterials in route.ts) to first
check Array.isArray(...) for parsed.materials, parsed.fabric, parsed.textiles
and use the first array found, otherwise if a string is found split by commas
(or wrap a non-empty string into a single-item array) and trim entries; ensure
the downstream call to normalizeMaterial still receives a string[] so
.map(normalizeMaterial) won't iterate characters of a string.
- Around line 173-197: The AI fallback is calling callLamatic with the
material-extraction workflow (same hardcoded workflowId used elsewhere) but
sending a plain text question, causing a contract mismatch and bad results;
update the fallback in the unknown-materials branch to invoke the scoring
workflow (use the correct scoring workflowId instead of the extraction
workflowId `55a58aab-...`) and send the payload fields that workflow expects
(pass the extracted materials as the proper input field(s) — e.g., a materials
list or `question`/`materials` param per the scoring workflow contract) so the
response contains ecoScore/skinScore JSON compatible with the existing parsing
logic around parsedAI and safeJSONParse.
- Around line 82-86: The two calls to callLamatic (the primary "extract
materials" invocation and the AI fallback call used later) can hang
indefinitely; add an AbortController-based timeout around each call: create an
AbortController, start a setTimeout that calls controller.abort() after a
sensible timeout (e.g., 5–15s), pass controller.signal into callLamatic (or into
the underlying fetch/options used by callLamatic), and clear the timer on
success; ensure callLamatic (or its caller) propagates abort errors so they can
be handled/translated into a proper timeout error instead of leaving the worker
blocked.
- Around line 36-60: The callLamatic function currently hardcodes the Lamatic
host URL, x-project-id header and workflowId; update callLamatic to read
process.env.LAMATIC_HOST (for the full GraphQL endpoint),
process.env.LAMATIC_PROJECT_ID (for the x-project-id header) and
process.env.LAMATIC_WORKFLOW_ID (for the variables.workflowId) with sensible
fallbacks or fail-fast errors if missing, ensure Authorization still uses
process.env.LAMATIC_API_KEY, and keep the rest of the GraphQL body intact;
reference the function name callLamatic and the header key "x-project-id" and
variable name "workflowId" when making the changes.
- Around line 62-79: The POST handler currently accepts any non-empty body?.url
and forwards it to Lamatic, which allows non-HTTP schemes and enables SSRF;
update the POST function to parse and validate the incoming URL using the URL
constructor (or equivalent) and enforce an http or https scheme only, returning
a 400 JSON response when parsing fails or when the protocol is not "http:" or
"https:"; additionally, consider rejecting IPs/hosts in private address ranges
if you want stricter SSRF protection.

In `@kits/fablens/apps/app/page.tsx`:
- Around line 88-115: Replace the raw emoji icons with lucide-react icon
components: locate the eco section rendering the line containing "🌱 Eco
Friendly: {data.ecoScore}%" and the skin section rendering "🧴 Skin Friendly:
{data.skinScore}%", import appropriate icons from 'lucide-react' (e.g., Leaf or
Sprout for eco and Bottle or Soap for skin) and render those components inline
next to the label; ensure any props (size/className) match existing styling and
remove the emoji characters, updating the JSX around data.ecoScore,
data.skinScore, and the showEco-related markup as needed.
- Around line 22-42: The analyze function can hang because fetch has no timeout;
add an AbortController inside analyze, pass controller.signal to fetch, and
start a timeout (e.g., via setTimeout) that calls controller.abort() after a
reasonable interval; ensure you clear the timeout when fetch completes or
errors, handle the abort case in the catch to setData({ note: 'Request timed
out' }) or similar, and still call setLoading(false) in the finally block so
setLoading, setData, and the AbortController/timeout are coordinated.
- Around line 59-64: The URL input lacks an accessible label; update the input
in app/page.tsx to include either a visible <label> tied to the input via an id
(e.g., id="url-input" and <label htmlFor="url-input">URL</label>) or add an
appropriate aria-label/aria-labelledby attribute so screen readers can identify
it; ensure you keep the existing value={url} and onChange={(e) =>
setUrl(e.target.value)} behavior and use the same id/label text to maintain
accessibility and clarity.

In `@kits/fablens/apps/package.json`:
- Around line 16-22: The devDependencies in package.json are still using caret
ranges; update each entry (`@tailwindcss/postcss`, `@types/node`, `@types/react`,
`@types/react-dom`, tailwindcss, typescript) to a pinned exact version (e.g.
replace "^4" / "^20" / "^19" / "^5" with the resolved semver like "4.0.1" etc.)
so no caret ranges remain; after editing package.json, run the package manager
to regenerate lockfile (npm/yarn/pnpm) and commit the updated lockfile to ensure
deterministic installs.

In `@kits/fablens/README.md`:
- Around line 53-71: The README.md has Markdown style violations: add a single
blank line after each top-level heading "Supported Sites", "Future Plans", and
"Limitations" so those headings are followed by an empty line (fixes MD022), and
ensure the file ends with a trailing newline character (fixes MD047); update the
sections in kits/fablens/README.md accordingly so each heading is followed by
one blank line and the file ends with a newline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 67a18202-b8a2-4ead-a953-30766b1372b1

📥 Commits

Reviewing files that changed from the base of the PR and between d321d06 and ac675a0.

⛔ Files ignored due to path filters (1)
  • kits/fablens/apps/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • kits/fablens/README.md
  • kits/fablens/apps/app/api/analyze/route.ts
  • kits/fablens/apps/app/globals.css
  • kits/fablens/apps/app/page.tsx
  • kits/fablens/apps/package.json

Comment thread kits/fablens/apps/app/globals.css Outdated
Comment thread kits/fablens/apps/app/page.tsx
Comment thread kits/fablens/apps/app/page.tsx Outdated
Comment thread kits/fablens/apps/package.json Outdated
Comment thread kits/fablens/README.md
Copy link
Copy Markdown
Contributor

@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: 3

♻️ Duplicate comments (3)
kits/fablens/apps/package.json (1)

21-23: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission-critical: lock and upgrade the Tailwind toolchain before launch.

Your objective: eliminate version ranges and move tailwindcss to a pinned v4+ release.
Right now, autoprefixer/tailwindcss are unpinned (^...), and tailwindcss is on v3, which conflicts with the kit Tailwind v4 requirement.

#!/bin/bash
set -euo pipefail

echo "Checking ranged versions in FabLens app manifest..."
rg -n '"(autoprefixer|tailwindcss)"\s*:\s*"\^' kits/fablens/apps/package.json || true

echo
echo "Current toolchain entries:"
rg -n '"(`@tailwindcss/postcss`|autoprefixer|tailwindcss)"\s*:' kits/fablens/apps/package.json

As per coding guidelines, "Each kit must have its own package.json with pinned dependency versions; do not rely on workspace-level hoisting or a root package.json" and "Use Tailwind CSS v4+ for styling kits".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/package.json` around lines 21 - 23, The package.json
currently uses ranged versions for autroprefixer and tailwindcss and pins
tailwindcss to v3; update kits/fablens/apps/package.json to replace the caret
ranges with exact version strings and bump tailwindcss to a v4+ release (e.g.,
"tailwindcss": "4.x.x") and pin autoprefixer to a specific version (e.g.,
"autoprefixer": "10.5.0" -> "10.5.0" or newer exact), ensuring both are exact
(no ^ or ~) so the FabLens app has its own locked toolchain and complies with
the kit Tailwind v4+ requirement.
kits/fablens/apps/app/api/analyze/route.ts (2)

134-140: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission alert: sanitize AI material arrays before normalization.

Array candidates are trusted as string[] without filtering. If an item is non-string, normalization will crash at runtime.

🧪 Proposed patch
     for (const c of candidates) {
       if (Array.isArray(c)) {
-        rawMaterials = c;
+        rawMaterials = c
+          .filter((v: unknown): v is string => typeof v === "string")
+          .map((s) => s.trim())
+          .filter(Boolean);
         break;
       } else if (typeof c === "string") {
-        rawMaterials = c.split(",").map((s) => s.trim());
+        rawMaterials = c.split(",").map((s) => s.trim()).filter(Boolean);
         break;
       }
     }

Also applies to: 157-158

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 134 - 140, The loop
over candidates assigns rawMaterials trusting array items are strings and splits
strings without sanitization; update the Array.isArray(c) branch to set
rawMaterials = c.filter((s) => typeof s === "string") and the typeof c ===
"string" branch to split and then filter (e.g.,
c.split(",").map(...).filter((s)=>typeof s === "string")) so normalization won't
receive non-string values; apply the same sanitization to the second occurrence
referenced around lines 157-158 (same variables candidates and rawMaterials).

40-43: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission-critical: decouple extraction and scoring workflows now.

callLamatic is hard-bound to LAMATIC_WORKFLOW_ID, so the fallback path cannot target LAMATIC_SCORING_WORKFLOW_ID. Your fallback is effectively locked to extraction workflow behavior.

🛠️ Proposed patch sketch
-async function callLamatic(question: string, url?: string) {
+async function callLamatic(workflowId: string, question: string, url?: string) {
@@
-  const workflowId = process.env.LAMATIC_WORKFLOW_ID;
+  // workflowId passed by caller
@@
-    const response = await callLamatic("extract materials", parsedUrl.href);
+    const extractionWorkflowId = process.env.LAMATIC_WORKFLOW_ID;
+    const scoringWorkflowId = process.env.LAMATIC_SCORING_WORKFLOW_ID;
+    if (!extractionWorkflowId || !scoringWorkflowId) {
+      throw new Error("Missing Lamatic workflow configuration");
+    }
+    const response = await callLamatic(extractionWorkflowId, "extract materials", parsedUrl.href);
@@
-        const aiRes = await callLamatic(
+        const aiRes = await callLamatic(
+          scoringWorkflowId,
           `Analyze these materials: ${unknown.join(", ")}. Return JSON only.`
         );

Also applies to: 207-211

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 40 - 43, The code
currently binds callLamatic to a single LAMATIC_WORKFLOW_ID (via workflowId),
preventing the fallback path from targeting the scoring workflow; change the
environment wiring to read a separate LAMATIC_SCORING_WORKFLOW_ID (e.g., add
const scoringWorkflowId = process.env.LAMATIC_SCORING_WORKFLOW_ID) and update
call sites of callLamatic and any logic that decides which workflow to call
(including the spots around the variables host/projectId/workflowId and the
other area mentioned) so the fallback uses scoringWorkflowId while the primary
path uses workflowId; ensure the selection logic passes the appropriate
workflowId variable into callLamatic instead of hardcoding LAMATIC_WORKFLOW_ID.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kits/fablens/apps/app/page.tsx`:
- Line 37: The client-side abort currently calls controller.abort() after const
timeout = setTimeout(() => controller.abort(), 10000), which is shorter than the
backend worst-case (12s+), causing premature "Request timed out" responses;
update the timeout logic in page.tsx so the setTimeout delay is increased to at
least the backend worst-case (e.g., >= 20000) or, better, derive it from a
shared config/ENV (e.g., BACKEND_TIMEOUT_MS) and use that value for setTimeout,
ensuring you still call clearTimeout(timeout) when the request completes to
avoid leaks.

In `@kits/fablens/apps/postcss.config.mjs`:
- Around line 2-4: Update the PostCSS plugins object to use the consolidated
Tailwind v4 plugin: replace the existing entries "tailwindcss" and
"autoprefixer" in the plugins map with a single "@tailwindcss/postcss": {} entry
(i.e., remove the tailwindcss and autoprefixer keys and add
"@tailwindcss/postcss": {}), ensuring the plugins object only references the new
consolidated plugin so Tailwind v4 is properly loaded.

In `@kits/fablens/README.md`:
- Around line 46-52: Add the missing environment variable
LAMATIC_SCORING_WORKFLOW_ID to the README's environment variables table so
operators see it alongside LAMATIC_API_KEY, LAMATIC_PROJECT_ID,
LAMATIC_WORKFLOW_ID, and LAMATIC_HOST; update the table row for
`LAMATIC_SCORING_WORKFLOW_ID` with a short description like "Scoring workflow ID
used for model scoring/validation" to match `.env.example` and ensure README
setup docs list all vars referenced by the kit.

---

Duplicate comments:
In `@kits/fablens/apps/app/api/analyze/route.ts`:
- Around line 134-140: The loop over candidates assigns rawMaterials trusting
array items are strings and splits strings without sanitization; update the
Array.isArray(c) branch to set rawMaterials = c.filter((s) => typeof s ===
"string") and the typeof c === "string" branch to split and then filter (e.g.,
c.split(",").map(...).filter((s)=>typeof s === "string")) so normalization won't
receive non-string values; apply the same sanitization to the second occurrence
referenced around lines 157-158 (same variables candidates and rawMaterials).
- Around line 40-43: The code currently binds callLamatic to a single
LAMATIC_WORKFLOW_ID (via workflowId), preventing the fallback path from
targeting the scoring workflow; change the environment wiring to read a separate
LAMATIC_SCORING_WORKFLOW_ID (e.g., add const scoringWorkflowId =
process.env.LAMATIC_SCORING_WORKFLOW_ID) and update call sites of callLamatic
and any logic that decides which workflow to call (including the spots around
the variables host/projectId/workflowId and the other area mentioned) so the
fallback uses scoringWorkflowId while the primary path uses workflowId; ensure
the selection logic passes the appropriate workflowId variable into callLamatic
instead of hardcoding LAMATIC_WORKFLOW_ID.

In `@kits/fablens/apps/package.json`:
- Around line 21-23: The package.json currently uses ranged versions for
autroprefixer and tailwindcss and pins tailwindcss to v3; update
kits/fablens/apps/package.json to replace the caret ranges with exact version
strings and bump tailwindcss to a v4+ release (e.g., "tailwindcss": "4.x.x") and
pin autoprefixer to a specific version (e.g., "autoprefixer": "10.5.0" ->
"10.5.0" or newer exact), ensuring both are exact (no ^ or ~) so the FabLens app
has its own locked toolchain and complies with the kit Tailwind v4+ requirement.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1d1d765e-3a12-4d52-a4dc-49ce4343116b

📥 Commits

Reviewing files that changed from the base of the PR and between ac675a0 and 4deaa1c.

⛔ Files ignored due to path filters (1)
  • kits/fablens/apps/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • kits/fablens/README.md
  • kits/fablens/apps/.env.example
  • kits/fablens/apps/app/api/analyze/route.ts
  • kits/fablens/apps/app/globals.css
  • kits/fablens/apps/app/page.tsx
  • kits/fablens/apps/package.json
  • kits/fablens/apps/postcss.config.mjs
  • kits/fablens/apps/tailwind.config.js

setShowNeg(false);

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mission reliability gap: align client timeout with backend worst-case latency.

Client aborts at 10s, but backend can take 12s for one Lamatic call and longer with fallback. This will produce avoidable “Request timed out” responses on valid requests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/app/page.tsx` at line 37, The client-side abort currently
calls controller.abort() after const timeout = setTimeout(() =>
controller.abort(), 10000), which is shorter than the backend worst-case (12s+),
causing premature "Request timed out" responses; update the timeout logic in
page.tsx so the setTimeout delay is increased to at least the backend worst-case
(e.g., >= 20000) or, better, derive it from a shared config/ENV (e.g.,
BACKEND_TIMEOUT_MS) and use that value for setTimeout, ensuring you still call
clearTimeout(timeout) when the request completes to avoid leaks.

Comment on lines +2 to +4
plugins: {
tailwindcss: {},
autoprefixer: {},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "PostCSS plugin config:"
sed -n '1,80p' kits/fablens/apps/postcss.config.mjs

echo
echo "Tailwind/PostCSS deps:"
rg -n '"(`@tailwindcss/postcss`|tailwindcss|autoprefixer)"\s*:' kits/fablens/apps/package.json

Repository: Lamatic/AgentKit

Length of output: 316


This PostCSS config must be updated to Tailwind v4 specification.

The config currently wires tailwindcss and autoprefixer as separate plugins (v3 style), but @tailwindcss/postcss v4.0.0 is already installed as a dependency. The mismatch means Tailwind v4 is not properly loaded. Tailwind v4 consolidates styling into a single @tailwindcss/postcss plugin that includes autoprefixing—no separate autoprefixer needed.

🎯 Required patch
 const config = {
   plugins: {
-    tailwindcss: {},
-    autoprefixer: {},
+    "@tailwindcss/postcss": {},
   },
 };
 export default config;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/postcss.config.mjs` around lines 2 - 4, Update the PostCSS
plugins object to use the consolidated Tailwind v4 plugin: replace the existing
entries "tailwindcss" and "autoprefixer" in the plugins map with a single
"@tailwindcss/postcss": {} entry (i.e., remove the tailwindcss and autoprefixer
keys and add "@tailwindcss/postcss": {}), ensuring the plugins object only
references the new consolidated plugin so Tailwind v4 is properly loaded.

Comment thread kits/fablens/README.md
Comment on lines +46 to +52
| Variable | Description |
|----------|-------------|
| `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |
| `LAMATIC_PROJECT_ID` | Your Lamatic project ID |
| `LAMATIC_WORKFLOW_ID` | Workflow ID used for material extraction |
| `LAMATIC_HOST` | Your Lamatic GraphQL endpoint (e.g. https://<org>.lamatic.dev/graphql) |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mission docs sync: add the scoring workflow env var to setup table.

LAMATIC_SCORING_WORKFLOW_ID exists in .env.example but is missing here, so operators can under-configure deployments.

📝 Proposed patch
 | `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai |
 | `LAMATIC_PROJECT_ID` | Your Lamatic project ID |
 | `LAMATIC_WORKFLOW_ID` | Workflow ID used for material extraction |
+| `LAMATIC_SCORING_WORKFLOW_ID` | Workflow ID used for unknown-material scoring fallback |
 | `LAMATIC_HOST` | Your Lamatic GraphQL endpoint (e.g. https://<org>.lamatic.dev/graphql) |

As per coding guidelines, "Every kit must have a README.md that documents setup, environment variables, and usage".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/README.md` around lines 46 - 52, Add the missing environment
variable LAMATIC_SCORING_WORKFLOW_ID to the README's environment variables table
so operators see it alongside LAMATIC_API_KEY, LAMATIC_PROJECT_ID,
LAMATIC_WORKFLOW_ID, and LAMATIC_HOST; update the table row for
`LAMATIC_SCORING_WORKFLOW_ID` with a short description like "Scoring workflow ID
used for model scoring/validation" to match `.env.example` and ensure README
setup docs list all vars referenced by the kit.

Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
kits/fablens/apps/.gitignore (1)

1-2: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Stop potential secret leaks: ignore .env and .env.local in this app .gitignore.

Right now this .gitignore only ignores .vercel, but the repo guideline requires excluding .env and .env.local to prevent accidental secret commits. Add them here too (Next.js apps often keep env files per-app).

🎯 Proposed fix
-.vercel
+.env
+.env.local
+.vercel
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kits/fablens/apps/.gitignore` around lines 1 - 2, Update the app's .gitignore
to also ignore environment files by adding the entries ".env" and ".env.local"
alongside the existing ".vercel" entry so per-app secrets can't be accidentally
committed; locate the .gitignore in the app folder and append those two lines to
the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@kits/fablens/apps/.gitignore`:
- Around line 1-2: Update the app's .gitignore to also ignore environment files
by adding the entries ".env" and ".env.local" alongside the existing ".vercel"
entry so per-app secrets can't be accidentally committed; locate the .gitignore
in the app folder and append those two lines to the file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: feec2e98-e733-46dd-a1c9-52be678f138d

📥 Commits

Reviewing files that changed from the base of the PR and between 4deaa1c and 0d2f8b0.

📒 Files selected for processing (2)
  • kits/fablens/apps/.gitignore
  • kits/fablens/lamatic.config.ts

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

Hi @yashasvij-19! 👋

Before this PR can be reviewed by maintainers, please resolve all comments and requested changes from the CodeRabbit automated review.

Steps to follow:

  1. Read through all CodeRabbit comments carefully
  2. Address each issue raised (or reply explaining why you disagree)
  3. Push your fixes as new commits
  4. Once all issues are resolved, comment here so we can re-review

This helps keep the review process efficient for everyone. Thank you! 🙏

Copy link
Copy Markdown
Contributor

@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: 4

♻️ Duplicate comments (1)
kits/fablens/apps/app/page.tsx (1)

40-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Dossier still flagged: client abort fires before the server can complete two Lamatic calls.

The 10 s AbortController timeout fires before the server's primary call can even respond (12 s) — let alone both calls back-to-back (worst case ~24 s). Users analyzing blends with unknown materials will reliably see "Request timed out" for valid requests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/fablens/apps/app/page.tsx` around lines 40 - 41, The 10s AbortController
timeout (controller and timeout) is too short and aborts valid requests;
increase the timeout to at least 30000ms (or make it configurable) and ensure
you call clearTimeout(timeout) once the Lamatic calls complete successfully;
alternatively, move AbortController scope so it only starts after both Lamatic
requests begin or remove the hard timeout and rely on per-request cancellation
logic so the controller.abort() won't fire before both calls finish.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kits/fablens/apps/app/api/analyze/route.ts`:
- Around line 223-229: parsedAI fields ecoReasons, skinReasons, and negatives
are being spread without type checks so non-array values (e.g., strings) will be
spread into characters; update the block that handles parsedAI (the parsedAI
variable and the arrays ecoReasons/skinReasons/negatives) to validate each field
before spreading: use Array.isArray(...) to accept arrays, if it's a string wrap
it into [value], otherwise fall back to []; apply the same normalization for
parsedAI.ecoReasons, parsedAI.skinReasons, and parsedAI.negatives before doing
ecoReasons.push(...), skinReasons.push(...), negatives.push(...).
- Around line 3-9: normalizeMaterial can return empty strings (e.g., "50%" ->
"") which then pass through splitCompound, Set, and the known/unknown
partitioning and produce blank list items and malformed AI prompts; update the
pipeline to drop empty normalized values — either filter out "" right after
calling normalizeMaterial (where splitCompound is used) or add a
post-normalization filter before creating the Set/partition step (affecting the
code paths that use normalizeMaterial, splitCompound, and the known/unknown
partition logic) so that any falsy/empty string is removed before deduplication
and before building the UI list or AI prompt.
- Around line 212-214: The prompt injects untrusted values from the unknown
array directly into callLamatic; sanitize unknown before forming the prompt by
filtering out entries that are too long (e.g., >50 chars) or contain
non-alphabetic characters (allow spaces and basic punctuation like hyphen), and
reject or trim any suspicious items, then escape/normalize remaining names
(e.g., lowercase/trim) and join them for the callLamatic invocation; update the
code around the unknown variable usage and the callLamatic(...) call to perform
this validation/normalization (referencing unknown and callLamatic) so only
vetted material names are re-injected.

In `@kits/fablens/apps/app/page.tsx`:
- Around line 129-134: The three toggle buttons controlling collapsible sections
(using state variables showEco, showSkin, showNeg and setters like setShowEco)
need ARIA state attributes so screen readers know their open/closed state: add
aria-expanded={showEco} to the eco button (and aria-expanded={showSkin} and
aria-expanded={showNeg} to the skin and negatives buttons), and link each button
to its panel with aria-controls pointing to a unique id on the corresponding
collapsible container (e.g., eco-panel, skin-panel, neg-panel) to ensure proper
accessible expand/collapse semantics.

---

Duplicate comments:
In `@kits/fablens/apps/app/page.tsx`:
- Around line 40-41: The 10s AbortController timeout (controller and timeout) is
too short and aborts valid requests; increase the timeout to at least 30000ms
(or make it configurable) and ensure you call clearTimeout(timeout) once the
Lamatic calls complete successfully; alternatively, move AbortController scope
so it only starts after both Lamatic requests begin or remove the hard timeout
and rely on per-request cancellation logic so the controller.abort() won't fire
before both calls finish.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 62a5fd5c-dd9d-4283-92f9-8fa8ea98f1f0

📥 Commits

Reviewing files that changed from the base of the PR and between 0d2f8b0 and 88c9adc.

📒 Files selected for processing (3)
  • kits/fablens/apps/app/api/analyze/route.ts
  • kits/fablens/apps/app/page.tsx
  • kits/fablens/apps/lib/materialDB.ts

Comment on lines +3 to +9
function normalizeMaterial(raw: string): string {
return raw
.toLowerCase()
.replace(/\d+%\s*/g, "")
.replace(/recycled\s*/g, "")
.trim();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Agent to field team: filter empty strings after normalization or risk phantom materials reaching the client and the AI fallback.

normalizeMaterial can produce "" for inputs like "50%" or "recycled". That empty string survives splitCompound, new Set, and both known/unknown partitions, ultimately rendering as a blank <li> in the UI and polluting the AI fallback prompt with a leading comma (e.g., "Analyze these materials: , cotton. Return JSON only.").

🛡️ Proposed fix
 const displayMaterials = [
   ...new Set(
     rawMaterials
       .map(normalizeMaterial)
       .flatMap(splitCompound)
+      .filter(Boolean)
   ),
 ];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 3 - 9,
normalizeMaterial can return empty strings (e.g., "50%" -> "") which then pass
through splitCompound, Set, and the known/unknown partitioning and produce blank
list items and malformed AI prompts; update the pipeline to drop empty
normalized values — either filter out "" right after calling normalizeMaterial
(where splitCompound is used) or add a post-normalization filter before creating
the Set/partition step (affecting the code paths that use normalizeMaterial,
splitCompound, and the known/unknown partition logic) so that any falsy/empty
string is removed before deduplication and before building the UI list or AI
prompt.

Comment on lines +212 to +214
const aiRes = await callLamatic(
`Analyze these materials: ${unknown.join(", ")}. Return JSON only.`
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Your mission, should you choose to accept it: sanitize AI-extracted material names before re-injecting them into the next AI call.

unknown.join(", ") is inserted verbatim into the second Lamatic prompt. The unknown array originates from the first AI call's output — a malicious product page could craft material names to manipulate the second workflow's behavior (prompt injection). At minimum, strip or reject any entry that is suspiciously long or contains non-alphabetic characters before forming the fallback prompt.

🛡️ Proposed fix
+  const safeUnknown = unknown.filter(
+    (m) => m.length <= 50 && /^[a-z\s-]+$/.test(m)
+  );
+  if (safeUnknown.length === 0) {
+    // nothing safe to send; skip fallback
+  } else {
   const aiRes = await callLamatic(
-    `Analyze these materials: ${unknown.join(", ")}. Return JSON only.`
+    `Analyze these materials: ${safeUnknown.join(", ")}. Return JSON only.`
   );
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 212 - 214, The
prompt injects untrusted values from the unknown array directly into
callLamatic; sanitize unknown before forming the prompt by filtering out entries
that are too long (e.g., >50 chars) or contain non-alphabetic characters (allow
spaces and basic punctuation like hyphen), and reject or trim any suspicious
items, then escape/normalize remaining names (e.g., lowercase/trim) and join
them for the callLamatic invocation; update the code around the unknown variable
usage and the callLamatic(...) call to perform this validation/normalization
(referencing unknown and callLamatic) so only vetted material names are
re-injected.

Comment on lines +223 to +229
if (parsedAI) {
ecoScore += parsedAI.ecoScore || 0;
skinScore += parsedAI.skinScore || 0;
ecoReasons.push(...(parsedAI.ecoReasons || []));
skinReasons.push(...(parsedAI.skinReasons || []));
negatives.push(...(parsedAI.negatives || []));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Critical field intel: validate AI fallback fields as arrays before spreading — non-array values will explode into character noise.

safeJSONParse returns any, so parsedAI.ecoReasons, skinReasons, and negatives are untyped. If the Lamatic workflow returns these as strings (e.g., "biodegradable" instead of ["biodegradable"]), ...(parsedAI.ecoReasons || []) spreads individual characters into the reasons arrays. The || [] fallback only guards undefined/null, not non-array values.

🛡️ Proposed fix
-          ecoScore += parsedAI.ecoScore || 0;
-          skinScore += parsedAI.skinScore || 0;
-          ecoReasons.push(...(parsedAI.ecoReasons || []));
-          skinReasons.push(...(parsedAI.skinReasons || []));
-          negatives.push(...(parsedAI.negatives || []));
+          const aiEco = typeof parsedAI.ecoScore === 'number' ? parsedAI.ecoScore : 0;
+          const aiSkin = typeof parsedAI.skinScore === 'number' ? parsedAI.skinScore : 0;
+          ecoScore += aiEco;
+          skinScore += aiSkin;
+          if (Array.isArray(parsedAI.ecoReasons))
+            ecoReasons.push(...parsedAI.ecoReasons.filter((r: unknown): r is string => typeof r === 'string'));
+          if (Array.isArray(parsedAI.skinReasons))
+            skinReasons.push(...parsedAI.skinReasons.filter((r: unknown): r is string => typeof r === 'string'));
+          if (Array.isArray(parsedAI.negatives))
+            negatives.push(...parsedAI.negatives.filter((n: unknown): n is string => typeof n === 'string'));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (parsedAI) {
ecoScore += parsedAI.ecoScore || 0;
skinScore += parsedAI.skinScore || 0;
ecoReasons.push(...(parsedAI.ecoReasons || []));
skinReasons.push(...(parsedAI.skinReasons || []));
negatives.push(...(parsedAI.negatives || []));
}
if (parsedAI) {
const aiEco = typeof parsedAI.ecoScore === 'number' ? parsedAI.ecoScore : 0;
const aiSkin = typeof parsedAI.skinScore === 'number' ? parsedAI.skinScore : 0;
ecoScore += aiEco;
skinScore += aiSkin;
if (Array.isArray(parsedAI.ecoReasons))
ecoReasons.push(...parsedAI.ecoReasons.filter((r: unknown): r is string => typeof r === 'string'));
if (Array.isArray(parsedAI.skinReasons))
skinReasons.push(...parsedAI.skinReasons.filter((r: unknown): r is string => typeof r === 'string'));
if (Array.isArray(parsedAI.negatives))
negatives.push(...parsedAI.negatives.filter((n: unknown): n is string => typeof n === 'string'));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/fablens/apps/app/api/analyze/route.ts` around lines 223 - 229, parsedAI
fields ecoReasons, skinReasons, and negatives are being spread without type
checks so non-array values (e.g., strings) will be spread into characters;
update the block that handles parsedAI (the parsedAI variable and the arrays
ecoReasons/skinReasons/negatives) to validate each field before spreading: use
Array.isArray(...) to accept arrays, if it's a string wrap it into [value],
otherwise fall back to []; apply the same normalization for parsedAI.ecoReasons,
parsedAI.skinReasons, and parsedAI.negatives before doing ecoReasons.push(...),
skinReasons.push(...), negatives.push(...).

Comment on lines +129 to +134
<button
onClick={() => setShowEco(!showEco)}
className="text-blue-600 text-sm mt-1 hover:underline"
>
{showEco ? 'Hide details' : 'Learn more'}
</button>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Accessibility gap: expand/collapse buttons are missing aria-expanded.

All three toggle buttons (showEco, showSkin, showNeg) control collapsible sections but carry no aria-expanded state. Screen readers announce them as plain buttons with no indication of the open/closed state, breaking keyboard-driven task completion for the reasons panels.

🛡️ Proposed fix (example for eco section; apply the same pattern to skin and negatives)
-                <button
-                  onClick={() => setShowEco(!showEco)}
-                  className="text-blue-600 text-sm mt-1 hover:underline"
-                >
+                <button
+                  onClick={() => setShowEco(!showEco)}
+                  aria-expanded={showEco}
+                  className="text-blue-600 text-sm mt-1 hover:underline"
+                >

Also applies to: 156-161, 177-182

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kits/fablens/apps/app/page.tsx` around lines 129 - 134, The three toggle
buttons controlling collapsible sections (using state variables showEco,
showSkin, showNeg and setters like setShowEco) need ARIA state attributes so
screen readers know their open/closed state: add aria-expanded={showEco} to the
eco button (and aria-expanded={showSkin} and aria-expanded={showNeg} to the skin
and negatives buttons), and link each button to its panel with aria-controls
pointing to a unique id on the corresponding collapsible container (e.g.,
eco-panel, skin-panel, neg-panel) to ensure proper accessible expand/collapse
semantics.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants