-
Notifications
You must be signed in to change notification settings - Fork 128
feat: Add FabLens - Eco-Friendly & Skin-Safe Fabric Checker #151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
c27a751
864cd78
c4de60f
6720bfa
66519eb
cf89be1
ec7839e
296b220
5c0abd4
451e6b8
ab25e60
d321d06
ac675a0
0da5041
4deaa1c
0d2f8b0
88c9adc
00eef4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| .lamatic/ | ||
| node_modules/ | ||
| .env | ||
| .env.local |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # FabLens — Eco-Friendly & Skin-Safe Fabric Checker | ||
|
|
||
| FabLens lets consumers paste any clothing product URL and instantly understand what materials it's made of — and what that means for their skin and the planet. | ||
|
|
||
| No scores. No guilt. Just facts. | ||
|
|
||
| ## What It Does | ||
|
|
||
| - Scrapes the product page for listed materials | ||
| - Analyzes each material for environmental impact (biodegradable, water usage, chemical processing) | ||
| - Analyzes each material for skin safety (breathability, irritation risk) | ||
| - Shows positives and negatives transparently | ||
| - Uses a local material database for known fabrics, with AI fallback for unknown ones | ||
|
|
||
| ## Tech Stack | ||
|
|
||
| - **Lamatic AI** — flow orchestration + scraping + LLM analysis | ||
| - **Firecrawl** — webpage scraping | ||
| - **Next.js** — frontend | ||
| - **Tailwind CSS** — styling | ||
| - **Groq (llama-4-scout)** — AI model | ||
|
|
||
| ## Setup | ||
|
|
||
| ```bash | ||
| cd kits/fablens/apps | ||
| cp .env.example .env.local | ||
| # Add your LAMATIC_API_KEY | ||
| npm install | ||
| npm run dev | ||
| ``` | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | | ||
| |----------|-------------| | ||
| | `LAMATIC_API_KEY` | Your Lamatic API key from studio.lamatic.ai | | ||
|
|
||
|
Comment on lines
+46
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mission docs sync: add the scoring workflow env var to setup table.
📝 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 🤖 Prompt for AI Agents |
||
| ## Supported Sites | ||
| Works best with product pages listing materials in plain text (BIBA, Patagonia, independent brands). Sites with scraper protection (H&M, Amazon) may return no results — known v1 limitation. | ||
|
|
||
| ## Future Plans | ||
| - Furniture and cosmetics support | ||
| - Image-based material detection | ||
| - Percentage-weighted scoring | ||
| - Expanded material database | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,60 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # FabLens | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## Overview | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+60
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mission cleanup: remove unresolved 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 📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.1)[warning] 5-5: Reference links and images should use a label that is defined (MD052, reference-links-images) [warning] 9-9: Reference links and images should use a label that is defined (MD052, reference-links-images) [warning] 33-33: Reference links and images should use a label that is defined (MD052, reference-links-images) [warning] 56-56: Reference links and images should use a label that is defined (MD052, reference-links-images) [warning] 56-56: Reference links and images should use a label that is defined (MD052, reference-links-images) [warning] 60-60: Files should end with a single newline character (MD047, single-trailing-newline) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| LAMATIC_API_KEY=your_lamatic_api_key_here |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,223 @@ | ||
| import { materialDB } from "../../../lib/materialDB"; | ||
|
|
||
| function normalizeMaterial(raw: string): string { | ||
| return raw | ||
| .toLowerCase() | ||
| .replace(/\d+%\s*/g, "") | ||
| .replace(/recycled\s*/g, "") | ||
| .trim(); | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| function safeJSONParse(raw: any) { | ||
| try { | ||
| if (typeof raw === "object") return raw; | ||
| return JSON.parse(raw.replace(/```json|```/g, "").trim()); | ||
| } catch { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| function splitCompound(mat: string): string[] { | ||
| const compounds: Record<string, string[]> = { | ||
| "viscose rayon": ["viscose", "rayon"], | ||
| "rayon viscose": ["viscose", "rayon"], | ||
| }; | ||
| return compounds[mat] || [mat]; | ||
| } | ||
|
|
||
| export async function POST(req: Request) { | ||
| try { | ||
| if (!process.env.LAMATIC_API_KEY) { | ||
| return Response.json( | ||
| { materials: [], note: "Missing API key." }, | ||
| { status: 500 } | ||
| ); | ||
| } | ||
|
|
||
| const { url } = await req.json(); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| // -------- PRIMARY AI CALL -------- | ||
| const response = await fetch( | ||
| "https://yashasvisorganization952-yashasvisproject443.lamatic.dev/graphql", | ||
| { | ||
| method: "POST", | ||
| headers: { | ||
| Authorization: `Bearer ${process.env.LAMATIC_API_KEY}`, | ||
| "Content-Type": "application/json", | ||
| "x-project-id": "f16d4f23-0c7a-42df-b553-b41b1f166670", | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| }, | ||
| body: JSON.stringify({ | ||
| query: `query ExecuteWorkflow($workflowId: String!, $question: String, $url: String) { | ||
| executeWorkflow(workflowId: $workflowId payload: { question: $question url: $url }) { | ||
| status result | ||
| } | ||
| }`, | ||
| variables: { | ||
| workflowId: "55a58aab-872b-463f-94b1-e0fbfc1c2056", | ||
| question: "extract materials", | ||
| url, | ||
| }, | ||
| }), | ||
| } | ||
| ); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| if (!response.ok) { | ||
| throw new Error("Primary API request failed"); | ||
| } | ||
|
|
||
| const data = await response.json(); | ||
| const workflowResult = data?.data?.executeWorkflow?.result; | ||
|
|
||
| let raw = | ||
| workflowResult?.answer ?? | ||
| workflowResult?.output ?? | ||
| workflowResult; | ||
|
|
||
| if (!raw) { | ||
| return Response.json({ | ||
| materials: [], | ||
| note: "No response from AI", | ||
| }); | ||
| } | ||
|
|
||
| const parsed = safeJSONParse(raw); | ||
|
|
||
| if (!parsed) { | ||
| return Response.json({ | ||
| materials: [], | ||
| note: "Failed to parse AI response", | ||
| }); | ||
| } | ||
|
|
||
| const rawMaterials: string[] = | ||
| parsed.materials || | ||
| parsed.fabric || | ||
| parsed.textiles || | ||
| []; | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| if (rawMaterials.length === 0) { | ||
| return Response.json({ | ||
| materials: [], | ||
| note: | ||
| parsed.note || | ||
| "This manufacturer has not disclosed materials.", | ||
| }); | ||
| } | ||
|
|
||
| // -------- NORMALIZATION -------- | ||
| const normalized = rawMaterials.map(normalizeMaterial); | ||
| const displayMaterials = [ | ||
| ...new Set(normalized.flatMap(splitCompound)), | ||
| ]; | ||
|
|
||
| const known = displayMaterials.filter((m) => materialDB[m]); | ||
| const unknown = displayMaterials.filter((m) => !materialDB[m]); | ||
|
|
||
| let ecoScore = 0; | ||
| let skinScore = 0; | ||
| let ecoReasons: string[] = []; | ||
| let skinReasons: string[] = []; | ||
| let negatives: string[] = []; | ||
|
|
||
| // -------- KNOWN MATERIAL SCORING -------- | ||
| known.forEach((mat) => { | ||
| const m = materialDB[mat]; | ||
| if (!m) return; | ||
|
|
||
| if (m.biodegradable) { | ||
| ecoScore += 30; | ||
| ecoReasons.push(`${mat} is biodegradable`); | ||
| } else { | ||
| negatives.push(`${mat} is not biodegradable`); | ||
| } | ||
|
|
||
| if (m.waterUsage === "low") ecoScore += 10; | ||
| else if (m.waterUsage === "high") | ||
| negatives.push(`${mat} uses high water`); | ||
|
|
||
| if (m.chemicalUse === "low") ecoScore += 10; | ||
| else if (m.chemicalUse === "high") | ||
| negatives.push(`${mat} uses heavy chemicals`); | ||
|
|
||
| if (m.breathability === "high") { | ||
| skinScore += 30; | ||
| skinReasons.push(`${mat} is breathable`); | ||
| } | ||
|
|
||
| if (m.irritationRisk === "low") { | ||
| skinScore += 30; | ||
| skinReasons.push(`${mat} is skin-safe`); | ||
| } else if (m.irritationRisk === "high") { | ||
| negatives.push(`${mat} may irritate skin`); | ||
| } | ||
| }); | ||
|
|
||
| // -------- AI FALLBACK FOR UNKNOWN -------- | ||
| if (unknown.length > 0) { | ||
| try { | ||
| const aiRes = await fetch( | ||
| "https://yashasvisorganization952-yashasvisproject443.lamatic.dev/graphql", | ||
| { | ||
| method: "POST", | ||
| headers: { | ||
| Authorization: `Bearer ${process.env.LAMATIC_API_KEY}`, | ||
| "Content-Type": "application/json", | ||
| "x-project-id": "f16d4f23-0c7a-42df-b553-b41b1f166670", | ||
| }, | ||
| body: JSON.stringify({ | ||
| query: `query ExecuteWorkflow($workflowId: String!, $question: String) { | ||
| executeWorkflow(workflowId: $workflowId payload: { question: $question }) { | ||
| status result | ||
| } | ||
| }`, | ||
| variables: { | ||
| workflowId: | ||
| "55a58aab-872b-463f-94b1-e0fbfc1c2056", | ||
| question: `Analyze these materials: ${unknown.join( | ||
| ", " | ||
| )}. Return JSON only.`, | ||
| }, | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| }), | ||
| } | ||
| ); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| if (aiRes.ok) { | ||
| const aiData = await aiRes.json(); | ||
| let aiRaw = | ||
| aiData?.data?.executeWorkflow?.result?.answer; | ||
|
|
||
| const parsedAI = safeJSONParse(aiRaw); | ||
|
|
||
| if (parsedAI) { | ||
| ecoScore += parsedAI.ecoScore || 0; | ||
| skinScore += parsedAI.skinScore || 0; | ||
| ecoReasons.push(...(parsedAI.ecoReasons || [])); | ||
| skinReasons.push(...(parsedAI.skinReasons || [])); | ||
| negatives.push(...(parsedAI.negatives || [])); | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
| } catch (err) { | ||
| console.error("AI fallback failed:", err); | ||
| } | ||
| } | ||
|
|
||
| // -------- FINAL NORMALIZATION -------- | ||
| ecoScore = Math.min(100, ecoScore); | ||
| skinScore = Math.min(100, skinScore); | ||
|
|
||
| return Response.json({ | ||
| materials: displayMaterials, | ||
| ecoScore, | ||
| skinScore, | ||
| ecoReasons, | ||
| skinReasons, | ||
| negatives, | ||
| }); | ||
| } catch (err) { | ||
| console.error("API ERROR:", err); | ||
| return Response.json( | ||
| { materials: [], note: "Internal server error" }, | ||
| { status: 500 } | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| @import "tailwindcss"; | ||
|
|
||
| :root { | ||
| --background: #ffffff; | ||
| --foreground: #171717; | ||
| } | ||
|
|
||
| @theme inline { | ||
| --color-background: var(--background); | ||
| --color-foreground: var(--foreground); | ||
| --font-sans: var(--font-geist-sans); | ||
| --font-mono: var(--font-geist-mono); | ||
| } | ||
|
|
||
| @media (prefers-color-scheme: dark) { | ||
| :root { | ||
| --background: #0a0a0a; | ||
| --foreground: #ededed; | ||
| } | ||
| } | ||
|
|
||
| body { | ||
| background: var(--background); | ||
| color: var(--foreground); | ||
| font-family: Arial, Helvetica, sans-serif; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mission-critical docs gap: add
FABLENS_WORKFLOW_IDto 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 |📝 Committable suggestion
🤖 Prompt for AI Agents