<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[code and cloud]]></title><description><![CDATA[code and cloud]]></description><link>https://bishwasjha.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 13:45:46 GMT</lastBuildDate><atom:link href="https://bishwasjha.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Python Maithili DSL — Bridging Programming & Culture]]></title><description><![CDATA[Empowering developers to write Python code in their native Maithili language using the elegant Devanagari script.
Programming in Your Mother Tongue
Imagine writing Python code not in English, but in Maithili, one of India’s and Nepal’s most ancient a...]]></description><link>https://bishwasjha.com/python-maithili-dsl-bridging-programming-and-culture</link><guid isPermaLink="true">https://bishwasjha.com/python-maithili-dsl-bridging-programming-and-culture</guid><category><![CDATA[Python]]></category><category><![CDATA[dsl]]></category><category><![CDATA[Culture]]></category><category><![CDATA[Nepal]]></category><category><![CDATA[india]]></category><dc:creator><![CDATA[Bishwas Jha]]></dc:creator><pubDate>Sat, 04 Oct 2025 20:29:33 GMT</pubDate><content:encoded><![CDATA[<p><em>Empowering developers to write Python code in their native</em> <strong><em>Maithili</em></strong> <em>language using the elegant</em> <strong><em>Devanagari script.</em></strong></p>
<h2 id="heading-programming-in-your-mother-tongue">Programming in Your Mother Tongue</h2>
<p>Imagine writing Python code <strong>not in English</strong>, but in <strong>Maithili</strong>, one of India’s and Nepal’s most ancient and culturally rich languages.<br />The <strong>Python Maithili DSL (Domain-Specific Language)</strong> makes this possible, allowing developers to express their ideas using familiar Maithili words and script.</p>
<pre><code class="lang-plaintext">कार्य नमस्कार():
    छपाउ("हम मैथिली में कोड कऽ रहल छी।")

नमस्कार()
</code></pre>
<p><em>Output: हम मैथिली में कोड कऽ रहल छी।</em></p>
<p>This isn’t just a translation layer — it’s a bridge between <strong>technology and culture</strong>, making programming more accessible and meaningful for millions of Maithili speakers worldwide.</p>
<h2 id="heading-why-it-matters-breaking-language-barriers">Why It Matters — Breaking Language Barriers</h2>
<h3 id="heading-the-challenge">The Challenge</h3>
<ul>
<li><p><strong>English-Centric Code</strong> → Most programming languages rely on English, creating hurdles for non-native speakers.</p>
</li>
<li><p><strong>Cultural Disconnect</strong> → Code feels foreign when written in an unfamiliar language.</p>
</li>
<li><p><strong>Limited Accessibility</strong> → Millions of aspiring developers never get started because of the language barrier.</p>
</li>
</ul>
<h3 id="heading-the-solution">The Solution</h3>
<ul>
<li><p><strong>Native Language Programming</strong> → Write Python using Maithili keywords and Devanagari script.</p>
</li>
<li><p><strong>Cultural Integration</strong> → Code that feels natural and connected to local identity.</p>
</li>
<li><p><strong>Inclusive Education</strong> → Makes programming easier to teach and learn in Maithili-speaking regions.</p>
</li>
</ul>
<h2 id="heading-key-features">Key Features</h2>
<h3 id="heading-full-python-compatibility">Full Python Compatibility</h3>
<ul>
<li><p>Works with <strong>all Python syntax</strong> — functions, classes, OOP, lambdas, decorators, async/await, and more.</p>
</li>
<li><p>Supports <strong>modern Python features</strong> like f-strings and type hints.</p>
</li>
</ul>
<h3 id="heading-beautiful-devanagari-integration">Beautiful Devanagari Integration</h3>
<ul>
<li><p>Use <strong>native numerals (०-९)</strong> instead of 0-9.</p>
</li>
<li><p>Elegant typography and full Unicode support for Devanagari characters.</p>
</li>
</ul>
<h3 id="heading-smart-developer-tools">Smart Developer Tools</h3>
<ul>
<li><p><strong>Maithili error messages</strong> — debug in your own language.</p>
</li>
<li><p><strong>Linting &amp; style guidance</strong> with Maithili feedback.</p>
</li>
<li><p><strong>Helpful suggestions</strong> for cleaner, idiomatic code.</p>
</li>
</ul>
<h3 id="heading-rich-example-library">Rich Example Library</h3>
<ul>
<li><p>Real-world projects like calculators, weather apps, and shopping lists.</p>
</li>
<li><p>Beginner-friendly tutorials and best practices.</p>
</li>
<li><p>Community-contributed code samples.</p>
</li>
</ul>
<hr />
<h2 id="heading-getting-started">Getting Started</h2>
<ol>
<li><h3 id="heading-install">Install</h3>
</li>
</ol>
<pre><code class="lang-bash">pip install python-maithili
</code></pre>
<ol start="2">
<li><h3 id="heading-write-your-first-program">Write Your First Program</h3>
</li>
</ol>
<p>Create a file named <code>hello.dmai</code>:</p>
<pre><code class="lang-plaintext">कार्य नमस्कार():
    छपाउ("नमस्कार! हम मैथिली में कोड कऽ रहल छी।")
    छपाउ("यह एक सुंदर भाषा अछि!")

नमस्कार()
</code></pre>
<p>Run it:</p>
<pre><code class="lang-bash">python_maithili hello.dmai
</code></pre>
<ol start="3">
<li><h3 id="heading-build-something-bigger-a-simple-calculator">Build Something Bigger — A Simple Calculator</h3>
</li>
</ol>
<pre><code class="lang-plaintext">कार्य जोड़(अ, ब):
    फेर करू अ + ब

कार्य घटाउ(अ, ब):
    फेर करू अ - ब

कार्य मुख्य_कैलकुलेटर():
    छपाउ("=== मैथिली कैलकुलेटर ===")
    संख्या१ = १०
    संख्या२ = ५

    परिणाम = जोड़(संख्या१, संख्या२)
    छपाउ("जोड़ का परिणाम: " + str(परिणाम))

मुख्य_कैलकुलेटर()
</code></pre>
<hr />
<h2 id="heading-english-maithili-mapping">English → Maithili Mapping</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>English</td><td>Maithili</td><td>Usage</td></tr>
</thead>
<tbody>
<tr>
<td><code>def</code></td><td><code>कार्य</code></td><td>Define a function</td></tr>
<tr>
<td><code>class</code></td><td><code>वर्ग</code></td><td>Define a class</td></tr>
<tr>
<td><code>if</code></td><td><code>यदि</code></td><td>Conditional statement</td></tr>
<tr>
<td><code>else</code></td><td><code>नहि त</code></td><td>Alternative condition</td></tr>
<tr>
<td><code>for</code></td><td><code>प्रत्येक</code></td><td>Loop iteration</td></tr>
<tr>
<td><code>in</code></td><td><code>में</code></td><td>Membership testing</td></tr>
<tr>
<td><code>print</code></td><td><code>छपाउ</code></td><td>Output text</td></tr>
<tr>
<td><code>return</code></td><td><code>फेर करू</code></td><td>Return value</td></tr>
<tr>
<td><code>True</code></td><td><code>सत्य</code></td><td>Boolean true</td></tr>
<tr>
<td><code>False</code></td><td><code>मिथ्या</code></td><td>Boolean false</td></tr>
<tr>
<td><code>None</code></td><td><code>शून्य</code></td><td>Null value</td></tr>
<tr>
<td><code>self</code></td><td><code>स्वयं</code></td><td>Object reference</td></tr>
</tbody>
</table>
</div><p><strong>Numerals:</strong> <code>० १ २ ३ ४ ५ ६ ७ ८ ९</code></p>
<hr />
<h2 id="heading-real-world-impact">Real-World Impact</h2>
<h3 id="heading-education">Education</h3>
<ul>
<li><p>Teach Python in <strong>local schools and colleges</strong>.</p>
</li>
<li><p>Enable <strong>computer science education</strong> in native Maithili.</p>
</li>
<li><p>Promote <strong>digital literacy</strong>.</p>
</li>
</ul>
<h3 id="heading-government-amp-public-services">Government &amp; Public Services</h3>
<ul>
<li><p>Build <strong>localized apps</strong> for e-governance and citizen services.</p>
</li>
<li><p>Analyze public data with tools accessible to local officials.</p>
</li>
</ul>
<h3 id="heading-business-amp-industry">Business &amp; Industry</h3>
<ul>
<li><p>Create <strong>custom software</strong> for Maithili-speaking enterprises.</p>
</li>
<li><p>Build <strong>web apps &amp; data tools</strong> in native language.</p>
</li>
</ul>
<h3 id="heading-cultural-preservation">Cultural Preservation</h3>
<ul>
<li><p>Keep Maithili alive in the digital age.</p>
</li>
<li><p>Build apps that celebrate <strong>heritage and identity</strong>.</p>
</li>
</ul>
<h2 id="heading-join-the-community">Join the Community</h2>
<p>Contributors of all backgrounds are welcome:</p>
<ul>
<li><p><strong>Developers:</strong> Code features, fix bugs, improve tools.</p>
</li>
<li><p><strong>Language Experts:</strong> Expand Maithili vocabulary &amp; ensure correct grammar.</p>
</li>
<li><p><strong>Educators:</strong> Create tutorials, courses, and outreach programs.</p>
</li>
<li><p><strong>Designers:</strong> Improve UI/UX, typography, and brand identity.</p>
</li>
</ul>
<p>Start contributing:</p>
<ol>
<li><p>Fork the repository.</p>
</li>
<li><p>Set up your dev environment.</p>
</li>
<li><p>Pick an issue marked “good first issue.”</p>
</li>
<li><p>Submit a pull request.</p>
</li>
</ol>
<h2 id="heading-whats-next">What’s Next</h2>
<ul>
<li><p><strong>v0.3.0:</strong> Better error messages, VS Code extension, debugger support, faster compilation.</p>
</li>
<li><p><strong>v0.4.0:</strong> Web-based REPL, mobile app, cloud deployment, AI-powered code suggestions.</p>
</li>
<li><p><strong>Long-term:</strong> Support for other languages and full learning platform.</p>
</li>
</ul>
<h2 id="heading-stay-connected">Stay Connected</h2>
<ul>
<li><p><strong>GitHub:</strong> <a target="_blank" href="https://github.com/yourusername/python-maithili-dsl">github.com/yourusername/python-maithili-dsl</a></p>
</li>
<li><p><strong>PyPI:</strong> <a target="_blank" href="https://pypi.org/project/python-maithili">pypi.org/project/python-maithili</a></p>
</li>
<li><p><strong>Docs:</strong> <a target="_blank" href="https://python-maithili-dsl.readthedocs.io/">python-maithili-dsl.readthedocs.io</a></p>
</li>
</ul>
<h2 id="heading-start-your-maithili-programming-journey-today">Start Your Maithili Programming Journey Today</h2>
<p>The <strong>Python Maithili DSL</strong> isn’t just a programming tool — it’s a <strong>movement</strong> to make technology more inclusive and culturally relevant.</p>
<p>👉 Install it, build your first program, join the community, and help shape the future of <strong>native-language programming</strong>.</p>
<blockquote>
<p><em>“Programming isn’t just about syntax; it’s about expressing ideas. Doing that in your mother tongue opens up endless possibilities.”</em></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How I Built My AI Chatbot Using n8n and Elementor]]></title><description><![CDATA[Over the last few weeks, I’ve been building a custom AI chatbot from the ground up, not just a basic assistant, but one designed to provide high-quality, structured, and ethical responses in a very specific domain. It is developed for a non-profit as...]]></description><link>https://bishwasjha.com/how-i-built-my-ai-chatbot-using-n8n-and-elementor</link><guid isPermaLink="true">https://bishwasjha.com/how-i-built-my-ai-chatbot-using-n8n-and-elementor</guid><category><![CDATA[n8n]]></category><category><![CDATA[AI]]></category><category><![CDATA[nocode]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[GPT 4]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[openai]]></category><category><![CDATA[nonprofit]]></category><category><![CDATA[Pinecone]]></category><category><![CDATA[langchain]]></category><category><![CDATA[chatbot]]></category><dc:creator><![CDATA[Bishwas Jha]]></dc:creator><pubDate>Mon, 14 Jul 2025 19:51:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752522407861/5c50b92d-abf0-4fcd-ba4c-ed1a1f4a61dc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the last few weeks, I’ve been building a custom AI chatbot from the ground up, not just a basic assistant, but one designed to provide high-quality, structured, and ethical responses in a very specific domain. It is developed for a non-profit as part of my voluntary effort, to give back.</p>
<p>This post is a behind-the-scenes look at how I built it: from automated data ingestion to AI reasoning and frontend integration. It’s powered entirely by <strong>n8n</strong> for the backend workflow logic and <strong>Elementor(WordPress website builder)</strong> for the frontend interface. While I’ll reveal more about the chatbot's identity and its unique purpose in a future article, this one focuses on the technical process.</p>
<hr />
<h2 id="heading-why-build-a-custom-ai-chatbot">Why Build a Custom AI Chatbot?</h2>
<p>With tools like ChatGPT and Gemini already out there, why bother building your own? The answer lies in <strong>control</strong> and <strong>customisation</strong>. I needed a solution that:</p>
<ul>
<li><p>Responds based only on approved content</p>
</li>
<li><p>Avoids hallucination and speculation</p>
</li>
<li><p>Includes multilingual disclaimers and reliability tags</p>
</li>
<li><p>Can integrate directly into my website with a tailored UI</p>
</li>
</ul>
<p>That meant building from the ground up and n8n was the perfect tool for the job.</p>
<h2 id="heading-architecture-overview">Architecture Overview</h2>
<p>The system is composed of <strong>two main n8n workflows</strong>:</p>
<ol>
<li><p><strong>Data ingestion pipeline</strong>: to process and embed source documents.</p>
</li>
<li><p><strong>Chatbot interaction engine</strong>: to manage real-time user queries.</p>
</li>
</ol>
<p>Let’s break them down.</p>
<hr />
<h2 id="heading-1-workflow-automated-data-ingestion">1) Workflow: Automated Data Ingestion</h2>
<p>This workflow ensures the chatbot always has access to the latest, most reliable source material.</p>
<h3 id="heading-step-1-trigger-on-new-uploads">Step 1: Trigger on New Uploads</h3>
<p>A <strong>Google Drive Trigger</strong> monitors a folder. When a new file (like a guideline or scientific document) is uploaded, the workflow begins.</p>
<h3 id="heading-step-2-download-amp-process">Step 2: Download &amp; Process</h3>
<p>The file is downloaded and processed through OpenAI’s <code>text-embedding-3-large</code> model to generate vector embeddings.</p>
<h3 id="heading-step-3-store-in-pinecone">Step 3: Store in Pinecone</h3>
<p>The embeddings are stored in a <strong>Pinecone vector database</strong>, organised under a specific namespace for later retrieval.</p>
<p>Text is chunked and metadata-tagged to improve semantic search.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752520750197/38123870-ce46-45f8-aa96-dd9c3213f802.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-2-workflow-ai-powered-chatbot-interaction">2) Workflow: AI-Powered Chatbot Interaction</h2>
<p>This is what powers the chatbot users interact with.</p>
<h3 id="heading-step-1-message-trigger">Step 1: Message Trigger</h3>
<p>A <strong>ChatTrigger</strong> node in n8n captures messages from the frontend interface.</p>
<h3 id="heading-step-2-langchain-agent">Step 2: LangChain Agent</h3>
<p>A LangChain Agent is set up with:</p>
<ul>
<li><p>A clear scope of what it can and cannot answer</p>
</li>
<li><p>A non-technical, empathetic tone</p>
</li>
<li><p>Built-in multilingual disclaimers</p>
</li>
<li><p>Transparency levels (A, B, C) for content sources</p>
</li>
</ul>
<h3 id="heading-step-3-memory-retrieval-and-response">Step 3: Memory, Retrieval, and Response</h3>
<p>The agent uses short-term memory to maintain context.</p>
<p>If needed, it queries Pinecone using a vector store tool, retrieves the most relevant content, and passes it to OpenAI’s <code>gpt-4o-mini</code> to generate the final reply.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752520821418/80b147c4-47dc-465f-bfbd-12b786b19adb.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-frontend-integration-with-elementor">Frontend Integration with Elementor</h2>
<p>To make the chatbot feel native to my website, I used HTML element. Here’s how I connected everything:</p>
<ul>
<li><p>Created a custom floating chat window with HTML + JS</p>
</li>
<li><p>Connected it to the n8n webhook</p>
</li>
<li><p>Made it responsive and cleanly styled</p>
</li>
<li><p>Ensured every response includes a disclaimer</p>
</li>
</ul>
<p>No third-party UI tools, no extra hosting, just pure control.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752521999127/4a1a4d3e-dbb7-4660-80d8-e7a44d165208.png" alt class="image--center mx-auto" /></p>
<p>Names are hidden as the chatbot is not publicly live yet.</p>
<hr />
<h2 id="heading-built-in-safety-and-guardrails">Built-In Safety and Guardrails</h2>
<p>Accuracy and ethical design were top priorities. Here's how the chatbot stays safe:</p>
<ul>
<li><p>No advice, no diagnosis, no speculation</p>
</li>
<li><p>Politely redirects questions that are out of scope</p>
</li>
<li><p>Every response includes a <strong>source reliability tag</strong> and a <strong>multilingual disclaimer</strong></p>
</li>
<li><p>If a reliable answer isn’t possible, it clearly says so</p>
</li>
</ul>
<hr />
<h2 id="heading-whats-next">What’s Next?</h2>
<p>In my next article, I’ll reveal the <strong>identity and mission</strong> of this chatbot. who it’s designed to help, and the meaning behind its name.</p>
<blockquote>
<p>Hint: it’s not just another assistant. It’s designed to help people make sense of something complex and important, but you’ll find out more soon.</p>
</blockquote>
<hr />
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>This project has taught me how powerful it is to combine AI with low-code tools like n8n and Pinecone.With thoughtful design and the right architecture, you can build something:</p>
<ul>
<li><p>Scalable</p>
</li>
<li><p>Safe</p>
</li>
<li><p>Purpose-driven</p>
</li>
</ul>
<p>Thanks for reading. I hope this inspired you to experiment or at least left you curious about what’s coming next. 😉</p>
]]></content:encoded></item><item><title><![CDATA[Become Zero to Hero with AWS CDK]]></title><description><![CDATA[What is AWS CDK?
The AWS Cloud Development Kit (CDK) is an open-source framework that lets you define and provision cloud infrastructure using familiar programming languages (TypeScript, Python, Java, .NET, etc.) instead of raw JSON or YAML CloudForm...]]></description><link>https://bishwasjha.com/become-zero-to-hero-with-aws-cdk</link><guid isPermaLink="true">https://bishwasjha.com/become-zero-to-hero-with-aws-cdk</guid><category><![CDATA[AWS]]></category><category><![CDATA[CDK]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Blueprints]]></category><category><![CDATA[customization]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Bishwas Jha]]></dc:creator><pubDate>Sun, 13 Jul 2025 04:14:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752414308782/03a65b93-61b4-4607-8e99-c5c6d1c505c5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-aws-cdk">What is AWS CDK?</h2>
<p>The AWS Cloud Development Kit (<strong>CDK</strong>) is an open-source framework that lets you define and provision cloud infrastructure using familiar programming languages (TypeScript, Python, Java, .NET, etc.) instead of raw JSON or YAML CloudFormation templates.</p>
<p><strong>Level of Constructs. what are they?</strong><br />– <strong>L1 constructs</strong> maps 1:1 to CloudFormation resources.<br />– <strong>L2 constructs</strong> provide opinionated, higher-level abstractions with sensible defaults.<br />– <strong>L3 (patterns)</strong> bundle multiple resources into a single, reusable component (e.g. a ECR-backed Fargate service with logging, auto-scaling, and alarms).</p>
<h2 id="heading-why-to-use-cdk">Why to use CDK?</h2>
<ul>
<li><p><strong>Infrastructure as Code (IaC)</strong></p>
<ul>
<li><p><strong>Imperative power</strong>: Use loops, functions, and abstractions instead of JSON/YAML snippets.</p>
</li>
<li><p><strong>L1 vs. L2(Level 1 and Level 2)</strong>: CDK’s L1 constructs mirror raw <strong>CloudFormation resources</strong>. L2 constructs provide sensible defaults and higher-level APIs.</p>
</li>
<li><p><strong>Gaps in coverage</strong>: When your architecture spans multiple resources for example: an encrypted S3 bucket wired to a Lambda function, you bundle them into a single reusable construct. That prevents duplication and enforces your standards.</p>
</li>
<li><p><strong>Use BluePrints</strong>: Blueprints take this a step further by allowing you to inject defaults into existing L2 constructs.</p>
</li>
</ul>
</li>
<li><p><strong>Polyglot support via jsii</strong><br />  Under the hood, CDK’s core is written in TypeScript and compiled by jsii into libraries for Python, Java, and .NET, so you get first-class support in your language of choice.</p>
</li>
<li><h3 id="heading-some-more-features-that-you-cannot-miss"><strong>Some more features that you cannot miss</strong></h3>
</li>
<li><p><strong>CLI tooling</strong><br />  – <code>cdk synth</code> generates CloudFormation templates.<br />  – <code>cdk diff</code> shows changes vs. deployed stacks.<br />  – <code>cdk deploy</code> provisions or updates stacks.<br />  – <code>cdk destroy</code> deletes stacks.</p>
</li>
<li><p><strong>Extensibility</strong><br />  – <strong>Custom constructs</strong> let you encapsulate multi-resource patterns (e.g. an encrypted S3 bucket with Lambda event-handlers) into shareable libraries.<br />  – <strong>Blueprints</strong> (via <code>IPropertyInjector</code>) let you enforce organizational standards (encryption, logging, tagging) across any L2 construct without modifying your app code.<br />  – <strong>Aspects</strong> (e.g. cdk-nag) allow you to apply linting and policy checks at synth time.</p>
</li>
<li><p><strong>Testing</strong><br />  CDK apps can be unit-tested using the <code>@aws-cdk/assertions</code> library to validate that your stacks and constructs produce the cloud resources and configurations you expect.</p>
</li>
</ul>
<h2 id="heading-lets-get-our-hands-dirty"><strong>Lets get our hands dirty!</strong></h2>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before you begin, make sure you have:</p>
<ul>
<li><p><strong>Node.js (&gt;=18.x)</strong> and <strong>npm</strong> installed</p>
</li>
<li><p><strong>AWS CLI</strong> configured with credentials and a default region</p>
</li>
<li><p>Your local machine’s <strong>AWS credentials</strong> set up (<code>~/.aws/credentials</code>)</p>
</li>
</ul>
<hr />
<h2 id="heading-step-1-install-and-bootstrap-aws-cdk">Step 1: Install and Bootstrap AWS CDK</h2>
<p><strong>1.1. Install the CDK CLI globally</strong></p>
<pre><code class="lang-bash">npm install -g aws-cdk
npm -g install typescript
</code></pre>
<p><strong>1.2. Verify your installation</strong></p>
<pre><code class="lang-bash">cdk --version
</code></pre>
<p><strong>1.3. Bootstrap your AWS environment</strong> (This is an one-time action per account/region)</p>
<pre><code class="lang-plaintext">cdk bootstrap aws://&lt;ACCOUNT_ID&gt;/&lt;REGION&gt;
</code></pre>
<p>This provisions the CDK Toolkit stack (S3 bucket, IAM roles) needed for deployments.</p>
<h2 id="heading-step-2-initialize-a-typescript-cdk-project">Step 2: Initialize a TypeScript CDK Project</h2>
<p><strong>2.1. Create a new directory &amp; initialize</strong></p>
<pre><code class="lang-plaintext">mkdir cdk-demo &amp;&amp; cd cdk-demo
cdk init app --language typescript
</code></pre>
<p><strong>2.2. Install core dependencies</strong></p>
<pre><code class="lang-plaintext">npm install aws-cdk-lib constructs
</code></pre>
<h2 id="heading-step-3-building-a-simple-s3-bucket">Step 3: Building a Simple s3 bucket</h2>
<p><strong>3.1. Import and instantiate the bucket</strong><br />Open the generated stack file (usually <code>lib/cdk-demo-stack.ts</code>) and modify it like so:</p>
<pre><code class="lang-bash">import { Stack, StackProps } from <span class="hljs-string">'aws-cdk-lib'</span>;
import { Construct } from <span class="hljs-string">'constructs'</span>;
// 1. Import the S3 Bucket construct
import { Bucket } from <span class="hljs-string">'aws-cdk-lib/aws-s3'</span>;

<span class="hljs-built_in">export</span> class CdkDemoStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // 2. Create a simple S3 bucket
    new Bucket(this, <span class="hljs-string">'MyFirstBucket'</span>, {
      // optional: you can <span class="hljs-built_in">set</span> properties here, e.g.:
      // versioned: <span class="hljs-literal">true</span>,
      // encryption: BucketEncryption.S3_MANAGED,
    });
  }
}
</code></pre>
<p><strong>3.2. Synthesize your template</strong></p>
<pre><code class="lang-bash">cdk synth
</code></pre>
<p>You should see a CloudFormation template printed, with an <code>AWS::S3::Bucket</code> resource named <code>MyFirstBucket</code>.</p>
<p><strong>3.3. Deploy to AWS</strong></p>
<pre><code class="lang-bash">cdk deploy
</code></pre>
<p>Confirm the deploy prompt, and CDK will provision your bucket.</p>
<p><strong>3.4. Verify</strong><br />After deployment, you can visit the AWS S3 console and confirm that a bucket named something like <code>cdk-demo-MyFirstBucket-XXXXXXXXX</code> exists.</p>
<h2 id="heading-step-4-building-a-custom-blueprint-via-property-injectors">Step 4: Building a Custom Blueprint via Property Injectors</h2>
<p>Blueprints hook into CDK’s tree by implementing <code>IPropertyInjector</code>. You can inject defaults into any L2 construct at instantiation time.</p>
<p><strong>4.1. Create Your Library</strong></p>
<pre><code class="lang-bash">mkdir custom-construct &amp;&amp; <span class="hljs-built_in">cd</span> custom-construct
cdk init lib --language typescript
mkdir lib/src <span class="hljs-built_in">cd</span> lib/src/
touch s3.ts
npm install aws-cdk-lib constructs jsii
</code></pre>
<p><strong>4.2. Secure S3 Bucket Injector:</strong> This customisation can be used with blueprints property injector. we wiil further discuss about these features in our future article but reference github link can be found here.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// lib/secure-bucket-injector.ts</span>
<span class="hljs-keyword">import</span> { IPropertyInjector, InjectionContext } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> { Bucket, BucketProps, BlockPublicAccess } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib/aws-s3'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SecureBucketDefaults <span class="hljs-keyword">implements</span> IPropertyInjector {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> constructUniqueId = Bucket.PROPERTY_INJECTION_ID;

  inject(originalProps: BucketProps, _ctx: InjectionContext): BucketProps {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-comment">// Organizational security defaults</span>
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
      enforceSSL: <span class="hljs-literal">true</span>,

      <span class="hljs-comment">// Allow consumers to override</span>
      ...originalProps,
    };
  }
}
</code></pre>
<p><strong>4.2. Secure S3 Bucket module:</strong> Reference github link can be found here.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> cdk <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> s3 <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib/aws-s3'</span>;
<span class="hljs-keyword">import</span> { Construct } <span class="hljs-keyword">from</span> <span class="hljs-string">'constructs'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> SecureBucketInjectorProps {
  bucketName?: <span class="hljs-built_in">string</span>;
  versioned?: <span class="hljs-built_in">boolean</span>;
  encryption?: s3.BucketEncryption;
  blockPublicAccess?: s3.BlockPublicAccess;
  removalPolicy?: cdk.RemovalPolicy;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SecureBucketInjector <span class="hljs-keyword">extends</span> Construct {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> bucket: s3.Bucket;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">scope: Construct, id: <span class="hljs-built_in">string</span>, props: SecureBucketInjectorProps = {}</span>) {
    <span class="hljs-built_in">super</span>(scope, id);

    <span class="hljs-built_in">this</span>.bucket = <span class="hljs-keyword">new</span> s3.Bucket(<span class="hljs-built_in">this</span>, <span class="hljs-string">'SecureBucket'</span>, {
      bucketName: props.bucketName,
      versioned: props.versioned ?? <span class="hljs-literal">true</span>,
      encryption: props.encryption ?? s3.BucketEncryption.S3_MANAGED,
      blockPublicAccess: props.blockPublicAccess ?? s3.BlockPublicAccess.BLOCK_ALL,
      removalPolicy: props.removalPolicy ?? cdk.RemovalPolicy.DESTROY,
      enforceSSL: <span class="hljs-literal">true</span>,
    });
  }
}
</code></pre>
<p><strong>4.3. Configure jsii</strong></p>
<p>In your <code>package.json</code> add:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"jsii"</span>: {
    <span class="hljs-attr">"outdir"</span>: <span class="hljs-string">"dist"</span>,
    <span class="hljs-attr">"targets"</span>: {
      <span class="hljs-attr">"python"</span>: { <span class="hljs-attr">"module"</span>: <span class="hljs-string">"cdk_blueprints_demo"</span> },
    }
  }
}
</code></pre>
<p><strong>4.4. Compile and run jsii:</strong></p>
<pre><code class="lang-bash">npm run build      <span class="hljs-comment"># compiles your .ts to .js</span>
jsii               <span class="hljs-comment"># emits bindings in dist/</span>
npm publish        <span class="hljs-comment"># share on npm</span>
</code></pre>
<hr />
<h2 id="heading-step-6-applying-blueprints-in-your-cdk-app">Step 6: Applying Blueprints in Your CDK App</h2>
<p>Back in your <strong>app</strong> directory:</p>
<p><strong>6.1. Install your blueprint package</strong></p>
<pre><code class="lang-bash">npm install cdk-blueprints-demo
</code></pre>
<p><strong>6.2. Wire in your injector</strong></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// bin/app.ts</span>
<span class="hljs-keyword">import</span> { App, Stack, PropertyInjectors } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> { SecureBucketDefaults } <span class="hljs-keyword">from</span> <span class="hljs-string">'cdk-blueprints-demo'</span>;

<span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> App();
PropertyInjectors.of(app).add(<span class="hljs-keyword">new</span> SecureBucketDefaults());

<span class="hljs-keyword">const</span> stack = <span class="hljs-keyword">new</span> Stack(app, <span class="hljs-string">'MySecureStack'</span>);
<span class="hljs-comment">// Every Bucket you instantiate below gets your defaults</span>
<span class="hljs-keyword">new</span> Bucket(stack, <span class="hljs-string">'DataBucket'</span>, { bucketName: <span class="hljs-string">'my-data'</span> });
</code></pre>
<p><strong>6.3. Synthesize &amp; deploy</strong></p>
<pre><code class="lang-bash">cdk synth
cdk deploy
</code></pre>
<hr />
<h2 id="heading-step-7-composing-multiple-injectors">Step 7: Composing Multiple Injectors</h2>
<p>You can register as many injectors as you like, in registration order:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// lib/lambda-logging-injector.ts</span>
<span class="hljs-keyword">import</span> { IPropertyInjector } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> { FunctionProps, <span class="hljs-built_in">Function</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib/aws-lambda'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> LambdaLoggingDefaults <span class="hljs-keyword">implements</span> IPropertyInjector {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> constructUniqueId = <span class="hljs-built_in">Function</span>.PROPERTY_INJECTION_ID;
  inject(orig: FunctionProps) {
    <span class="hljs-keyword">return</span> { logRetention: <span class="hljs-number">14</span>, ...orig };
  }
}

<span class="hljs-comment">// lib/global-tag-injector.ts</span>
<span class="hljs-keyword">import</span> { IPropertyInjector } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> GlobalTagInjector <span class="hljs-keyword">implements</span> IPropertyInjector {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> constructUniqueId = <span class="hljs-string">'*'</span>; <span class="hljs-comment">// wildcard for all constructs</span>
  inject(orig: <span class="hljs-built_in">any</span>) {
    <span class="hljs-keyword">return</span> {
      tags: { Team: <span class="hljs-string">'Platform'</span>, ...orig.tags },
      ...orig,
    };
  }
}

<span class="hljs-comment">// In your app:</span>
PropertyInjectors.of(app).add(
  <span class="hljs-keyword">new</span> SecureBucketDefaults(),
  <span class="hljs-keyword">new</span> LambdaLoggingDefaults(),
  <span class="hljs-keyword">new</span> GlobalTagInjector(),
);
</code></pre>
<blockquote>
<p><strong>Tip:</strong> Defaults should be registered <strong>before</strong> consumer props; forced props go <strong>after</strong>.</p>
</blockquote>
<hr />
<h2 id="heading-step-8-avoiding-infinite-recursion">Step 8: Avoiding Infinite Recursion</h2>
<p>If your injector itself creates the same construct type, use the <code>InjectionContext</code>’s <code>skipNestedInjection</code> flag:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AccessLogInjector <span class="hljs-keyword">implements</span> IPropertyInjector {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> constructUniqueId = Bucket.PROPERTY_INJECTION_ID;

  inject(orig: BucketProps, ctx: InjectionContext): BucketProps {
    <span class="hljs-keyword">if</span> (ctx.skipNestedInjection) {
      <span class="hljs-keyword">return</span> orig;
    }

    <span class="hljs-keyword">const</span> logBucket = <span class="hljs-keyword">new</span> Bucket(ctx.host, <span class="hljs-string">'LogBucket'</span>, { <span class="hljs-comment">/* ... */</span> });

    <span class="hljs-keyword">return</span> {
      ...orig,
      serverAccessLogsBucket: logBucket,
      accessControl: BucketAccessControl.LOG_DELIVERY_WRITE,
      <span class="hljs-comment">// prevent recursion</span>
      _skipNestedInjection: <span class="hljs-literal">true</span>,
    };
  }
}
</code></pre>
<hr />
<h2 id="heading-step-9-integrating-cdk-nag-for-policy-checks">Step 9: Integrating cdk-nag for Policy Checks</h2>
<p>Add <strong>cdk-nag</strong> to enforce AWS Solutions best practices at synth time:</p>
<pre><code class="lang-bash">npm install cdk-nag
</code></pre>
<p>In your app:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Aspects } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> { AwsSolutionsChecks } <span class="hljs-keyword">from</span> <span class="hljs-string">'cdk-nag'</span>;

Aspects.of(app).add(<span class="hljs-keyword">new</span> AwsSolutionsChecks());
</code></pre>
<p>Now, when you run <code>cdk synth</code>, cdk-nag will emit warnings or errors for any violations (e.g., public S3 buckets).</p>
<hr />
<h2 id="heading-step-10-testing-your-constructs-amp-injectors">Step 10: Testing Your Constructs &amp; Injectors</h2>
<p>Use the CDK assertions library to write unit tests:</p>
<p><strong>10.1 Install test dependencies</strong></p>
<pre><code class="lang-bash">npm install --save-dev jest @aws-cdk/assertions
</code></pre>
<p><strong>10.2 Example test</strong></p>
<pre><code class="lang-typescript"><span class="hljs-comment">// test/secure-bucket.test.ts</span>
<span class="hljs-keyword">import</span> { App, Stack } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib'</span>;
<span class="hljs-keyword">import</span> { Template } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib/assertions'</span>;
<span class="hljs-keyword">import</span> { SecureBucketDefaults } <span class="hljs-keyword">from</span> <span class="hljs-string">'../lib/secure-bucket-injector'</span>;
<span class="hljs-keyword">import</span> { Bucket } <span class="hljs-keyword">from</span> <span class="hljs-string">'aws-cdk-lib/aws-s3'</span>;

test(<span class="hljs-string">'SecureBucketDefaults enforces encryption &amp; block public'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> app = <span class="hljs-keyword">new</span> App({ propertyInjectors: [<span class="hljs-keyword">new</span> SecureBucketDefaults()] });
  <span class="hljs-keyword">const</span> stack = <span class="hljs-keyword">new</span> Stack(app, <span class="hljs-string">'TestStack'</span>);
  <span class="hljs-keyword">new</span> Bucket(stack, <span class="hljs-string">'TestBucket'</span>);

  <span class="hljs-keyword">const</span> tpl = Template.fromStack(stack);
  tpl.hasResourceProperties(<span class="hljs-string">'AWS::S3::Bucket'</span>, {
    BlockPublicAccessConfiguration: { BlockPublicAcls: <span class="hljs-literal">true</span> },
    BucketEncryption: { ServerSideEncryptionConfiguration: Match.anyValue() },
  });
});
</code></pre>
<p><strong>10.3. Run tests</strong></p>
<pre><code class="lang-bash">npm <span class="hljs-built_in">test</span>
</code></pre>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>You now have a full end-to-end workflow:</p>
<ol>
<li><p><strong>Install &amp; bootstrap</strong> CDK</p>
</li>
<li><p><strong>Initialize</strong> your TypeScript app</p>
</li>
<li><p><strong>Author</strong> custom injectors via CDK Blueprints</p>
</li>
<li><p><strong>Leverage jsii</strong> for multi-language support</p>
</li>
<li><p><strong>Compose</strong> multiple injectors and guard against recursion</p>
</li>
<li><p><strong>Enforce</strong> standards with cdk-nag</p>
</li>
<li><p><strong>Validate</strong> via unit tests</p>
</li>
</ol>
<p>With these patterns in place, your organisation’s security, naming, tagging, and logging standards are <strong>baked in</strong> to every CDK construct, while still letting individual teams override when and only when they need to. This gives a good segway for our next read topic that is creating custom cdk-nag.</p>
]]></content:encoded></item></channel></rss>