PageSourceSearch

https://innovationlab.fetch.ai/resources/assets/js/b92e97f0.eb22efb6.js

js fetch.ai collected 2026-09-24 09:39:38 UTC 23,041 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkinnovation_labs=self.webpackChunkinnovation_labs||[]).push([[1893],{57132:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"examples/integrations/frontend-integration","title":"Frontend Web App Integration","description":"This guide demonstrates how to create a complete web application that integrates uAgents with external APIs using a Flask frontend. We\'ll build a food product discovery system using the Open Food Facts API.","source":"@site/versioned_docs/version-1.0.4/examples/integrations/frontend-integration.md","sourceDirName":"examples/integrations","slug":"/examples/integrations/frontend-integration","permalink":"/resources/docs/1.0.4/examples/integrations/frontend-integration","draft":false,"unlisted":false,"tags":[],"version":"1.0.4","frontMatter":{"id":"frontend-integration","title":"Frontend Web App Integration"},"sidebar":"tutorialSidebar","previous":{"title":"Stripe Payment Agent","permalink":"/resources/docs/1.0.4/examples/integrations/stripe-integration"},"next":{"title":"LangGraph Agent with MCP adapter","permalink":"/resources/docs/1.0.4/examples/mcp-integration/langgraph-mcp-agent-example"}}');var s=t(74848),i=t(28453);const a={id:"frontend-integration",title:"Frontend Web App Integration"},o="Build a Frontend Web Application with uAgents and Open Food Facts API",c={},l=[{value:"Overview",id:"overview",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"1. Clone the Complete Example",id:"1-clone-the-complete-example",level:3},{value:"2. Set Up Virtual Environment",id:"2-set-up-virtual-environment",level:3},{value:"3. Install Dependencies",id:"3-install-dependencies",level:3},{value:"Architecture Overview",id:"architecture-overview",level:2},{value:"Two Specialized uAgents",id:"two-specialized-uagents",level:3},{value:"Frontend Application",id:"frontend-application",level:3},{value:"Quick Start",id:"quick-start",level:2},{value:"1. Start Search Agent",id:"1-start-search-agent",level:3},{value:"2. Start Info Agent",id:"2-start-info-agent",level:3},{value:"3. Start Frontend",id:"3-start-frontend",level:3},{value:"4. Access the Web Interface",id:"4-access-the-web-interface",level:3},{value:"Agent Implementation Details",id:"agent-implementation-details",level:2},{value:"Search Agent (Port 8001)",id:"search-agent-port-8001",level:3},{value:"Info Agent (Port 8002)",id:"info-agent-port-8002",level:3},{value:"Frontend Implementation",id:"frontend-implementation",level:2},{value:"Flask Backend",id:"flask-backend",level:3},{value:"Testing the Application",id:"testing-the-application",level:2},{value:"1. Product Search Testing",id:"1-product-search-testing",level:3},{value:"2. Product Details Testing",id:"2-product-details-testing",level:3},{value:"3. Health Status Monitoring",id:"3-health-status-monitoring",level:3},{value:"Key Features Demonstrated",id:"key-features-demonstrated",level:2},{value:"1. Microservice Architecture",id:"1-microservice-architecture",level:3},{value:"2. REST API Design",id:"2-rest-api-design",level:3},{value:"3. Frontend Integration",id:"3-frontend-integration",level:3},{value:"4. External API Integration",id:"4-external-api-integration",level:3},{value:"GitHub Repository",id:"github-repository",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"build-a-frontend-web-application-with-uagents-and-open-food-facts-api",children:"Build a Frontend Web Application with uAgents and Open Food Facts API"})}),"\n",(0,s.jsx)(n.p,{children:"This guide demonstrates how to create a complete web application that integrates uAgents with external APIs using a Flask frontend. We'll build a food product discovery system using the Open Food Facts API."}),"\n",(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(n.p,{children:"The Frontend Integration example provides:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Two Specialized uAgents"})," - Search Agent and Info Agent"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"REST API Endpoints"})," using uAgents framework"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Exter
1nal API Integration"})," with Open Food Facts"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Modern Web Interface"})," built with Flask and HTML/CSS/JavaScript"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Real-time Health Monitoring"})," of all services"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsx)(n.p,{children:"Before you begin, ensure you have:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Python 3.11+"})," installed"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Basic knowledge"})," of Flask and web development"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Understanding"})," of REST APIs and HTTP requests"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,s.jsx)(n.h3,{id:"1-clone-the-complete-example",children:"1. Clone the Complete Example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone https://github.com/fetchai/innovation-lab-examples.git\ncd innovation-lab-examples/frontend-integration\n"})}),"\n",(0,s.jsx)(n.h3,{id:"2-set-up-virtual-environment",children:"2. Set Up Virtual Environment"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# Create virtual environment\npython3 -m venv venv\n\n# Activate virtual environment\n# On macOS/Linux:\nsource venv/bin/activate\n# On Windows:\n# venv\\Scripts\\activate\n"})}),"\n",(0,s.jsx)(n.h3,{id:"3-install-dependencies",children:"3. Install Dependencies"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"pip install -r requirements.txt\n"})}),"\n",(0,s.jsx)(n.h2,{id:"architecture-overview",children:"Architecture Overview"}),"\n",(0,s.jsx)(n.h3,{id:"two-specialized-uagents",children:"Two Specialized uAgents"}),"\n",(0,s.jsx)(n.p,{children:"Our system consists of two specialized microservices:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Search Agent"})," (Port 8001): Handles product search queries"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Info Agent"})," (Port 8002): Retrieves detailed product information"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"frontend-application",children:"Frontend Application"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Flask Web App"})," (Port 5000): Modern web interface to interact with agents"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"quick-start",children:"Quick Start"}),"\n",(0,s.jsx)(n.h3,{id:"1-start-search-agent",children:"1. Start Search Agent"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Terminal 1:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"source venv/bin/activate  # Activate venv if not already active\npython3 product_search_agent.py\n"})}),"\n",(0,s.jsx)(n.h3,{id:"2-start-info-agent",children:"2. Start Info Agent"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Terminal 2:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"source venv/bin/activate  # Activate venv if not already active\npython3 product_info_agent.py\n"})}),"\n",(0,s.jsx)(n.h3,{id:"3-start-frontend",children:"3. Start Frontend"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Terminal 3:"})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"source venv/bin/activate  # Activate venv if not already active\npython3 frontend_app.py\n"})}),"\n",(0,s.jsx)(n.h3,{id:"4-access-the-web-interface",children:"4. Access the Web Interface"}),"\n",(0,s.jsxs)(n.p,{children:["Open your browser to: ",(0,s.jsx)(n.a,{href:"http://127.0.0.1:5000",children:"http://127.0.0.1:5000"})]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Frontend Browser",src:t(77925).A+"",width:"3455",height:"2070"})}),"\n",(0,s.jsx)(n.h2,{id:"agent-implementation-details",children:"Agent Implementation Details"}),"\n",(0,s.jsx)(n.h3,{id:"search-agent-port-8001",children:"Search Agent (Port 8001)"}),"\n",(0,s.jsx)(n.p,{children:"The search agent handles product discovery using natural language queries:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'from uagents import Agent, Context, Model\nimport openfoodfacts\n\nclass SearchRequest(Model):\n    query: str\n\nclass ProductInfo(Model):\n    code: str\n    product_name: str\n    brands: str\n    categories: str\n    image_url: str\n\nclass SearchResponse(Mo
1del):\n    query: str\n    count: int\n    products: List[ProductInfo]\n    error: Optional[str] = None\n\nsearch_agent = Agent(\n    name="product_search_agent",\n    port=8001,\n    endpoint=["http://127.0.0.1:8001/submit"],\n)\n\n@search_agent.on_rest_post("/search", SearchRequest, SearchResponse)\nasync def search_products(ctx: Context, req: SearchRequest) -> SearchResponse:\n    try:\n        query = req.query\n        ctx.logger.info(f"Searching for products with query: {query}")\n        \n        # Search products using Open Food Facts API\n        results = api.product.text_search(query, page_size=10)\n        \n        # Extract relevant information\n        products = []\n        for product in results.get("products", [])[:10]:\n            product_info = ProductInfo(\n                code=product.get("code", "N/A"),\n                product_name=product.get("product_name", "N/A"),\n                brands=product.get("brands", "N/A"),\n                categories=product.get("categories", "N/A"),\n                image_url=product.get("image_url", "")\n            )\n            products.append(product_info)\n        \n        return SearchResponse(\n            query=query,\n            count=results.get("count", 0),\n            products=products\n        )\n    except Exception as e:\n        return SearchResponse(\n            query=req.query,\n            count=0,\n            products=[],\n            error=f"Failed to search products: {str(e)}"\n        )\n'})}),"\n",(0,s.jsx)(n.h3,{id:"info-agent-port-8002",children:"Info Agent (Port 8002)"}),"\n",(0,s.jsx)(n.p,{children:"The info agent provides detailed product information using exact barcodes:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'from uagents import Agent, Context, Model\nimport requests\n\nclass ProductRequest(Model):\n    barcode: str\n\nclass ProductInfoResponse(Model):\n    barcode: str\n    product_name: str\n    brands: str\n    categories: str\n    ingredients_text: str\n    allergens: str\n    nutrition_grades: str\n    ecoscore_grade: str\n    image_url: str\n    countries: str\n    stores: str\n    packaging: str\n    quantity: str\n    energy_100g: str\n    fat_100g: str\n    sugars_100g: str\n    salt_100g: str\n    error: Optional[str] = None\n\ninfo_agent = Agent(\n    name="product_info_agent",\n    port=8002,\n    endpoint=["http://127.0.0.1:8002/submit"],\n)\n\n@info_agent.on_rest_post("/product", ProductRequest, ProductInfoResponse)\nasync def get_product_info(ctx: Context, req: ProductRequest) -> ProductInfoResponse:\n    try:\n        barcode = req.barcode\n        ctx.logger.info(f"Getting product info for barcode: {barcode}")\n        \n        # Use direct API call to Open Food Facts\n        url = f"https://world.openfoodfacts.org/api/v0/product/{barcode}.json"\n        headers = {\n            \'User-Agent\': \'uAgents-FoodInfo/1.0 (https://github.com/fetchai/uAgents)\'\n        }\n        \n        response = requests.get(url, headers=headers, timeout=10)\n        data = response.json()\n        \n        if data.get(\'status\') != 1 or "product" not in data:\n            return ProductInfoResponse(\n                barcode=barcode,\n                # ... other fields with "N/A"\n                error="Product not found"\n            )\n        \n        product = data["product"]\n        \n        # Extract comprehensive product information\n        return ProductInfoResponse(\n            barcode=barcode,\n            product_name=product.get("product_name", "N/A"),\n            brands=product.get("brands", "N/A"),\n            categories=product.get("categories", "N/A"),\n            ingredients_text=product.get("ingredients_text", "N/A"),\n            allergens=product.get("allergens", "N/A"),\n            nutrition_grades=product.get("nutrition_grades", "N/A"),\n            ecoscore_grade=product.get("ecoscore_grade", "N/A"),\n            image_url=product.get("image_url", ""),\n            countries=product.get("countries", "N/A"),\n            stores=product.get("stores", "N/A"),\n            packaging=product.get("packaging", "N
1/A"),\n            quantity=product.get("quantity", "N/A"),\n            energy_100g=str(product.get("nutriments", {}).get("energy_100g", "N/A")),\n            fat_100g=str(product.get("nutriments", {}).get("fat_100g", "N/A")),\n            sugars_100g=str(product.get("nutriments", {}).get("sugars_100g", "N/A")),\n            salt_100g=str(product.get("nutriments", {}).get("salt_100g", "N/A"))\n        )\n    except Exception as e:\n        return ProductInfoResponse(\n            barcode=req.barcode,\n            # ... other fields with "N/A"\n            error=f"Failed to get product info: {str(e)}"\n        )\n'})}),"\n",(0,s.jsx)(n.h2,{id:"frontend-implementation",children:"Frontend Implementation"}),"\n",(0,s.jsx)(n.h3,{id:"flask-backend",children:"Flask Backend"}),"\n",(0,s.jsx)(n.p,{children:"The Flask application serves as a bridge between the web interface and uAgents:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'from flask import Flask, render_template, request, jsonify\nimport requests\n\napp = Flask(__name__)\n\n# Agent endpoints\nAGENTS = {\n    "search": "http://127.0.0.1:8001",\n    "info": "http://127.0.0.1:8002"\n}\n\[email protected](\'/search_products\', methods=[\'POST\'])\ndef search_products():\n    """Search products via search agent"""\n    try:\n        query = request.form.get(\'query\', \'\').strip()\n        if not query:\n            return jsonify({"error": "Please provide a search query"})\n        \n        # Call search agent with POST request\n        payload = {"query": query}\n        response = requests.post(f"{AGENTS[\'search\']}/search", json=payload)\n        response.raise_for_status()\n        \n        result = response.json()\n        \n        # Format the results for display\n        formatted_results = []\n        if result.get(\'products\'):\n            for product in result[\'products\'][:10]:\n                formatted_product = {\n                    \'name\': product.get(\'product_name\', \'N/A\'),\n                    \'brands\': product.get(\'brands\', \'N/A\'),\n                    \'barcode\': product.get(\'code\', \'N/A\'),\n                    \'categories\': product.get(\'categories\', \'N/A\'),\n                    \'image_url\': product.get(\'image_url\', \'\')\n                }\n                formatted_results.append(formatted_product)\n        \n        return jsonify({\n            "success": True, \n            "count": result.get(\'count\', 0),\n            "query": query,\n            "products": formatted_results\n        })\n        \n    except requests.RequestException as e:\n        return jsonify({"error": f"Failed to connect to search agent: {str(e)}"})\n    except Exception as e:\n        return jsonify({"error": f"Search failed: {str(e)}"})\n\[email protected](\'/health\')\ndef health_check():\n    """Check health of all agents"""\n    health_status = {}\n    \n    for agent_name, agent_url in AGENTS.items():\n        try:\n            response = requests.get(f"{agent_url}/health", timeout=5)\n            if response.status_code == 200:\n                health_data = response.json()\n                health_status[agent_name] = {\n                    "status": "healthy", \n                    "url": agent_url, \n                    "agent_info": health_data\n                }\n            else:\n                health_status[agent_name] = {"status": "unhealthy", "url": agent_url}\n        except:\n            health_status[agent_name] = {"status": "offline", "url": agent_url}\n    \n    return jsonify(health_status)\n'})}),"\n",(0,s.jsx)(n.h2,{id:"testing-the-application",children:"Testing the Application"}),"\n",(0,s.jsx)(n.h3,{id:"1-product-search-testing",children:"1. Product Search Testing"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:'Search Query: "chocolate"'})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Navigate to ",(0,s.jsx)(n.a,{href:"http://127.0.0.1:5000",children:"http://127.0.0.1:5000"})]}),"\n",(0,s.jsxs)(n.li,{children:['In the "Search Products" section, enter ',(0,s.jsx)(n.code,{children:"chocolate"}
1)," in the search field"]}),"\n",(0,s.jsx)(n.li,{children:'Click "Search Products" to see results'}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Search Results for Chocolate",src:t(89433).A+"",width:"3450",height:"1986"})}),"\n",(0,s.jsx)(n.p,{children:"The search will return multiple chocolate products with product names, brands, categories, barcodes, and images."}),"\n",(0,s.jsx)(n.h3,{id:"2-product-details-testing",children:"2. Product Details Testing"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:'Barcode Query: "3017624010701"'})}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:['In the "Get Product Information" section, enter the barcode ',(0,s.jsx)(n.code,{children:"3017624010701"})]}),"\n",(0,s.jsx)(n.li,{children:'Click "Get Product Info" to retrieve detailed information'}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Product Details for Nutella",src:t(4425).A+"",width:"3456",height:"2082"})}),"\n",(0,s.jsx)(n.p,{children:"This will display comprehensive information for Nutella including basic information, ingredients, nutrition facts, and quality scores."}),"\n",(0,s.jsx)(n.h3,{id:"3-health-status-monitoring",children:"3. Health Status Monitoring"}),"\n",(0,s.jsx)(n.p,{children:'Click the "Check Agent Status" button to verify all services are running:'}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Agent Health Status",src:t(4668).A+"",width:"2332",height:"680"})}),"\n",(0,s.jsx)(n.p,{children:"This displays the real-time status of both Search Agent (Port 8001) and Info Agent (Port 8002)."}),"\n",(0,s.jsx)(n.h2,{id:"key-features-demonstrated",children:"Key Features Demonstrated"}),"\n",(0,s.jsx)(n.h3,{id:"1-microservice-architecture",children:"1. Microservice Architecture"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Separation of Concerns"}),": Each agent has a specific responsibility"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Independent Scaling"}),": Agents can be scaled independently"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Fault Isolation"}),": Failure in one service doesn't affect others"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"2-rest-api-design",children:"2. REST API Design"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Proper HTTP Methods"}),": POST for data operations, GET for health checks"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Pydantic Models"}),": Type-safe request/response validation"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Error Handling"}),": Comprehensive error responses"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"3-frontend-integration",children:"3. Frontend Integration"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Ajax Requests"}),": Asynchronous communication with agents"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Real-time Updates"}),": Dynamic UI updates without page refresh"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Health Monitoring"}),": Live status checking of backend services"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"4-external-api-integration",children:"4. External API Integration"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"HTTP Client Usage"}),": Direct API calls to Open Food Facts"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Data Transformation"}),": Converting external API responses to internal models"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Error Handling"}),": Graceful handling of external API failures"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"github-repository",children:"GitHub Repository"}),"\n",(0,s.jsxs)(n.p,{children:["For the complete code and additional examples, visit the ",(0,s.jsx)(n.a,{href:"https://github.com/fetchai/innovation-lab-examples/tree/main/frontend-integration",children:"Frontend Integration Example"})," repository."]}),"\n",(0,s.jsx)(n.p,{children:"This repository includes:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u2705 Complete agent implementations"}),"\n",(0,s.jsx)(n.li,{children:"\u2705 Flask web application"}),"\n",(0,s.jsx)(n.li,{children:"\u2705 Modern responsive web interface"}),"\n",(0,s.jsx)(n.li,{children:"\u2705 Docker configuration"}),"\n",(0,s.jsx)(n.li,{children:"\u2705 Comprehensive documentation"}),"\n",(0,s.jsx)(n.li,{children:"\u2705 Testing examples"}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},77925:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/frontend-browser-d2ff82f09ee926c74df2dfabe7a1a09f.png"},4668:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/frontend-health-status-46e2d8f9ce6cabe6fff55cd6d4fe3287.png"},4425:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/frontend-info-b35d7b1b4a1c3a5486640614febdf3b8.png"},89433:(e,n,t)=>{t.d(n,{A:()=>r});const r=t.p+"assets/images/frontend-search-76d07ed01dde0854959f661a7ec1b0a3.png"},28453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>o});var r=t(96540);const s={},i=r.createContext(s);function a(e){const n=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.