<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lahfir</title>
    <description>The latest articles on DEV Community by Lahfir (@lahfir_ac22d8714d76cfd31e).</description>
    <link>https://dev.to/lahfir_ac22d8714d76cfd31e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3495415%2F858504dc-384e-41e5-95f6-f656a173359e.webp</url>
      <title>DEV Community: Lahfir</title>
      <link>https://dev.to/lahfir_ac22d8714d76cfd31e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lahfir_ac22d8714d76cfd31e"/>
    <language>en</language>
    <item>
      <title>Integrating Nano Banana Try‑On into a Polyglot Microservices Demo (gRPC, Skaffold, K8s)</title>
      <dc:creator>Lahfir</dc:creator>
      <pubDate>Mon, 22 Sep 2025 19:44:04 +0000</pubDate>
      <link>https://dev.to/lahfir_ac22d8714d76cfd31e/integrating-nano-banana-try-on-into-a-polyglot-microservices-demo-grpc-skaffold-k8s-14m4</link>
      <guid>https://dev.to/lahfir_ac22d8714d76cfd31e/integrating-nano-banana-try-on-into-a-polyglot-microservices-demo-grpc-skaffold-k8s-14m4</guid>
      <description>&lt;p&gt;Adding a new AI feature to a polyglot microservices repo doesn’t have to be painful. In this post, I’ll show how I integrated the Nano Banana Try‑On service (&lt;code&gt;tryonservice/&lt;/code&gt;) into the Google Online Boutique–style demo: containerizing a Python gRPC service, exposing it on Kubernetes, wiring the Go frontend, and enabling local/dev workflows with Skaffold and Docker Compose.&lt;/p&gt;

&lt;p&gt;What we’ll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service design and gRPC surface&lt;/li&gt;
&lt;li&gt;Containerization (multi‑stage Dockerfile)&lt;/li&gt;
&lt;li&gt;Kubernetes Deployment/Service and env wiring&lt;/li&gt;
&lt;li&gt;Frontend integration (Go) via env vars + gRPC client&lt;/li&gt;
&lt;li&gt;Local dev with Skaffold and Docker Compose&lt;/li&gt;
&lt;li&gt;Observability hooks with OpenTelemetry&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Architecture at a glance
&lt;/h3&gt;

&lt;p&gt;The new &lt;code&gt;tryonservice&lt;/code&gt; is a Python gRPC service that generates a virtual try‑on image for a given user and product. The Go &lt;code&gt;frontend&lt;/code&gt; exposes HTTP routes and calls &lt;code&gt;tryonservice&lt;/code&gt; over gRPC. Everything is deployed with Kubernetes; images are built via Skaffold.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Try‑On service (Python + gRPC)
&lt;/h3&gt;

&lt;p&gt;Key entrypoint: &lt;code&gt;src/tryonservice/tryon_server.py&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gRPC server implements &lt;code&gt;TryOnService&lt;/code&gt; with two RPCs: &lt;code&gt;TryOnProduct&lt;/code&gt; and &lt;code&gt;GetTryOnHistory&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Uses Google Gemini via &lt;code&gt;google-genai&lt;/code&gt; when &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; is present; otherwise returns a mock image so dev flows are smooth.&lt;/li&gt;
&lt;li&gt;Emits structured logs and optional OpenTelemetry traces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code highlights:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;58:class TryOnService(demo_pb2_grpc.TryOnServiceServicer):
71:    def TryOnProduct(self, request, context):
299:def serve():
301:    port = os.environ.get('PORT', '5012')
324:    server.add_insecure_port(f'[::]:{port}')
327:    logger.info(f"TryOn service listening on port {port}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observability is opt‑in via OTLP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;41:# Initialize OpenTelemetry
42:if os.environ.get('OTEL_EXPORTER_OTLP_ENDPOINT'):
43:    resource = Resource(attributes={"service.name": "tryonservice"})
45:    processor = BatchSpanProcessor(
46:        OTLPSpanExporter(endpoint=os.environ.get('OTEL_EXPORTER_OTLP_ENDPOINT'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;Pinned in &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:grpcio==1.68.1
4:google-genai==0.3.0
5:Pillow==11.0.0
8:opentelemetry-api==1.29.0
11:opentelemetry-exporter-otlp==1.29.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Containerization (multi‑stage Dockerfile)
&lt;/h3&gt;

&lt;p&gt;The service uses a two‑stage build to keep the runtime image slim, exposes gRPC on 5012, and runs the Python server directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:FROM python:3.12-slim AS base
9:COPY requirements.txt .
10:RUN pip install --prefix="/install" -r requirements.txt
14:WORKDIR /tryonservice
24:EXPOSE 5012
29:ENTRYPOINT ["python", "tryon_server.py"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kubernetes: Deployment and Service
&lt;/h3&gt;

&lt;p&gt;We declare the Deployment and ClusterIP Service, and wire in env vars for port, Gemini key (as a Secret), and OTEL exporter. Probes are simple TCP checks on the gRPC port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:apiVersion: apps/v1
4:  name: tryonservice
19:      containers:
21:        image: gcr.io/quiet-cider-472416-a5/tryonservice:v2
27:        - name: PORT
28:          value: "5012"
29:        - name: GEMINI_API_KEY
31:            secretKeyRef:
32:              name: gemini-api-key
35:        - name: OTEL_EXPORTER_OTLP_ENDPOINT
36:          value: "otel-collector:4317"
56:apiVersion: v1
59:  name: tryonservice
65:  - name: grpc
66:    port: 5012
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Skaffold: build and deploy
&lt;/h3&gt;

&lt;p&gt;Skaffold tracks and builds the service image and deploys manifests via kustomize.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;50:  - image: tryonservice
51:    context: src/tryonservice
60:  kustomize:
62:    - kubernetes-manifests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means &lt;code&gt;skaffold dev&lt;/code&gt; or &lt;code&gt;skaffold run&lt;/code&gt; will build &lt;code&gt;src/tryonservice&lt;/code&gt; and roll it out alongside other services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend wiring (Go)
&lt;/h3&gt;

&lt;p&gt;The Go &lt;code&gt;frontend&lt;/code&gt; consumes &lt;code&gt;TRYON_SERVICE_ADDR&lt;/code&gt; and opens a gRPC connection; routes &lt;code&gt;/tryon&lt;/code&gt; and &lt;code&gt;/tryon/history&lt;/code&gt; proxy user actions to the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;84: tryOnSvcAddr string
145:    mustMapEnv(&amp;amp;svc.tryOnSvcAddr, "TRYON_SERVICE_ADDR")
155:    mustConnGRPC(ctx, &amp;amp;svc.tryOnSvcConn, svc.tryOnSvcAddr)
168:    r.HandleFunc(baseUrl + "/tryon", svc.tryOnHandler).Methods(http.MethodPost)
169:    r.HandleFunc(baseUrl + "/tryon/history", svc.tryOnHistoryHandler).Methods(http.MethodGet)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kubernetes, the frontend gets that env var from its Deployment manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;86:          - name: TRYON_SERVICE_ADDR
87:            value: "tryonservice:5012"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local docker‑compose and the helper script, the variable is present too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;72:      - TRYON_SERVICE_ADDR=tryonservice:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;93:TRYON_SERVICE_ADDR=tryonservice:8080
136:      - TRYON_SERVICE_ADDR=tryonservice:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: In Kubernetes we expose 5012 (native gRPC port). In some local setups we route through the frontend at 8080; adjust as needed for your environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running locally with Skaffold
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prereqs: Docker, kubectl, a local or remote Kubernetes cluster, and Skaffold.&lt;/li&gt;
&lt;li&gt;Optional: Create the Gemini API key Secret so the service can use real generations:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret generic gemini-api-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GEMINI_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Launch dev loop:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;skaffold dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Port‑forward the try‑on service for quick gRPC tests:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward deployment/tryonservice 5012:5012
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Example gRPC smoke test with &lt;code&gt;grpcurl&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grpcurl &lt;span class="nt"&gt;-plaintext&lt;/span&gt; localhost:5012 list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running with docker‑compose
&lt;/h3&gt;

&lt;p&gt;If you prefer Compose for a quick end‑to‑end spin‑up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure the frontend and try‑on env vars are aligned; in this repo they’re defined in &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability (optional)
&lt;/h3&gt;

&lt;p&gt;Set &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt; in &lt;code&gt;tryonservice&lt;/code&gt; to emit traces to your collector. The frontend is already OTel‑instrumented via &lt;code&gt;otelgrpc&lt;/code&gt; and &lt;code&gt;otelhttp&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gotchas and tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;GEMINI_API_KEY&lt;/code&gt; is not set, the service falls back to a mock image. This is great for dev environments and CI.&lt;/li&gt;
&lt;li&gt;gRPC readiness/liveness probes use TCP checks on 5012. If you add TLS, switch probes accordingly.&lt;/li&gt;
&lt;li&gt;Keep image sizes small by relying on the two‑stage Dockerfile and avoiding unnecessary build tools in the runtime image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wrap‑up
&lt;/h3&gt;

&lt;p&gt;That’s the full integration path: Python gRPC microservice → container → Kubernetes → Go frontend → local/dev workflows with Skaffold and Compose → optional OTel. You can apply the same pattern to add more AI‑backed capabilities to the demo.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>microservices</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Semantic Search UI with Tambo</title>
      <dc:creator>Lahfir</dc:creator>
      <pubDate>Thu, 11 Sep 2025 17:07:56 +0000</pubDate>
      <link>https://dev.to/lahfir_ac22d8714d76cfd31e/semantic-search-ui-with-tambo-3dd1</link>
      <guid>https://dev.to/lahfir_ac22d8714d76cfd31e/semantic-search-ui-with-tambo-3dd1</guid>
      <description>&lt;p&gt;&lt;em&gt;Let people ask in their own words. Show results they can act on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://drive.google.com/file/d/12--5cD5xuHDMaFWQ9LJN08RMmQjlWE0D/view?usp=sharing" rel="noopener noreferrer"&gt;Live demo&lt;/a&gt; · &lt;a href="https://github.com/lahfir/tambo-product-showcase" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;Most search experiences make people work too hard: pick the right category, open five filter drawers, guess which checkbox means what. It’s tiring.&lt;/p&gt;

&lt;p&gt;I wanted something simpler: you type “show me laptops under $1500 with 16GB RAM” and immediately see useful cards you can skim, compare, and click. No flashy effects, no friction—just answers.&lt;/p&gt;

&lt;p&gt;I built this template during the Tambo Hackathon by Tambo. My goal was personal: stop making people wrestle with filters and let them just ask for what they need. With limited time, I focused on what actually helps users—semantic understanding, clean cards, fast performance—and skipped everything that gets in the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this template gives you
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generative UI with Tambo&lt;/strong&gt;: Plain‑English queries are turned into structured intent (filters, sort, constraints) and friendly UI hints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Card‑first results&lt;/strong&gt;: Clean, responsive cards that highlight the details that matter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works across domains&lt;/strong&gt;: Products, jobs, real estate, services, recipes, documents—anything you can search and present as cards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast by default&lt;/strong&gt;: Minimal JS, smart caching, mobile‑first, and no gratuitous animations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a pragmatic starting point for teams who need great semantic search without building a bespoke system from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Tambo powers “generative UI”
&lt;/h2&gt;

&lt;p&gt;Tambo converts fuzzy, natural language into something your UI can immediately use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understand intent&lt;/strong&gt;: Extracts entities, constraints, preferences, and sort hints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Propose UI&lt;/strong&gt;: Suggests helpful refinements and short explanations (“Filtered to 2 bedrooms under $2k”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay predictable&lt;/strong&gt;: You keep control of what is rendered; Tambo just provides structured guidance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is an interface that feels conversational without becoming chaotic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try these queries
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“Find wireless headphones under $200 with noise canceling”
“2‑bedroom apartments downtown under $2,000 with in‑unit laundry”
“Remote senior React roles above $120k, US‑only”
“Men’s waterproof hiking boots, wide fit”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get relevant, scannable cards—no labyrinth of filters required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real‑world examples included
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Electronics&lt;/strong&gt;: Specs, prices, compatibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real Estate&lt;/strong&gt;: Beds, location, amenities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs&lt;/strong&gt;: Salary, skills, remote/hybrid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fashion&lt;/strong&gt;: Sizes, materials, styles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same UI, different data. That’s the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack (kept intentionally simple)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js 15 — Routing, data, and deployment
React 19 — Modern, stable UI primitives
TypeScript — Catch mistakes early
Tambo — Semantic understanding + UI guidance
Tailwind CSS — Fast, consistent styling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design choices that respect users
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Card‑first&lt;/strong&gt;: Clear hierarchy, actionable info, easy comparison&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile‑native&lt;/strong&gt;: Touch targets sized right, no hover‑only affordances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No gratuitous animations&lt;/strong&gt;: Snappy over “smooth”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessible by default&lt;/strong&gt;: High contrast, sensible semantics&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  My baseline theme
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0070f3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eaeaea&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;High contrast, zero clutter. Change it if you want; it won’t fight you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance that feels instant
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tiny, focused bundles&lt;/strong&gt;: Only what you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart caching&lt;/strong&gt;: Results feel instant after first query&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image optimization&lt;/strong&gt;: Crisp cards, quick loads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No animation tax&lt;/strong&gt;: Fewer libs, fewer jank sources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started (2 minutes)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/lahfir/tambo-product-showcase
&lt;span class="nb"&gt;cd &lt;/span&gt;product-showcase
npm &lt;span class="nb"&gt;install
cp &lt;/span&gt;example.env.local .env.local
&lt;span class="c"&gt;# Add your Tambo API key&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"NEXT_PUBLIC_TAMBO_API_KEY=your-key-here"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .env.local
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the app, type a query, and you’re off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make it yours
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Swap the data source&lt;/strong&gt;: Point the retrieval layer at your API or database (see &lt;code&gt;src/services/*-data.ts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tune the cards&lt;/strong&gt;: Adjust the fields and layout in the existing components under &lt;code&gt;src/components/tambo/&lt;/code&gt; so they show what matters for your domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control the UI contract&lt;/strong&gt;: You decide which Tambo signals you honor (filters, sort, facets, explanations) and how they render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the template is domain‑agnostic, you can use it for anything that involves search, with results presented as cards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why simple wins
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fast beats fancy&lt;/strong&gt;: People want answers, not motion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile matters&lt;/strong&gt;: Many users are on phones—optimize for that reality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean scales&lt;/strong&gt;: Fewer assumptions make it easier to adapt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less breaks less&lt;/strong&gt;: Small surface area, fewer bugs&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;I’m doubling down on the core experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even faster first‑query results&lt;/li&gt;
&lt;li&gt;More polished mobile ergonomics&lt;/li&gt;
&lt;li&gt;Additional domain examples&lt;/li&gt;
&lt;li&gt;Continued code cleanup and clarity&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Built for teams who want to ship a semantic search today—not a science project tomorrow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tambo</category>
    </item>
  </channel>
</rss>
