<?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[AI & System Design]]></title><description><![CDATA[Exploring AI, scalable systems, and modern engineering design.
Insights on building intelligent and scalable systems.
Deep dives into AI and system architecture]]></description><link>https://blog.ratishfolio.com</link><image><url>https://cdn.hashnode.com/uploads/logos/639ca8d6052fc36d4a8f42ec/9b025d45-4b52-4c90-bd45-a613aabde1fe.png</url><title>AI &amp; System Design</title><link>https://blog.ratishfolio.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 03:09:03 GMT</lastBuildDate><atom:link href="https://blog.ratishfolio.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Agentic Systems Are Just Patterns]]></title><description><![CDATA[Single Agent Patterns
Tool Use Pattern
An LLM by itself can only produce tokens. It can't query a database, hit an API, run code, or check today's weather. The tool use pattern closes that gap by givi]]></description><link>https://blog.ratishfolio.com/agentic-systems-are-just-patterns</link><guid isPermaLink="true">https://blog.ratishfolio.com/agentic-systems-are-just-patterns</guid><category><![CDATA[agentic AI]]></category><category><![CDATA[llm]]></category><category><![CDATA[AI]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sat, 22 Aug 2026 08:18:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/62775fe9-ada1-4e66-8af2-6b20db61228d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Single Agent Patterns</h2>
<h3>Tool Use Pattern</h3>
<p>An LLM by itself can only produce tokens. It can't query a database, hit an API, run code, or check today's weather. The tool use pattern closes that gap by giving the model a structured way to say "I want to call function X with these arguments" and having the surrounding system actually execute that call and feed the result back in.</p>
<p>How it works, step by step</p>
<ol>
<li><p><strong>Tool definitions are given to the model (JSON Schema) -</strong> ame, description, and a schema for expected inputs.This happens in the system prompt or a dedicated <code>tools</code> parameter.</p>
</li>
<li><p><strong>The model decides whether a tool is needed</strong> based on the user's request and the tool descriptions.</p>
</li>
<li><p><strong>The model emits a structured tool call</strong> instead of (or alongside) natural language e.g. <code>{"tool": "get_weather", "input": {"city": "Bangalore"}}</code>.</p>
</li>
<li><p><strong>The orchestrating code (not the model) executes the actual function</strong> hits the API, runs the query, etc.</p>
</li>
<li><p><strong>The result is returned to the model as a new message</strong> (a "tool result").</p>
</li>
<li><p><strong>The model incorporates that result into its next response</strong> either calling another tool or answering the user.</p>
</li>
</ol>
<p>This is fundamentally a loop: think → act → observe → think again.</p>
<h3>ReAct Pattern</h3>
<p><strong>ReAct</strong> (Reason + Act) is the pattern that interleaves the model's reasoning with tool calls, step by step, rather than doing all the thinking up front or calling a tool exactly once. It's essentially Tool Use pattern extended into a loop with explicit reasoning traces at each step.</p>
<p>Instead of "think once, then answer" or "call one tool, then answer," ReAct has the model alternate between:</p>
<ul>
<li><p><strong>Thought</strong>: reason in natural language about what it knows and what it needs next</p>
</li>
<li><p><strong>Action</strong>: call a tool based on that reasoning</p>
</li>
<li><p><strong>Observation</strong>: read the tool's result</p>
</li>
<li><p><strong>Thought</strong>: reason again, incorporating the new observation</p>
</li>
<li><p>... repeat until it has enough to answer</p>
</li>
<li><p>Final answer</p>
</li>
</ul>
<p>This loop is what lets an agent handle multi-step problems where the next action genuinely depends on what the previous action returned, you can't know what to search for next until you see what the first search turned up.</p>
<h3>Plan &amp; Execute Pattern</h3>
<p><strong>Plan &amp; Execute</strong> splits agentic work into two distinct phases: first produce a full multi-step plan, then work through it rather than deciding one step at a time the way ReAct does. It trades ReAct's adaptability for more efficient, more predictable execution.</p>
<ol>
<li><p><strong>Plan</strong>: a (usually more capable) model looks at the whole task and decomposes it into an ordered list of discrete steps upfront before any tool has been called or any information gathered.</p>
</li>
<li><p><strong>Execute</strong>: same agent executes the plan in the given steps involving tool calls etc.</p>
</li>
</ol>
<p>Incorporated in multi agent systems as well with a dedicated planner agent and execution agent</p>
<h3>Agentic RAG Pattern</h3>
<p><strong>Agentic RAG</strong> takes the standard retrieve-then-generate pipeline and gives the model control over the retrieval itself instead of a fixed "always retrieve once, then answer" flow, the model decides <em>whether</em> to retrieve, <em>what</em> to retrieve, <em>how many times</em>, and whether the results are actually good enough to answer with.</p>
<pre><code class="language-plaintext">Standard RAG (fixed pipeline):
Query → Embed → Retrieve top-k → Stuff into context → Generate answer (one shot, no judgment calls)

Agentic RAG (model-in-the-loop):
Query → Model reasons: "do I even need retrieval for this?"
→ If yes: Model decides what to search, calls retrieval asa tool
→ Model evaluates:"are these chunks actually relevant/sufficient?"                    → If not: reformulate query, retrieve again, or try a                               different source
→ Repeat until confident → Generate answer
</code></pre>
<h2>Multi Agent Patterns</h2>
<h3>Sequential Execution</h3>
<p>agents run one after another in a fixed order, each one's output becoming the next one's input - a pipeline, not a negotiation.</p>
<pre><code class="language-plaintext">Task → Agent A → Agent B → Agent C → Final Output
       (draft)   (review)  (format)
</code></pre>
<h3>Parallel Execution</h3>
<p>runs multiple agents at the same time on independent pieces of a task, then combines their outputs - a fan-out/fan-in shape.</p>
<pre><code class="language-plaintext">                ┌─→ Agent A (source 1) ─┐
Task ─ split ──┼─→ Agent B (source 2) ─┼── merge → Final Output
                └─→ Agent C (source 3) ─┘
</code></pre>
<h3>Router Pattern</h3>
<p>The <strong>Router pattern</strong> (also called Router-based orchestration or Dynamic Routing) puts a single decision-maker in front of a set of specialist agents, and sends each incoming task to whichever one fits, instead of running everyone in a fixed sequence or in parallel by default.</p>
<pre><code class="language-plaintext">                          ┌─→ Agent A (billing questions)
Task → Router (classify) ─┼─→ Agent B (technical support)
                          └─→ Agent C (account changes)
</code></pre>
<h3>Orchestrator Worker Pattern ( Manager Worker Pattern )</h3>
<p>The <strong>Orchestrator-Worker pattern</strong> (also called Manager-Worker or Hierarchical orchestration) puts a central agent in charge of a task from start to finish - it doesn't just dispatch once like Router, it keeps control, breaking the task into subtasks, assigning them to workers, checking their results, and deciding what happens next.</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/43395382-6a70-4307-80ac-3c391c129f0c.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Deploying a CrewAI Multi-Agent Crew to Amazon Bedrock AgentCore]]></title><description><![CDATA[Full source for this project: https://github.com/ratishjain12/crewai-bedrock-agentcore  
Amazon Bedrock AgentCore is AWS's answer to a problem every team building agents eventually hits: your agent wo]]></description><link>https://blog.ratishfolio.com/deploying-a-crewai-multi-agent-crew-to-amazon-bedrock-agentcore</link><guid isPermaLink="true">https://blog.ratishfolio.com/deploying-a-crewai-multi-agent-crew-to-amazon-bedrock-agentcore</guid><category><![CDATA[bedrock agentcore]]></category><category><![CDATA[agentcore]]></category><category><![CDATA[CrewAI]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sun, 16 Aug 2026 12:13:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/17f626c6-c754-4faf-915e-bb192a47e1c6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Full source for this project:</em> <a href="https://github.com/ratishjain12/crewai-bedrock-agentcore">https://github.com/ratishjain12/crewai-bedrock-agentcore</a>  </p>
<p>Amazon Bedrock AgentCore is AWS's answer to a problem every team building agents eventually hits: your agent works great on your laptop, and then you need to actually run it somewhere with scaling, session isolation, observability, and a secure invocation boundary without hand-rolling that infrastructure yourself.</p>
<p>This post walks through taking a real multi-agent <a href="https://www.crewai.com/">CrewAI</a> crew - a two-agent "Research Crew" that researches a topic and turns the findings into a report from <code>crewai run</code> on a laptop to a secured, containerized deployment on AgentCore Runtime. Every step here was actually run against a live AWS account, including the mistakes.</p>
<h2>What is Bedrock AgentCore, actually?</h2>
<p>Strip away the marketing and AgentCore is a managed runtime with one real contract: give it a container (or a zipped Python package) that speaks HTTP on port 8080 — <code>POST /invocations</code> for the actual work, <code>GET /ping</code> for health and AgentCore handles the rest: provisioning, scaling, session isolation, IAM, logging, and (optionally) JWT-based auth in front of it. It's explicitly framework-agnostic. Nothing about the contract cares whether the code behind it is Strands, LangChain, LangGraph, or in this case, CrewAI.</p>
<p>That framework-agnosticism matters here: AgentCore's own CLI ships built-in project templates for Strands, LangChain/LangGraph, GoogleADK, OpenAI Agents, and Autogen but not CrewAI. The escape hatch is a <strong>BYO (bring your own code) agent</strong>: you register a code location and an entrypoint file, and AgentCore doesn't care what's inside as long as it implements the HTTP contract.</p>
<h2>The architecture</h2>
<p>Here's what we ended up with:</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/3dbd07b6-47e5-48fe-9e97-d243cd536923.png" alt="" style="display:block;margin:0 auto" />

<p>Walking it left to right:</p>
<ul>
<li><p><strong>Client</strong> - anything calling the agent: a script, another service, <code>agentcore invoke</code>.</p>
</li>
<li><p><strong>Identity Provider (Cognito) / IAM-JWT Auth</strong> - the front door. AgentCore Runtime supports two inbound-auth modes: <code>AWS_IAM</code> (SigV4-signed requests, the default) or <code>CUSTOM_JWT</code> (bearer tokens from any OIDC-compliant issuer - Cognito here). This layer validates the request before it ever reaches your code.</p>
</li>
<li><p><strong>AgentCore Runtime → MicroVM → Docker Container → Agent Application Code</strong> - each invocation gets an isolated microVM running your container. Your code (<code>main.py</code> in this project) is the innermost layer — it never sees infrastructure concerns, just a payload in and a result out.</p>
</li>
<li><p><strong>Execution Role</strong> - the IAM role AgentCore assumes on your container's behalf, scoped to exactly what it needs.</p>
</li>
<li><p><strong>ECR</strong> - where the container image lives; the Execution Role pulls it to start the runtime.</p>
</li>
<li><p><strong>CloudWatch</strong> - logs and traces from every invocation land here automatically.</p>
</li>
<li><p><strong>Bedrock (LLM)</strong> - where the actual model calls go. The Execution Role, not the client, is what's authorized to invoke Bedrock - the client never touches AWS credentials at all.</p>
</li>
</ul>
<h2>The demo: a CrewAI Research Crew</h2>
<p>The crew is intentionally simple - two agents, sequential process:</p>
<ul>
<li><p><strong>Researcher</strong> — gathers information on a topic using <code>SerperDevTool</code> (web search), backed by <code>bedrock/apac.amazon.nova-lite-v1:0</code>.</p>
</li>
<li><p><strong>Analyst</strong> — turns the researcher's output into a structured markdown report, backed by the same model.</p>
</li>
</ul>
<p>It's defined declaratively, CrewAI's JSON-first format - <code>crew.jsonc</code> for the crew/task graph, <code>agents/researcher.jsonc</code> and <code>agents/analyst.jsonc</code> for each agent's role/goal/backstory/model/tools:</p>
<pre><code class="language-jsonc">// agents/researcher.jsonc
{
  "role": "Senior Research Specialist for {topic}",
  "goal": "Find comprehensive and accurate information about {topic}...",
  "llm": "bedrock/apac.amazon.nova-lite-v1:0",
  "tools": ["SerperDevTool"]
}
</code></pre>
<p>Locally, <code>crewai run</code> reads this straight out of <code>pyproject.toml</code>'s <code>[tool.crewai]</code> block. Neither <code>crew.jsonc</code> nor the loader cares whether you're running on a laptop or inside AgentCore - which is exactly what makes the port to a BYO agent almost mechanical.</p>
<h2>Wiring it into AgentCore</h2>
<p>A BYO agent needs exactly one thing beyond the existing project: an entrypoint that speaks the AgentCore HTTP contract. CrewAI conveniently exposes a <code>load_crew()</code> helper that does the JSON-first loading programmatically, so the entrypoint is a thin wrapper:</p>
<pre><code class="language-python"># app/ResearchAgent/main.py
from pathlib import Path
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from crewai.project.crew_loader import load_crew

app = BedrockAgentCoreApp()
CREW_PATH = Path(__file__).parent / "crew.jsonc"

@app.entrypoint
def invoke(payload, context):
    crew, default_inputs = load_crew(CREW_PATH)
    topic = payload.get("prompt", default_inputs.get("topic", ""))
    result = crew.kickoff(inputs={**default_inputs, "topic": topic})
    return {"result": result.raw}

if __name__ == "__main__":
    app.run()
</code></pre>
<p><code>BedrockAgentCoreApp</code> handles the HTTP contract (<code>/invocations</code>, <code>/ping</code>) — the crew itself doesn't know it's running inside AgentCore at all.</p>
<p>The agent is registered in <code>agentcore/agentcore.json</code> as a flat resource entry — <code>codeLocation</code>, <code>entrypoint</code>, <code>build</code> type, environment variables, and (as it turned out) auth config, all declared, not templated:</p>
<pre><code class="language-jsonc">{
  "runtimes": [{
    "name": "ResearchAgent",
    "build": "Container",
    "entrypoint": "main.py",
    "codeLocation": "app/ResearchAgent/",
    "envVars": [
      { "name": "SERPER_API_KEY", "value": "..." },
      { "name": "AWS_DEFAULT_REGION", "value": "ap-south-1" }
    ]
  }]
}
</code></pre>
<h2>Two bugs that only show up in deployment</h2>
<p>Everything above sounds clean in hindsight. It wasn't, the first time through — and both failures are worth calling out because neither is obvious from the CrewAI or AgentCore docs alone.</p>
<p><strong>1. The package was too big for a</strong> <code>CodeZip</code> <strong>build.</strong> AgentCore's default build type zips your code and its dependencies and caps the artifact at 250 MB. <code>crewai[bedrock,tools]</code> blew past that at 285 MB. The reason: the <code>tools</code> extra doesn't scope dependencies per-tool — it pulls in <code>crewai-tools</code>' <em>entire</em> dependency tree, because the package ships all ~40 tool wrappers as one unit. The researcher agent uses exactly one tool (<code>SerperDevTool</code>, a thin <code>requests</code> wrapper), but that one line in <code>pyproject.toml</code> also drags in chromadb, lancedb, pyarrow, onnxruntime, pymupdf, and kubernetes — dependencies for RAG tools and PDF tools and a Kubernetes tool we never touch. The fix was switching the runtime's <code>build</code> type from <code>CodeZip</code> to <code>Container</code> — a container image isn't subject to the 250 MB cap, so the same heavy dependency tree just... works. (The leaner fix, for anyone hitting this without wanting to move to containers, is dropping the <code>tools</code> extra and hand-writing a ten-line Serper tool against <code>requests</code> instead.)</p>
<p><strong>2. Cross-region model IDs silently picked the wrong region.</strong> The crew uses <code>bedrock/apac.amazon.nova-lite-v1:0</code> — a cross-region inference profile that only routes within APAC regions. Locally, everything worked, because the AWS CLI's default profile region was <code>ap-south-1</code>. Deployed, every invocation failed with <em>"The provided model identifier is invalid."</em> The cause: CrewAI's Bedrock LLM provider builds its own boto3 session and only checks <code>AWS_DEFAULT_REGION</code> / <code>AWS_REGION_NAME</code> env vars for region — it never falls back to <code>~/.aws/config</code> the way a bare <code>boto3.Session()</code> does. With neither env var set, it silently defaulted to <code>us-east-1</code>, where an APAC-only inference profile is, correctly, rejected. The fix was one env var — <code>AWS_DEFAULT_REGION=ap-south-1</code> — set explicitly in both <code>agentcore/.env.local</code> (for local <code>agentcore dev</code>) and the runtime's <code>envVars</code> in <code>agentcore.json</code> (for the deployed container). Two separate places, because — importantly — <code>.env.local</code> <strong>never reaches the deployed runtime.</strong> It lives outside the container's <code>codeLocation</code> and is read only by the local dev server; production env vars are a completely separate, explicit declaration.</p>
<h2>Locking down the front door: Cognito JWT auth</h2>
<p>By default, AgentCore Runtime protects invocations with IAM/SigV4 — fine for service-to-service calls already inside your AWS account, but not something you'd hand to, say, a frontend client. Swapping in JWT auth is a matter of setting two fields on the runtime:</p>
<pre><code class="language-jsonc">"authorizerType": "CUSTOM_JWT",
"authorizerConfiguration": {
  "customJwtAuthorizer": {
    "discoveryUrl": "https://cognito-idp.&lt;region&gt;.amazonaws.com/&lt;pool-id&gt;/.well-known/openid-configuration",
    "allowedClients": ["&lt;app-client-id&gt;"]
  }
}
</code></pre>
<p>The catch: AgentCore doesn't provision the identity provider for you — there's no <code>agentcore add cognito</code>. Cognito (user pool, resource server, domain, app client) is a plain AWS resource you create yourself; AgentCore's CLI only consumes the resulting discovery URL. This project's <code>scripts/cognito/</code> directory has three small scripts for exactly that lifecycle: <code>create-cognito.sh</code> provisions everything and prints the config block above; <code>get-bearer-token.sh</code> does the client-credentials token exchange for testing; <code>destroy-cognito.sh</code> tears it back down. Once <code>CUSTOM_JWT</code> is set, plain boto3 <code>invoke_agent_runtime</code> calls stop working — SigV4 signing and JWT bearer tokens are mutually exclusive per runtime, so invocation becomes a raw HTTPS <code>POST</code> with an <code>Authorization: Bearer &lt;token&gt;</code> header instead.</p>
<h2>Closing thoughts</h2>
<p>None of the individual pieces here are exotic — CrewAI's JSON-first crews, AgentCore's BYO-agent model, Cognito client-credentials grants. What's worth taking away is that the two real failures — a silent dependency bloat past a packaging limit, and a silent region fallback inside a third-party LLM provider — both looked like AgentCore problems at first and were actually one level down, in how CrewAI resolves its own dependencies and its own AWS region. Deploying an existing framework onto a new runtime surfaces exactly these kinds of assumptions the framework was making that never had to be explicit before.</p>
<hr />
<p><em>Full source for this project:</em> <a href="https://github.com/ratishjain12/crewai-bedrock-agentcore">https://github.com/ratishjain12/crewai-bedrock-agentcore</a></p>
]]></content:encoded></item><item><title><![CDATA[LLM Observability: A Technical Deep Dive]]></title><description><![CDATA[How do you debug an LLM application when the answer is wrong, latency suddenly spikes, or token costs explode?
Traditional application monitoring isn't enough. LLM applications require a new layer of ]]></description><link>https://blog.ratishfolio.com/llm-observability-a-technical-deep-dive</link><guid isPermaLink="true">https://blog.ratishfolio.com/llm-observability-a-technical-deep-dive</guid><category><![CDATA[llm]]></category><category><![CDATA[observability]]></category><category><![CDATA[OpenTelemetry]]></category><category><![CDATA[distributed system]]></category><category><![CDATA[System Design]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sun, 19 Jul 2026 11:39:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/3dda2ebd-c1f1-4cd8-bf54-85a2e0501c6c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How do you debug an LLM application when the answer is wrong, latency suddenly spikes, or token costs explode?</p>
<p>Traditional application monitoring isn't enough. LLM applications require a new layer of observability that captures prompts, model calls, agent workflows, retrieval steps, token usage, and much more.</p>
<h2>Introduction</h2>
<p>Modern LLM applications are no longer simple request-response APIs.</p>
<p>A single user query may involve:</p>
<ul>
<li><p>API Gateway</p>
</li>
<li><p>Authentication</p>
</li>
<li><p>Multiple LLM calls</p>
</li>
<li><p>Retrieval from a Vector Database</p>
</li>
<li><p>Tool execution</p>
</li>
<li><p>Agent planning</p>
</li>
<li><p>Memory lookup</p>
</li>
<li><p>Reranking</p>
</li>
<li><p>Response generation</p>
</li>
</ul>
<p>If any step fails, understanding <strong>where</strong>, <strong>why</strong>, and <strong>how</strong> becomes difficult.</p>
<p>This is exactly what <strong>LLM Observability</strong> solves.</p>
<p>Unlike traditional monitoring that focuses on CPU or HTTP latency, LLM observability helps answer questions like:</p>
<ul>
<li><p>Why did the model hallucinate?</p>
</li>
<li><p>Which retrieval step failed?</p>
</li>
<li><p>Which tool took 8 seconds?</p>
</li>
<li><p>Why did token usage suddenly double?</p>
</li>
<li><p>Which model version produced poor answers?</p>
</li>
<li><p>Where is most of the latency coming from?</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/e5970548-c7a2-40de-881d-d3c697f5bd01.png" alt="" style="display:block;margin:0 auto" />

<h2>The Three Pillars of Observability</h2>
<p>Every observability platform—whether for distributed systems or LLM applications—is built on three core pillars:</p>
<ol>
<li><p>Metrics</p>
</li>
<li><p>Logs</p>
</li>
<li><p>Traces</p>
</li>
</ol>
<p>Together they provide answers to three different questions:</p>
<table>
<thead>
<tr>
<th>Pillar</th>
<th>Answers</th>
</tr>
</thead>
<tbody><tr>
<td>Metrics</td>
<td>What is happening?</td>
</tr>
<tr>
<td>Logs</td>
<td>What exactly happened?</td>
</tr>
<tr>
<td>Traces</td>
<td>Where did it happen?</td>
</tr>
</tbody></table>
<p>Think of them as progressively increasing levels of detail.</p>
<h3>1. Metrics</h3>
<p>Metrics are numerical measurements collected over time.</p>
<p>They provide a high-level view of system health.</p>
<p>Examples in traditional systems:</p>
<ul>
<li><p>CPU utilization</p>
</li>
<li><p>Memory usage</p>
</li>
<li><p>Request latency</p>
</li>
<li><p>Error rate</p>
</li>
<li><p>Requests per second</p>
</li>
</ul>
<p>For LLM systems, metrics become even more interesting.</p>
<p>Examples:</p>
<ul>
<li><p>Prompt tokens</p>
</li>
<li><p>Completion tokens</p>
</li>
<li><p>Total cost</p>
</li>
<li><p>Requests/minute</p>
</li>
<li><p>Tool execution latency</p>
</li>
<li><p>Cache hit ratio</p>
</li>
<li><p>Retrieval latency</p>
</li>
<li><p>Hallucination rate (if measured)</p>
</li>
<li><p>User satisfaction score</p>
</li>
<li><p>Agent step count</p>
</li>
</ul>
<p>Metrics are lightweight and ideal for dashboards and alerting.</p>
<p>Example dashboard:</p>
<pre><code class="language-plaintext">Average latency: 1.8 sec

P95 latency: 3.7 sec

Average tokens/request: 1842

Error rate: 1.2%

Daily cost: $146
</code></pre>
<p>Metrics answer:</p>
<blockquote>
<p>"Is something wrong?"</p>
</blockquote>
<p>They usually <strong>do not explain why</strong></p>
<h3>2. Logs</h3>
<p>Logs are detailed records of individual events.</p>
<p>Unlike metrics, logs preserve context.</p>
<p>For an LLM application, logs might include:</p>
<pre><code class="language-plaintext">{
  "request_id": "abc123",
  "model": "gpt-4.1",
  "temperature": 0.2,
  "prompt": "...",
  "completion": "...",
  "input_tokens": 1452,
  "output_tokens": 321,
  "latency_ms": 1832
}
</code></pre>
<p>Logs help investigate questions like:</p>
<ul>
<li><p>What prompt was actually sent?</p>
</li>
<li><p>What response came back?</p>
</li>
<li><p>Which model version was used?</p>
</li>
<li><p>Which user triggered this?</p>
</li>
<li><p>Which tool failed?</p>
</li>
<li><p>What exception occurred?</p>
</li>
</ul>
<p>Good logs should be:</p>
<ul>
<li><p>Structured</p>
</li>
<li><p>Searchable</p>
</li>
<li><p>Correlated</p>
</li>
<li><p>Timestamped</p>
</li>
</ul>
<p>Prefer structured logs:</p>
<pre><code class="language-plaintext">{
 "event":"tool_execution",
 "tool":"weather_api",
 "latency":482,
 "status":"success"
}
</code></pre>
<p>Structured logs make querying much easier.</p>
<h3>3. Traces</h3>
<p>Metrics tell you <strong>something is wrong</strong>.</p>
<p>Logs tell you <strong>what happened</strong>.</p>
<p>Traces tell you <strong>where it happened</strong>.</p>
<p>Tracing follows a request from beginning to end as it travels across multiple services.</p>
<p>Imagine a user asks:</p>
<blockquote>
<p>"Summarize my quarterly sales."</p>
</blockquote>
<p>The request may flow like this:</p>
<pre><code class="language-plaintext">Gateway

↓

Authentication

↓

Planner Agent

↓

Retriever

↓

Vector Database

↓

LLM

↓

SQL Tool

↓

LLM

↓

Response
</code></pre>
<p>A trace records every one of these steps.</p>
<p>This allows engineers to identify:</p>
<ul>
<li><p>Which component was slow</p>
</li>
<li><p>Which component failed</p>
</li>
<li><p>How requests propagated</p>
</li>
<li><p>Total end-to-end latency</p>
</li>
</ul>
<p>Without traces, debugging distributed AI systems becomes guesswork.</p>
<h2>Understanding Traces and Spans</h2>
<p>Tracing revolves around two fundamental concepts:</p>
<ul>
<li><p>Trace</p>
</li>
<li><p>Span</p>
</li>
</ul>
<p>These are often confused.</p>
<p>Let's break them down.</p>
<h3>What is a Trace?</h3>
<p>A trace represents the <strong>entire lifecycle of one request</strong>.</p>
<p>One user request equals one trace.</p>
<p>Example:</p>
<pre><code class="language-plaintext">User asks:

"What were my sales this quarter?"
</code></pre>
<p>Everything that happens afterward belongs to a single trace.</p>
<pre><code class="language-plaintext">Trace

├── Authenticate

├── Retrieve documents

├── LLM call

├── SQL query

├── Final response
</code></pre>
<p>Each trace has a unique Trace ID.</p>
<p>Every service involved shares this ID.</p>
<h3>What is a Span?</h3>
<p>A span represents <strong>one operation inside a trace</strong>.</p>
<p>Think of spans as building blocks.  </p>
<p>Example:</p>
<pre><code class="language-plaintext">Trace

├── Span: API Gateway
      22 ms

├── Span: Authentication
      41 ms

├── Span: Vector Search
      182 ms

├── Span: LLM Call
      2150 ms

├── Span: SQL Query
      98 ms

├── Span: Final Formatting
      12 ms
</code></pre>
<p>Each span contains metadata such as:</p>
<ul>
<li><p>Start time</p>
</li>
<li><p>End time</p>
</li>
<li><p>Duration</p>
</li>
<li><p>Status</p>
</li>
<li><p>Attributes</p>
</li>
<li><p>Events</p>
</li>
<li><p>Parent span</p>
</li>
</ul>
<p>Because spans have parent-child relationships, the backend can reconstruct the complete execution tree</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/40ac7683-5225-4910-9a7d-62220650474c.png" alt="" style="display:block;margin:0 auto" />

<h2>OpenTelemetry (OTel)</h2>
<p>Collecting telemetry separately for every vendor quickly becomes painful.</p>
<p>Imagine rewriting instrumentation every time you move from Datadog to Grafana, or from Jaeger to another backend.</p>
<p>OpenTelemetry solves this problem.</p>
<p>OpenTelemetry (OTel) is the <strong>Cloud Native Computing Foundation (CNCF)</strong> open standard for generating, collecting, and exporting telemetry data. It is vendor-neutral and supported by most major observability platforms.</p>
<p>It standardizes three signal types:</p>
<ul>
<li><p>Metrics</p>
</li>
<li><p>Logs</p>
</li>
<li><p>Traces</p>
</li>
</ul>
<p>Instead of instrumenting your application differently for every backend, you instrument once using OpenTelemetry.</p>
<p>The backend can change later without changing application code.</p>
<p>This vendor-neutral approach prevents vendor lock-in while enabling interoperability across observability ecosystems</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/c06d43da-81ed-4711-b4be-f3e2c5ca0489.png" alt="" style="display:block;margin:0 auto" />

<h2>The OpenTelemetry Observability Pipeline</h2>
<p>One of the biggest strengths of OpenTelemetry is its decoupled architecture.</p>
<p>Instead of applications sending telemetry directly to an observability platform, data flows through a standardized pipeline.</p>
<pre><code class="language-plaintext">Application

↓

OpenTelemetry SDK

↓

OpenTelemetry Collector

↓

Observability Backend
</code></pre>
<p>Let's understand each component.</p>
<h3>1. OpenTelemetry SDK</h3>
<p>The SDK runs inside your application.</p>
<p>Its responsibilities include:</p>
<ul>
<li><p>Creating spans</p>
</li>
<li><p>Recording metrics</p>
</li>
<li><p>Capturing logs</p>
</li>
<li><p>Adding metadata</p>
</li>
<li><p>Propagating Trace IDs</p>
</li>
<li><p>Exporting telemetry</p>
</li>
</ul>
<p>Example (Python):</p>
<pre><code class="language-python">from opentelemetry import trace

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("llm_call"):
    response = client.responses.create(...)
</code></pre>
<p>The SDK should do as little processing as possible to minimize application overhead.</p>
<h3>2. OpenTelemetry Collector</h3>
<p>The Collector is the heart of the pipeline.</p>
<p>Instead of every application talking directly to Datadog, Grafana, or Jaeger, they all send telemetry to the Collector.</p>
<p>The Collector can:</p>
<ul>
<li><p>Receive telemetry from many services</p>
</li>
<li><p>Batch requests</p>
</li>
<li><p>Filter sensitive data</p>
</li>
<li><p>Enrich telemetry</p>
</li>
<li><p>Sample traces</p>
</li>
<li><p>Transform attributes</p>
</li>
<li><p>Route data to multiple destinations</p>
</li>
<li><p>Retry failed exports</p>
</li>
<li><p>Buffer during backend outages</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-plaintext">20 Services

↓

OTel Collector

↓

Grafana

↓

Jaeger

↓

S3 Archive
</code></pre>
<p>A single Collector can fan out telemetry to multiple backends simultaneously, making migrations and multi-tool deployments much easier.  </p>
<h3>3. Observability Backend</h3>
<p>The backend stores and visualizes telemetry.</p>
<p>Popular options include:</p>
<ul>
<li><p>Jaeger</p>
</li>
<li><p>Grafana Tempo</p>
</li>
<li><p>SigNoz</p>
</li>
<li><p>Datadog</p>
</li>
<li><p>Honeycomb</p>
</li>
<li><p>New Relic</p>
</li>
<li><p>Elastic Observability</p>
</li>
</ul>
<p>The backend provides:</p>
<ul>
<li><p>Search</p>
</li>
<li><p>Dashboards</p>
</li>
<li><p>Trace visualization</p>
</li>
<li><p>Service dependency graphs</p>
</li>
<li><p>Alerts</p>
</li>
<li><p>Cost analysis</p>
</li>
<li><p>Root cause analysis</p>
</li>
</ul>
<p>This is where engineers spend most of their debugging time.</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/5598535e-e0d6-44a5-b727-c82388f998fd.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Voice Agent Architectures Explained: Cascading vs Native Multimodal Pipelines]]></title><description><![CDATA[Everyone wants to build “voice agents”, but that term hides two very different architectures.
The first is the classic cascading pipeline: speech-to-text → LLM → text-to-speech, all coordinated by you]]></description><link>https://blog.ratishfolio.com/voice-agent-architectures-explained-cascading-vs-native-multimodal-pipelines</link><guid isPermaLink="true">https://blog.ratishfolio.com/voice-agent-architectures-explained-cascading-vs-native-multimodal-pipelines</guid><category><![CDATA[voice ai]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[llm]]></category><category><![CDATA[AI]]></category><category><![CDATA[Orchestration]]></category><category><![CDATA[AI Engineering]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Wed, 24 Jun 2026 12:22:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/de1b6da9-1347-476b-a41c-711ce308a8ba.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Everyone wants to build “voice agents”, but that term hides two very different architectures.</p>
<p>The first is the classic <strong>cascading pipeline</strong>: speech-to-text → LLM → text-to-speech, all coordinated by your backend.</p>
<p>The second is the newer <strong>native multimodal realtime pipeline</strong>, where the client talks almost directly to a realtime model session capable of handling speech input/output in one loop.</p>
<p>I sketched both architectures to understand the tradeoffs more clearly. In this post, I’ll break down how each pipeline works, where latency comes from, what your backend is responsible for, and when I’d choose one over the other.</p>
<h2>Why voice agent architecture matters?</h2>
<p>Building a voice agent is not just about plugging an LLM into a microphone. The architecture you choose determines:</p>
<ul>
<li><p>how fast the assistant feels</p>
</li>
<li><p>whether you can swap STT/TTS vendors independently</p>
</li>
<li><p>how easily you can add tools and business logic</p>
</li>
<li><p>how much conversational nuance the system can preserve</p>
</li>
<li><p>how much your backend stays in the critical path</p>
</li>
<li><p>how hard it is to debug latency spikes or broken turns</p>
</li>
</ul>
<p>At a high level, most production systems today fall into one of two buckets:</p>
<ol>
<li><p><strong>Cascading voice pipeline</strong><br />Separate STT, LLM, and TTS services connected by backend orchestration.</p>
</li>
<li><p><strong>Native multimodal realtime pipeline</strong><br />A realtime model session handles the conversational loop, while the backend acts more like a sidecar for auth, tools, and control.</p>
</li>
</ol>
<h2>1) Cascading voice pipeline</h2>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/d4bef901-e68a-4a6b-abf4-d15578e5b59a.png" alt="" style="display:block;margin:0 auto" />

<p>In the cascading design, the voice stack is decomposed into three separate stages:</p>
<ul>
<li><p><strong>Speech-to-Text (STT / ASR)</strong><br />Converts user audio into text</p>
</li>
<li><p><strong>LLM reasoning/generation</strong><br />Takes the transcript + context and produces a response</p>
</li>
<li><p><strong>Text-to-Speech (TTS)</strong><br />Converts the response text back into audio</p>
</li>
</ul>
<p>The backend orchestrates all three stages and sits directly in the middle of the conversation loop.</p>
<h3>High-level flow</h3>
<ol>
<li><p>The <strong>client</strong> (browser / SIP endpoint / phone integration) streams audio to the <strong>backend</strong></p>
</li>
<li><p>The backend forwards audio to an <strong>STT provider</strong></p>
</li>
<li><p>The STT system emits partial/final transcripts</p>
</li>
<li><p>The backend sends the transcript + conversation context to an <strong>LLM</strong></p>
</li>
<li><p>The LLM streams back response text</p>
</li>
<li><p>The backend forwards the generated text to a <strong>TTS provider</strong></p>
</li>
<li><p>TTS returns synthesized audio</p>
</li>
<li><p>The backend streams audio back to the client</p>
</li>
</ol>
<h2>Breaking down the components</h2>
<h3>Client</h3>
<p>The client can be:</p>
<ul>
<li><p>a browser using WebRTC/WebSocket audio streaming</p>
</li>
<li><p>a SIP/telephony system for phone calls</p>
</li>
<li><p>a mobile app streaming microphone audio</p>
</li>
</ul>
<p>Its job is simple: capture audio, send it upstream, and play audio responses back with low latency.</p>
<h3>Backend</h3>
<p>The backend is the <strong>conductor</strong> of the entire pipeline.</p>
<p>It is responsible for:</p>
<ul>
<li><p>managing websocket sessions</p>
</li>
<li><p>buffering audio chunks</p>
</li>
<li><p>forwarding audio to STT</p>
</li>
<li><p>maintaining conversation state</p>
</li>
<li><p>calling the LLM with the latest transcript + context</p>
</li>
<li><p>invoking TTS for response synthesis</p>
</li>
<li><p>streaming synthesized audio back to the client</p>
</li>
<li><p>enforcing business rules, auth, logging, and analytics</p>
</li>
</ul>
<p>In a cascading pipeline, the backend is not optional infrastructure — it is the core orchestrator.</p>
<h3>STT / ASR</h3>
<p>The STT layer converts incoming speech into text. Typical providers include:</p>
<ul>
<li><p>OpenAI Whisper / realtime transcription offerings</p>
</li>
<li><p>Azure Speech-to-Text</p>
</li>
<li><p>Deepgram</p>
</li>
<li><p>AssemblyAI</p>
</li>
<li><p>ElevenLabs speech recognition offerings where relevant</p>
</li>
</ul>
<p>This stage often also handles:</p>
<ul>
<li><p><strong>voice activity detection (VAD)</strong> — detecting when the user starts/stops speaking</p>
</li>
<li><p><strong>turn detection</strong> — deciding when the user’s utterance is “complete enough” to send to the LLM</p>
</li>
<li><p>partial transcript streaming</p>
</li>
</ul>
<h3>LLM</h3>
<p>Once the backend has a usable transcript, it calls the LLM. This is where:</p>
<ul>
<li><p>intent understanding happens</p>
</li>
<li><p>tool decisions happen</p>
</li>
<li><p>conversation memory is used</p>
</li>
<li><p>response text is generated</p>
</li>
</ul>
<p>For voice systems, teams often prefer <strong>small, fast models</strong> for the conversational path because latency matters more than perfect reasoning depth for every turn.</p>
<h3>TTS</h3>
<p>Finally, response text is synthesized into speech using providers like:</p>
<ul>
<li><p>ElevenLabs</p>
</li>
<li><p>Deepgram</p>
</li>
<li><p>AssemblyAI / others depending on the stack</p>
</li>
</ul>
<p>The backend then streams the generated audio to the client.</p>
<h2>Why teams still use cascading pipelines</h2>
<h3>Advantages</h3>
<ul>
<li><p><strong>Modular and replaceable</strong><br />You can swap Deepgram for Whisper, or ElevenLabs for another TTS provider, without redesigning the whole system.</p>
</li>
<li><p><strong>Maximum backend control</strong><br />The backend sees the transcript, the prompt, the tool calls, and the generated response. That’s valuable for compliance, debugging, analytics, and guardrails.</p>
</li>
<li><p><strong>Tool orchestration is straightforward</strong><br />Since the LLM call already goes through your backend, executing tools, calling APIs, or injecting business logic is easy to control.</p>
</li>
<li><p><strong>Best when speech is only one part of a larger workflow</strong><br />For example: contact-center agents, internal enterprise assistants, booking flows, or customer support systems with strict backend workflows.</p>
</li>
</ul>
<h3>Drawbacks</h3>
<ul>
<li><p><strong>Higher latency</strong> because STT, LLM, and TTS are separate hops</p>
</li>
<li><p><strong>Speech expressiveness can be lost</strong> when everything is collapsed into text between stages</p>
</li>
<li><p><strong>Interruption handling is harder</strong> because the system has to coordinate stop-speaking / start-speaking behavior across multiple services</p>
</li>
<li><p><strong>More moving parts</strong> means more operational complexity</p>
</li>
</ul>
<h2>2) Native multimodal realtime pipeline</h2>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/8629b4ba-56f8-498a-a855-c103de430614.png" alt="" style="display:block;margin:0 auto" />

<p>The second architecture is structurally different.</p>
<p>Instead of routing every conversational turn through separate STT → LLM → TTS services, the client establishes a <strong>direct low-latency connection to a realtime multimodal model session</strong>.</p>
<p>The backend still exists, but it no longer sits in the middle of every audio token flowing through the system. Instead, it acts more like a <strong>control plane / sideband service</strong>.</p>
<h3>High-level flow</h3>
<ol>
<li><p>The client requests an <strong>ephemeral auth token</strong> from the backend</p>
</li>
<li><p>The client uses that token to establish a <strong>direct websocket/realtime connection</strong> to the model provider</p>
</li>
<li><p>Audio/video streams directly between the client and the realtime session</p>
</li>
<li><p>The backend maintains a <strong>sideband channel</strong> to the session for:</p>
<ul>
<li><p>tool/function execution</p>
</li>
<li><p>telemetry monitoring</p>
</li>
<li><p>session updates / injected instructions</p>
</li>
<li><p>business logic hooks</p>
</li>
</ul>
</li>
</ol>
<p>This changes the role of the backend significantly.</p>
<h2>Breaking down the components</h2>
<h3>Client</h3>
<p>In the native multimodal setup, the client becomes much more important.</p>
<p>It is responsible for:</p>
<ul>
<li><p>establishing the realtime connection</p>
</li>
<li><p>sending live audio (and sometimes video)</p>
</li>
<li><p>receiving streamed speech responses directly from the model session</p>
</li>
<li><p>handling interruptions and playback state on the client side</p>
</li>
</ul>
<p>Because the client is closer to the model, the interaction can feel more conversational and immediate.</p>
<h3>Backend</h3>
<p>The backend does <strong>not</strong> disappear. It just moves out of the direct audio path.</p>
<p>Its responsibilities now shift toward:</p>
<ul>
<li><p>minting <strong>ephemeral session/auth tokens</strong></p>
</li>
<li><p>maintaining a <strong>sideband websocket / control channel</strong></p>
</li>
<li><p>intercepting and executing <strong>tool calls</strong></p>
</li>
<li><p>injecting dynamic instructions or policy updates</p>
</li>
<li><p>collecting telemetry, usage, and observability data</p>
</li>
<li><p>enforcing app-specific business rules</p>
</li>
</ul>
<p>This is a crucial mindset shift:</p>
<blockquote>
<p>In a cascading pipeline, the backend is the <strong>conversation orchestrator</strong>.<br />In a realtime multimodal pipeline, the backend is often the <strong>session controller and tool executor</strong>.</p>
</blockquote>
<h3>Realtime multimodal model session</h3>
<p>The model session now handles much more of the conversational loop natively:</p>
<ul>
<li><p>streaming speech input</p>
</li>
<li><p>turn-taking behavior</p>
</li>
<li><p>response generation</p>
</li>
<li><p>speech output</p>
</li>
<li><p>sometimes multimodal context like audio + text + image/video</p>
</li>
</ul>
<p>Instead of manually chaining STT + LLM + TTS, you’re delegating that conversational stack to the model provider.</p>
<h3></h3>
<p>Why the native multimodal pipeline feels faster</p>
<p>The biggest architectural win is that the system removes multiple explicit stages from the critical path.</p>
<p>Instead of:</p>
<p><strong>client → backend → STT → backend → LLM → backend → TTS → backend → client</strong></p>
<p>you get something closer to:</p>
<p><strong>client ↔ realtime model session</strong></p>
<p>with the backend participating only when needed.</p>
<p>That reduces:</p>
<ul>
<li><p>extra network hops</p>
</li>
<li><p>orchestration overhead</p>
</li>
<li><p>cross-service coordination delays</p>
</li>
</ul>
<p>It also enables more natural interaction patterns like:</p>
<ul>
<li><p>faster interruptions / barge-in</p>
</li>
<li><p>lower response latency</p>
</li>
<li><p>smoother turn-taking</p>
</li>
<li><p>tighter speech-to-speech conversational flow</p>
</li>
</ul>
<h3>When I’d choose each architecture</h3>
<p><strong>I’d choose a cascading pipeline when…</strong></p>
<ul>
<li><p>I need <strong>full control</strong> over the stack</p>
</li>
<li><p>I want to independently choose the best STT, LLM, and TTS vendors</p>
</li>
<li><p>tool execution and business workflows are central to the product</p>
</li>
<li><p>I’m building for <strong>enterprise / contact-center / workflow-heavy</strong> use cases</p>
</li>
<li><p>I need strong logging, auditability, and stage-by-stage debugging</p>
</li>
</ul>
<p><strong>I’d choose a native multimodal realtime pipeline when…</strong></p>
<ul>
<li><p>the core product value is <strong>real-time conversation quality</strong></p>
</li>
<li><p>low latency is the top priority</p>
</li>
<li><p>I want more natural interruptions and turn-taking</p>
</li>
<li><p>I’m building a <strong>voice assistant, AI tutor, interviewer, sales caller, or realtime support agent</strong></p>
</li>
<li><p>I’m comfortable delegating more of the speech loop to the model provider</p>
</li>
</ul>
<p>If I had to summarize the tradeoff in one line:</p>
<ul>
<li><p><strong>Cascading pipeline = control and composability (flexibility, low cost)</strong></p>
</li>
<li><p><strong>Native multimodal pipeline = speed and conversational fluidity (less flexible, high cost, low latency than cascading pipeline)</strong></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[If You Want to Become an AI Engineer, Learn These Concepts First]]></title><description><![CDATA[Introduction
Artificial Intelligence is evolving faster than ever. Just a few years ago, building AI applications meant training machine learning models from scratch and deploying them with complex in]]></description><link>https://blog.ratishfolio.com/if-you-want-to-become-an-ai-engineer-learn-these-concepts-first</link><guid isPermaLink="true">https://blog.ratishfolio.com/if-you-want-to-become-an-ai-engineer-learn-these-concepts-first</guid><category><![CDATA[AI]]></category><category><![CDATA[System Design]]></category><category><![CDATA[AI Engineering]]></category><category><![CDATA[llm]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[mcp]]></category><category><![CDATA[RAG ]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Fri, 15 May 2026 10:49:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/9271b205-aa29-44a8-b194-dda1b5a10d8d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Introduction</h3>
<p>Artificial Intelligence is evolving faster than ever. Just a few years ago, building AI applications meant training machine learning models from scratch and deploying them with complex infrastructure. Today, developers can build powerful AI systems using Large Language Models (LLMs), retrieval pipelines, vector databases, memory systems, and autonomous agents - all working together as a modern AI stack.</p>
<p>But there’s a problem.</p>
<p>Most aspiring AI engineers jump directly into prompting tools like ChatGPT or Claude without understanding the core concepts that power modern AI applications. As a result, they can use AI tools, but struggle to design reliable, scalable, and production-ready AI systems.</p>
<p>This blog is designed to bridge that gap.</p>
<p>In this guide, we’ll explore the foundational concepts every modern AI engineer should understand - including LLMs, RAG (Retrieval-Augmented Generation), MCP, fine-tuning, vector databases, memory systems, AI agents, and agentic workflows.</p>
<p>Rather than treating these as isolated buzzwords, we’ll understand how they connect together to form real-world AI architectures used in products like ChatGPT, Cursor, Perplexity, Claude, and modern AI copilots.</p>
<p>By the end of this blog, you’ll have:</p>
<ul>
<li><p>A strong mental model of the modern AI stack</p>
</li>
<li><p>Clarity on how different AI components interact</p>
</li>
<li><p>Practical understanding of real-world AI architectures</p>
</li>
<li><p>A roadmap for building production-grade AI applications</p>
</li>
</ul>
<p>Whether you’re an aspiring AI engineer, developer, student, or builder exploring the future of AI systems, this guide will help you understand the technologies shaping the next generation of software.</p>
<h3>Understanding Large Language Models (LLMs)</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/f498ed78-ca36-4b1f-9f42-6774b39e4f5c.png" alt="" style="display:block;margin:0 auto" />

<p>Large Language Models (LLMs) are the foundation of modern AI applications. Tools like OpenAI ChatGPT, Anthropic Claude, and Google Gemini are all powered by LLMs trained on massive amounts of text data.</p>
<p>At their core, LLMs are prediction engines.</p>
<p>They learn patterns from enormous datasets and generate text by predicting the most probable next token in a sequence. A token can be a word, subword, punctuation mark, or even part of a sentence depending on the tokenizer being used.</p>
<p>For example, given the sentence:</p>
<blockquote>
<p>“Artificial Intelligence is transforming…”</p>
</blockquote>
<p>the model predicts what token is most likely to come next based on everything it learned during training.</p>
<h3>The Transformer Architecture</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/31da9d2f-826b-45c1-84c2-486402fa7800.png" alt="" style="display:block;margin:0 auto" />

<p>Modern LLMs are primarily built on the Transformer architecture introduced in the 2017 paper:</p>
<blockquote>
<p>Attention Is All You Need</p>
</blockquote>
<p>The Transformer fundamentally changed AI by making it possible for models to understand relationships between words and context much more effectively than previous architectures like RNNs or LSTMs.</p>
<p>The key innovation behind Transformers is <strong>self-attention</strong>.</p>
<p>Self-attention allows the model to determine which words in a sentence are important relative to each other.</p>
<p>For example, in the sentence:</p>
<blockquote>
<p>“The animal didn’t cross the street because it was too tired.”</p>
</blockquote>
<p>the model understands that “it” refers to “the animal” rather than “the street.”</p>
<h3>Tokens, Context Windows, and Parameters</h3>
<p>To understand how LLMs work in practice, three concepts are extremely important:</p>
<p><strong>Tokens</strong></p>
<p>LLMs do not process raw sentences directly. They process tokens.</p>
<p>For example:</p>
<ul>
<li><p>“ChatGPT is amazing” may become multiple tokens</p>
</li>
<li><p>Longer prompts consume more tokens</p>
</li>
<li><p>Input + output tokens contribute to cost and latency</p>
</li>
</ul>
<p>This is why token optimization matters in production AI systems.</p>
<p><strong>Context Window</strong></p>
<p>The context window defines how much information the model can “remember” during a conversation or task.</p>
<p>A larger context window allows the model to:</p>
<ul>
<li><p>Analyze larger documents</p>
</li>
<li><p>Maintain longer conversations</p>
</li>
<li><p>Work with more instructions simultaneously</p>
</li>
</ul>
<p>However, larger context windows also increase compute cost and latency.</p>
<p><strong>Parameters</strong></p>
<p>Parameters are the learned weights inside the model.</p>
<p>In general:</p>
<ul>
<li><p>More parameters → greater capability</p>
</li>
<li><p>But also → higher infrastructure requirements</p>
</li>
</ul>
<p>Modern frontier models contain billions or even trillions of parameters trained across massive GPU clusters.</p>
<h3>Training vs Inference</h3>
<p>LLMs operate in two major phases:</p>
<p><strong>Pretraining</strong></p>
<p>During pretraining, the model learns language patterns from massive datasets collected from books, websites, codebases, research papers, and other sources.</p>
<p>This phase is extremely compute-intensive and can cost millions of dollars.</p>
<p><strong>Inference</strong></p>
<p>Inference happens when users interact with the model after training is complete.</p>
<p>Every time you send a prompt to ChatGPT or Claude, the model performs inference to generate a response.</p>
<p>Most AI engineers today focus more on inference applications rather than training foundational models from scratch.</p>
<h3>Why LLMs Changed Software Forever</h3>
<p>Traditional software behaves deterministically:</p>
<ul>
<li>Same input → same output</li>
</ul>
<p>LLMs behave probabilistically:</p>
<ul>
<li><p>Same input can generate different outputs</p>
</li>
<li><p>Responses are context-dependent</p>
</li>
<li><p>Systems become more flexible and adaptive</p>
</li>
</ul>
<p>Instead of hardcoding every rule manually, developers can now build systems where language itself becomes the interface.</p>
<p>That is why modern AI engineering is less about building isolated models and more about orchestrating intelligent systems around LLMs.</p>
<p>And this is where concepts like RAG, vector databases, memory systems, and AI agents become critically important.</p>
<h3>Retrieval-Augmented Generation (RAG)</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/64a236c0-fcbc-48e7-9ac2-391c277e5496.png" alt="" style="display:block;margin:0 auto" />

<p>One of the biggest limitations of Large Language Models is that they do not truly “know” real-time or private information.</p>
<p>An LLM only knows what it learned during training. This creates several problems:</p>
<ul>
<li><p>Knowledge becomes outdated (Knowledge Cut-off)</p>
</li>
<li><p>Models hallucinate facts</p>
</li>
<li><p>Private company data cannot be accessed directly</p>
</li>
<li><p>Responses may lack domain-specific accuracy</p>
</li>
</ul>
<p>This is where <strong>Retrieval-Augmented Generation (RAG)</strong> becomes extremely important.</p>
<p>RAG is an architecture pattern that enhances LLMs by retrieving relevant external information before generating a response.</p>
<p>Instead of relying only on what the model memorized during training, the system dynamically fetches relevant context from external sources such as:</p>
<ul>
<li><p>PDFs</p>
</li>
<li><p>Documentation</p>
</li>
<li><p>Databases</p>
</li>
<li><p>Notion pages</p>
</li>
<li><p>Internal company knowledge bases</p>
</li>
<li><p>APIs</p>
</li>
<li><p>Websites</p>
</li>
</ul>
<p>The retrieved information is then injected into the prompt so the LLM can generate more accurate and grounded responses.</p>
<h3>How RAG Works</h3>
<p>A typical RAG pipeline consists of three major stages:</p>
<p><strong>1. Indexing Knowledge</strong></p>
<p>Before retrieval can happen, documents must first be processed and stored.</p>
<p>This usually involves:</p>
<ul>
<li><p>Splitting documents into chunks</p>
</li>
<li><p>Generating embeddings for each chunk</p>
</li>
<li><p>Storing embeddings inside a vector database</p>
</li>
</ul>
<p>For example:</p>
<ul>
<li><p>A 200-page PDF might be split into hundreds of smaller chunks</p>
</li>
<li><p>Each chunk is converted into a numerical representation (embedding)</p>
</li>
<li><p>These embeddings allow semantic search instead of keyword-only matching</p>
</li>
</ul>
<p><strong>2. Retrieval</strong></p>
<p>When a user sends a query:</p>
<ul>
<li><p>The query itself is converted into an embedding</p>
</li>
<li><p>The system searches for semantically similar chunks</p>
</li>
<li><p>Relevant information is retrieved from the vector database</p>
</li>
</ul>
<p>Unlike traditional search systems, semantic retrieval understands meaning rather than exact keywords.</p>
<p>For example:</p>
<ul>
<li><p>“How do I deploy this application?”</p>
</li>
<li><p>“How can I host this project?”</p>
</li>
</ul>
<p>Both queries may retrieve similar documents even though the wording is different.</p>
<p><strong>3. Generation</strong></p>
<p>The retrieved context is appended to the user’s prompt before sending it to the LLM.</p>
<p>The model now generates responses grounded in external information rather than relying purely on memorized knowledge.</p>
<p>This dramatically improves:</p>
<ul>
<li><p>Accuracy</p>
</li>
<li><p>Freshness</p>
</li>
<li><p>Reliability</p>
</li>
<li><p>Personalization</p>
</li>
</ul>
<p><strong>Sparse Retrieval vs Dense Retrieval</strong></p>
<p>There are two major retrieval approaches commonly used in RAG systems.</p>
<p><strong>Sparse Retrieval</strong></p>
<p>Traditional methods like BM25 rely on keyword matching.</p>
<p>Advantages:</p>
<ul>
<li><p>Fast</p>
</li>
<li><p>Interpretable</p>
</li>
<li><p>Good for exact terms</p>
</li>
</ul>
<p>Disadvantages:</p>
<ul>
<li><p>Weak semantic understanding</p>
</li>
<li><p>Struggles with paraphrased queries</p>
</li>
</ul>
<p><strong>Dense Retrieval</strong></p>
<p>Dense retrieval uses embeddings generated by transformer models.</p>
<p>Advantages:</p>
<ul>
<li><p>Understands semantic meaning</p>
</li>
<li><p>Better contextual matching</p>
</li>
<li><p>More flexible retrieval</p>
</li>
</ul>
<p>Disadvantages:</p>
<ul>
<li><p>Higher infrastructure cost</p>
</li>
<li><p>Requires vector databases</p>
</li>
</ul>
<p>Most modern AI applications use dense retrieval or hybrid approaches combining both methods.</p>
<h3>Challenges in Building Good RAG Systems</h3>
<p>Although RAG sounds simple conceptually, building high-quality RAG systems is surprisingly difficult.</p>
<p>Some common engineering challenges include:</p>
<p><strong>Chunking Strategy</strong></p>
<p>Chunks that are too small lose context.<br />Chunks that are too large reduce retrieval precision.</p>
<p><strong>Retrieval Quality</strong></p>
<p>Poor retrieval leads to poor generation.</p>
<p>Even the best LLM cannot answer correctly if irrelevant context is retrieved.</p>
<p><strong>Latency</strong></p>
<p>RAG pipelines introduce additional retrieval steps before generation.</p>
<p>This increases response time.</p>
<p><strong>Context Window Limits</strong></p>
<p>Too much retrieved context can overwhelm the model and reduce answer quality.</p>
<p><strong>Data Freshness</strong></p>
<p>Knowledge bases must be updated continuously to keep information relevant.</p>
<h3>What is a Vector Database?</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/b1c80ae5-c1e1-4b65-afe7-28a55c45e458.png" alt="" style="display:block;margin:0 auto" />

<p>A vector database is a system designed to store and retrieve embeddings efficiently.</p>
<p>Instead of performing exact-match queries like traditional SQL databases, vector databases perform <strong>similarity search</strong>.</p>
<p>This allows AI systems to retrieve semantically relevant information extremely quickly.</p>
<p>Popular vector databases include:</p>
<ul>
<li><p>Pinecone Pinecone</p>
</li>
<li><p>FAISS FAISS</p>
</li>
<li><p>Chroma Chroma</p>
</li>
<li><p>Milvus Milvus</p>
</li>
</ul>
<p>These systems are commonly used in:</p>
<ul>
<li><p>RAG pipelines</p>
</li>
<li><p>AI search engines</p>
</li>
<li><p>Recommendation systems</p>
</li>
<li><p>AI assistants</p>
</li>
<li><p>Memory systems for agents</p>
</li>
</ul>
<h3>Why Embeddings Matter</h3>
<p>Embeddings are one of the most important building blocks in modern AI engineering because they allow machines to understand semantic relationships between data.</p>
<p>They power capabilities such as:</p>
<ul>
<li><p>Semantic search</p>
</li>
<li><p>Document retrieval</p>
</li>
<li><p>Recommendation engines</p>
</li>
<li><p>Context-aware AI systems</p>
</li>
<li><p>Personalized AI experiences</p>
</li>
</ul>
<p>Without embeddings, most modern RAG and AI memory systems would not work effectively.</p>
<h3>Fine-Tuning and Model Adaptation</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/4cd163e9-9474-4355-a9e5-05d6e2a69e63.png" alt="" style="display:block;margin:0 auto" />

<p>Although modern LLMs are incredibly capable out of the box, they are still general-purpose models.</p>
<p>In real-world applications, organizations often need models to:</p>
<ul>
<li><p>Understand domain-specific knowledge</p>
</li>
<li><p>Follow custom response styles</p>
</li>
<li><p>Perform specialized tasks</p>
</li>
<li><p>Adapt to internal workflows</p>
</li>
</ul>
<p>This is where fine-tuning becomes important.</p>
<p>Fine-tuning is the process of adapting a pretrained model using additional training data for a specific use case.</p>
<p>Instead of training a model from scratch, developers build on top of an already capable foundation model.</p>
<p><strong>Full Fine-Tuning vs Efficient Adaptation</strong></p>
<p>Training all model parameters is extremely expensive.</p>
<p>Because of this, modern AI systems often use more efficient adaptation techniques instead of full retraining.</p>
<p>Popular approaches include:</p>
<ul>
<li><p>LoRA (Low-Rank Adaptation)</p>
</li>
<li><p>Adapters</p>
</li>
<li><p>Prompt tuning</p>
</li>
<li><p>Instruction tuning</p>
</li>
</ul>
<p>These methods reduce compute cost while still enabling strong customization.</p>
<p><strong>Fine-Tuning vs RAG</strong></p>
<p>One of the most common misconceptions in AI engineering is confusing RAG with fine-tuning.</p>
<p>They solve different problems.</p>
<p><strong>RAG is used for:</strong></p>
<ul>
<li><p>Injecting external knowledge</p>
</li>
<li><p>Accessing real-time information</p>
</li>
<li><p>Retrieving private documents</p>
</li>
<li><p>Improving factual grounding</p>
</li>
</ul>
<p><strong>Fine-tuning is used for:</strong></p>
<ul>
<li><p>Changing model behavior</p>
</li>
<li><p>Improving formatting/style</p>
</li>
<li><p>Specializing tasks</p>
</li>
<li><p>Adapting workflows</p>
</li>
</ul>
<p>A good rule of thumb:</p>
<blockquote>
<p>Use RAG for knowledge.<br />Use fine-tuning for behavior.</p>
</blockquote>
<p>Many production AI systems combine both approaches together.</p>
<p><strong>Challenges of Fine-Tuning</strong></p>
<p>Fine-tuning is powerful, but it also introduces challenges.</p>
<p><strong>1. Data Quality</strong></p>
<p>Poor training data leads to poor model behavior.</p>
<p><strong>2. Overfitting</strong></p>
<p>Models may become too specialized and lose general capability.</p>
<p><strong>3. Cost</strong></p>
<p>Training and hosting customized models can become expensive.</p>
<p><strong>4. Evaluation</strong></p>
<p>Testing AI systems reliably is still a major engineering challenge.</p>
<p>This is why many teams first optimize prompting and RAG pipelines before moving to fine-tuning.</p>
<h3>Memory in AI Systems</h3>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/89e75dad-3529-4845-9b62-0fad3b2cf880.png" alt="" style="display:block;margin:0 auto" />

<p>One of the biggest limitations of traditional LLM interactions is that conversations are often stateless.</p>
<p>The model may respond intelligently within a session, but once the context window is gone, the information disappears.</p>
<p>This creates an important challenge:</p>
<blockquote>
<p>How can AI systems remember useful information over time?</p>
</blockquote>
<p>This is where memory systems become essential in modern AI applications.</p>
<p><strong>Short-Term vs Long-Term Memory</strong></p>
<p>AI memory is commonly divided into two categories.</p>
<p><strong>Short-Term Memory</strong></p>
<p>Short-term memory exists inside the model’s context window.</p>
<p>This includes:</p>
<ul>
<li><p>Current conversation history</p>
</li>
<li><p>Instructions</p>
</li>
<li><p>Retrieved documents</p>
</li>
<li><p>Temporary context</p>
</li>
</ul>
<p>The limitation is that context windows are finite.</p>
<p>Once the limit is exceeded, older information is removed.</p>
<p><strong>Long-Term Memory</strong></p>
<p>Long-term memory persists information outside the model itself.</p>
<p>This memory is usually stored using:</p>
<ul>
<li><p>Vector databases</p>
</li>
<li><p>Structured databases</p>
</li>
<li><p>Knowledge graphs</p>
</li>
<li><p>External storage systems</p>
</li>
</ul>
<p>The system can later retrieve this information when needed.</p>
<p>Examples include:</p>
<ul>
<li><p>Remembering user preferences</p>
</li>
<li><p>Past conversations</p>
</li>
<li><p>Personalized recommendations</p>
</li>
<li><p>Workflow history</p>
</li>
<li><p>Project context</p>
</li>
</ul>
<p><strong>How AI Memory Works in Practice</strong></p>
<p>Most memory systems follow a simple pattern:</p>
<ol>
<li><p>Store important interactions externally</p>
</li>
<li><p>Convert them into embeddings</p>
</li>
<li><p>Retrieve relevant memories during future interactions</p>
</li>
<li><p>Inject them back into the prompt</p>
</li>
</ol>
<p>This allows AI systems to behave more consistently and contextually over time.</p>
<p>In many ways, memory systems are an extension of RAG architectures.</p>
<h3>What is Agentic AI?</h3>
<p>Agentic AI refers to AI systems capable of acting more autonomously toward goals rather than waiting for step-by-step human instructions.</p>
<p>Traditional AI:</p>
<ul>
<li>Responds to prompts</li>
</ul>
<p>Agentic AI:</p>
<ul>
<li><p>Plans</p>
</li>
<li><p>Decides</p>
</li>
<li><p>Iterates</p>
</li>
<li><p>Executes workflows</p>
</li>
</ul>
<p>This is a major shift in how software is being designed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/639ca8d6052fc36d4a8f42ec/d3db3d60-1653-4284-b91f-cffd6182e54d.png" alt="" style="display:block;margin:0 auto" />

<h3>MCP (Model Context Protocol)</h3>
<p>As AI systems become more connected to external tools, one major challenge starts to appear:</p>
<blockquote>
<p>How can LLMs securely and reliably interact with different applications, databases, and services?</p>
</blockquote>
<p>Every tool traditionally required:</p>
<ul>
<li><p>Custom integrations</p>
</li>
<li><p>Separate APIs</p>
</li>
<li><p>Manual authentication logic</p>
</li>
<li><p>Tool-specific implementations</p>
</li>
</ul>
<p>This quickly becomes difficult to scale.</p>
<p>This is where the <strong>Model Context Protocol (MCP)</strong> becomes important.</p>
<p>MCP is an open protocol designed to standardize how AI models communicate with external tools, data sources, and applications.</p>
<p>Instead of building custom integrations for every system individually, MCP creates a common interface between AI systems and external resources.</p>
<p>You can think of MCP as:</p>
<blockquote>
<p>“USB-C for AI applications.”</p>
</blockquote>
<p><strong>How MCP Works</strong></p>
<p>At a high level, MCP introduces a standardized communication layer between:</p>
<ul>
<li><p>AI models</p>
</li>
<li><p>Tools</p>
</li>
<li><p>External applications</p>
</li>
</ul>
<p>An MCP-compatible system can expose:</p>
<ul>
<li><p>Tools</p>
</li>
<li><p>Resources</p>
</li>
<li><p>Context</p>
</li>
<li><p>Actions</p>
</li>
</ul>
<p>to an AI model in a structured way.</p>
<p>Instead of hardcoding integrations directly into the application, tools become dynamically discoverable and reusable.</p>
<p>For example, an AI assistant could:</p>
<ul>
<li><p>Access files from a filesystem</p>
</li>
<li><p>Query a database</p>
</li>
<li><p>Use GitHub tools</p>
</li>
<li><p>Interact with cloud infrastructure</p>
</li>
<li><p>Read documentation</p>
</li>
</ul>
<p>all through a standardized protocol.</p>
<h3>MCP and AI Agents</h3>
<p>MCP becomes especially powerful when combined with AI agents.</p>
<p>Agents require access to:</p>
<ul>
<li><p>Context</p>
</li>
<li><p>Memory</p>
</li>
<li><p>External tools</p>
</li>
<li><p>Execution environments</p>
</li>
</ul>
<p>MCP provides a cleaner and more scalable way to manage these interactions.</p>
<p>Rather than building isolated agent architectures for every application, developers can build reusable ecosystems of tools that AI systems can access dynamically.</p>
<p>This is one of the reasons MCP is gaining significant attention in the AI ecosystem.</p>
<h3>A Simple Mental Model of Modern AI Systems</h3>
<p>A modern AI application often looks something like this:</p>
<ul>
<li><p><strong>LLM</strong> → reasoning engine</p>
</li>
<li><p><strong>RAG</strong> → retrieves external knowledge</p>
</li>
<li><p><strong>Vector Database</strong> → stores semantic embeddings</p>
</li>
<li><p><strong>Memory System</strong> → maintains context over time</p>
</li>
<li><p><strong>Fine-Tuning</strong> → adapts behavior for specific tasks</p>
</li>
<li><p><strong>MCP / Tools</strong> → connects external systems and APIs</p>
</li>
<li><p><strong>AI Agent Layer</strong> → orchestrates actions and workflows</p>
</li>
</ul>
<p>Instead of relying on a single model, modern AI systems combine multiple layers working together.</p>
<p>This shift is transforming AI from:</p>
<ul>
<li>Simple chat interfaces</li>
</ul>
<p>into:</p>
<ul>
<li>Autonomous, context-aware software systems</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Implement Api Rate Limiting with Upstash Redis in your Next.js project]]></title><description><![CDATA[What is Rate Limiting?
Suppose you have a application where a user can post his picture, for this action you are calling an api endpoint running on a server and the endpoint stores the post in the database.
Now lets say the user posting the picture s...]]></description><link>https://blog.ratishfolio.com/implement-api-rate-limiting-with-upstash-redis-in-your-nextjs-project</link><guid isPermaLink="true">https://blog.ratishfolio.com/implement-api-rate-limiting-with-upstash-redis-in-your-nextjs-project</guid><category><![CDATA[ratelimit]]></category><category><![CDATA[Redis]]></category><category><![CDATA[Upstash]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Server side rendering]]></category><category><![CDATA[server]]></category><category><![CDATA[coding]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sun, 28 Jul 2024 03:30:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722108427757/5867839e-20ce-4cf8-a3aa-6e1528c30761.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722103968241/f8424f71-ed55-4a2e-8574-96784015727f.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-what-is-rate-limiting">What is Rate Limiting?</h2>
<p>Suppose you have a application where a user can post his picture, for this action you are calling an api endpoint running on a server and the endpoint stores the post in the database.</p>
<p>Now lets say the user posting the picture spams the post button and the server recieves thousands of requests per second, potentially overwhelming the server and causing it to crash or become unresponsive for other users.</p>
<p>To avoid the above scenario Rate Limiting is used!!</p>
<h2 id="heading-setup">Setup</h2>
<p>Create a boilerplate Next.js project using:</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>Install @<strong>upstash/redis</strong> and @<strong>upstash/ratelimit</strong> using:</p>
<pre><code class="lang-bash">npm i @upstash/redis @upstash/ratelimit
</code></pre>
<p>docs - <a target="_blank" href="https://upstash.com/blog/upstash-ratelimit">https://upstash.com/blog/upstash-ratelimit</a></p>
<h2 id="heading-implementation-of-rate-limiting">Implementation of rate limiting</h2>
<p>Since we are using nextjs the demonstration of implementation will be using server actions.</p>
<p>so, go ahead create a folder of actions and creates a server action which posts a picture or content to the database(Highly suggest prisma or drizzle for this).</p>
<p>After creating the server action follow the following steps:</p>
<ul>
<li><p>create a config folder and inside it create upstash.ts file with the following code</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">import</span> { Redis } <span class="hljs-keyword">from</span> <span class="hljs-string">"@upstash/redis"</span>

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> redis = <span class="hljs-keyword">new</span> Redis({
      <span class="hljs-comment">// get these credentials by creating account on upstash</span>
      url: <span class="hljs-string">`enter your upstash db url here`</span> 
      token: <span class="hljs-string">`enter you db token here`</span>
  });
</code></pre>
</li>
<li><p>Now inside your server actions file, where the action for posting is created we'll use upstash/ratelimit by doing the following:</p>
<pre><code class="lang-typescript">  <span class="hljs-string">"use server"</span>;
  <span class="hljs-keyword">import</span> { Ratelimit } <span class="hljs-keyword">from</span> <span class="hljs-string">'@upstash/ratelimit'</span>;
  <span class="hljs-keyword">import</span> { redis } <span class="hljs-keyword">from</span> <span class="hljs-string">'./upstash'</span>; <span class="hljs-comment">// the file that you created above</span>
  <span class="hljs-keyword">import</span> { headers } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/headers'</span>;

  <span class="hljs-keyword">const</span> ratelimit = <span class="hljs-keyword">new</span> Ratelimit({
      redis,
      limiter: Ratelimit.slidingWindow(<span class="hljs-number">5</span>,<span class="hljs-string">"120s"</span>); 
      <span class="hljs-comment">//this means 5 requests is allowed per 120 seconds</span>
  });

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addPost = <span class="hljs-keyword">async</span> () =&gt; { <span class="hljs-comment">// your server action</span>
      <span class="hljs-keyword">const</span> ip = headers().get(<span class="hljs-string">'x-forwarded-for'</span>); <span class="hljs-comment">//getting user's ip </span>
      <span class="hljs-keyword">const</span> {remaining, limit, success} = <span class="hljs-keyword">await</span> ratelimit.limit(ip!);
      <span class="hljs-built_in">console</span>.log(limit) <span class="hljs-comment">// shows max limit</span>
      <span class="hljs-built_in">console</span>.log(remaining) <span class="hljs-comment">// shows remaining requests in the window</span>
      <span class="hljs-built_in">console</span>.log(success) <span class="hljs-comment">// returns if able to process the request</span>

      <span class="hljs-comment">// so to implement rate limit we need to use simple if condition</span>
      <span class="hljs-keyword">if</span>(!success){
          <span class="hljs-keyword">return</span> <span class="hljs-string">"unable to process the request, limit reached wait for 2 minutes"</span>;
      }

      <span class="hljs-comment">//rest of the addPost logic should be here dealing with the database</span>
  }
</code></pre>
</li>
</ul>
<p>Note: Here we are using rate limiting which uses sliding window technique and there are many more types of rate limiting to know about them check out the following link:</p>
<p>types of rate limiting: <a target="_blank" href="https://www.imperva.com/learn/application-security/rate-limiting/">https://www.imperva.com/learn/application-security/rate-limiting/</a></p>
<p>There you go!! now you know how to implement rate limiting in your large scale projects very easily without any headache.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering API Development with the FastAPI Framework]]></title><description><![CDATA[Let's Lean How to setup FastAPI

Install Python: If you don't have Python installed on your system, you can download it from the official Python website (https://www.python.org/downloads/).

Create a Virtual Environment: It's recommended to create a ...]]></description><link>https://blog.ratishfolio.com/mastering-api-development-with-the-fastapi-framework</link><guid isPermaLink="true">https://blog.ratishfolio.com/mastering-api-development-with-the-fastapi-framework</guid><category><![CDATA[APIs]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[server]]></category><category><![CDATA[client]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sun, 07 Apr 2024 09:41:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712482713948/6001d710-bd16-428d-a0ee-43ff41b8a475.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-lets-lean-how-to-setup-fastapi">Let's Lean How to setup FastAPI</h3>
<ul>
<li><p><strong>Install Python</strong>: If you don't have Python installed on your system, you can download it from the official Python website (<a target="_blank" href="https://www.python.org/downloads/">https://www.python.org/downloads/</a>).</p>
</li>
<li><p><strong>Create a Virtual Environment</strong>: It's recommended to create a virtual environment for your FastAPI project to keep your dependencies isolated. You can use the built-in <code>venv</code> module in Python to create a virtual environment</p>
<pre><code class="lang-bash">  python -m venv myenv
</code></pre>
</li>
<li><p><strong>Install FastAPI</strong>: With the virtual environment activated, install FastAPI and its dependencies using pip:</p>
<pre><code class="lang-bash">  pip install fastapi uvicorn
</code></pre>
</li>
<li><p><strong>Create a FastAPI Application</strong>: Create a new Python file (e.g., <a target="_blank" href="http://main.py"><code>main.py</code></a>) and add the following code:</p>
<pre><code class="lang-python">  <span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
  <span class="hljs-keyword">import</span> uvicorn
  app = FastAPI()

<span class="hljs-meta">  @app.get("/")</span>
  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">root</span>():</span>
      <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello World"</span>}

  <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
      uvicorn.run(app, host=<span class="hljs-string">"0.0.0.0"</span>, port=<span class="hljs-number">8000</span>
</code></pre>
</li>
<li><p>Uvicorn is an ASGI web server implementation for Python to run FastApi app on local host</p>
</li>
</ul>
<h3 id="heading-lets-create-an-api-endpoint-using-fastapi">Let's create an api endpoint using FastApi</h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

app = FastAPI()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>(<span class="hljs-params">BaseModel</span>):</span>
    id: int
    name: str
    description: str
    price: float

<span class="hljs-meta">@app.get("/") #endpoint</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">root</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to the E-commerce API!"</span>}


<span class="hljs-comment"># example of dynamic url</span>
<span class="hljs-meta">@app.get("/products/{product_id}", response_model=Product) </span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_product</span>(<span class="hljs-params">product_id: int</span>):</span>
    <span class="hljs-comment"># Fetch the product data from a database or external service</span>
    product = {
        <span class="hljs-string">"id"</span>: product_id,
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"Product Name"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Product Description"</span>,
        <span class="hljs-string">"price"</span>: <span class="hljs-number">19.99</span>
    }
    <span class="hljs-keyword">return</span> product
</code></pre>
<ul>
<li><p>To run the FastApi app use <strong>uvicorn main:app --reload</strong> command</p>
<pre><code class="lang-bash">  uvicorn main:app --reload
</code></pre>
</li>
</ul>
<p>The api endpoint <strong>/product/{product_id}</strong> will return product based on the product_id provided in the params making it a dynamic url</p>
<p>Pydantic is data validation and parsing library generally used for data modelling of data that the user passes while hitting the api endpoint or when the user recieves the data when hitting the api endpoint.</p>
<p><strong>HTTP</strong> methods used to create endpoints are <strong>GET,POST,PUT,DELETE</strong></p>
<p>In the above example we have created get request api.</p>
<p>This way you can created api <strong>endpoints</strong> quickly and easily with the help of FastAPI</p>
<p>FastAPI also helps to document your api and you can access this docs using <strong>/docs</strong> endpoint of the FastAPI app.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering React Testing Library and Jest: A Comprehensive Guide]]></title><description><![CDATA[Definitions
Testing
Testing is the process of evaluating a software application or system to identify defects, ensure its functionality meets the desired requirements, and verify that it performs as intended. It helps in maintaining software reliabil...]]></description><link>https://blog.ratishfolio.com/mastering-react-testing-library-and-jest-a-comprehensive-guide</link><guid isPermaLink="true">https://blog.ratishfolio.com/mastering-react-testing-library-and-jest-a-comprehensive-guide</guid><category><![CDATA[Testing]]></category><category><![CDATA[react testing library]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Jest]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Fri, 27 Oct 2023 15:00:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698418685688/56cd7bcb-e542-4950-9cfe-2b7eb4c8da56.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-definitions">Definitions</h2>
<p><strong>Testing</strong></p>
<p>Testing is the process of evaluating a software application or system to identify defects, ensure its functionality meets the desired requirements, and verify that it performs as intended. It helps in maintaining software reliability and usability.</p>
<p>There are two types of testing in general</p>
<ul>
<li><p><strong>Unit Testing</strong></p>
</li>
<li><p><strong>Integration Testing</strong></p>
</li>
</ul>
<p><strong>Unit Testing</strong></p>
<p>Unit testing is a level of software testing where individual components or units of a software application are tested in isolation. A "unit" typically refers to the smallest testable part of a program, such as a function, method, or class.</p>
<p><strong>Integration Testing</strong></p>
<p>Integration testing is a level of software testing that focuses on the interactions and interfaces between various units or components of a software system. The primary goal of integration testing is to ensure that these individual units when combined, work together as intended and that the interactions between them do not lead to defects or unexpected behavior.</p>
<h2 id="heading-react-testing-library-amp-jest">React Testing Library &amp; Jest</h2>
<p><strong>React Testing Library</strong> and <strong>Jest</strong> are two of the most popular tools used for testing React applications.</p>
<p><strong>Setup</strong></p>
<p>Firstly Install the react testing library package in your project using the following command</p>
<pre><code class="lang-bash">npm install --save-dev @testing-library/react
</code></pre>
<ul>
<li><p>You might also need to set up a configuration file for Jest, such as <code>jest.config.js</code> or <code>package.json</code> settings.</p>
</li>
<li><p>Create the react components that you want to test.</p>
</li>
</ul>
<p>In this blog, we are gonna see how to write a simple test for a component and run the tests.</p>
<p>Firstly, create a test file for your component the naming convention generally followed is <strong>ComponentName.test.js</strong></p>
<p>Now, inside your test file import the required functions such as <code>render</code> and <code>screen</code> from the react testing library as well as the component that you want to test.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { render, screen } <span class="hljs-keyword">from</span> <span class="hljs-string">'@testing-library/react'</span>;
<span class="hljs-keyword">import</span> MyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'./MyComponent'</span>;
</code></pre>
<p>Now let's understand how the <code>react testing library</code> and <code>jest</code> work!!</p>
<p><strong>Structure of a test block</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698417376854/9fa2191b-1060-4796-ae1c-71a81483d22e.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Render a component you want to test</p>
</li>
<li><p>Search for the element you want to interact with</p>
</li>
<li><p>After that assert/check the results to see whether they are working as desired</p>
</li>
</ul>
<p>The code below shows how a test block is written</p>
<pre><code class="lang-javascript">test(<span class="hljs-string">'MyComponent renders correctly'</span>, <span class="hljs-function">() =&gt;</span> { <span class="hljs-comment">// test block</span>
  render(<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyComponent</span> /&gt;</span></span>);
  <span class="hljs-keyword">const</span> element = screen.getByText(<span class="hljs-string">'Hello, World!'</span>);
  expect(element).toBeInTheDocument();
});
</code></pre>
<p>The above test checks whether the element having the text <code>Hello, World!</code> is rendering properly on the screen or not.</p>
<p>We use <code>render</code> function to render the component we are supposed to test on.</p>
<p>The <code>screen</code> object is an essential utility that provides methods for querying and interacting with the rendered components.</p>
<p><strong>To understand these methods refer to the below chart</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698417917957/329cae68-5476-4ae3-8087-dfac99810b6a.png" alt class="image--center mx-auto" /></p>
<p>The chart shows what each function returns in the case of No Match, 1 Match, 1+ Match and async calls.</p>
<p><strong>A Little bit about Jest</strong></p>
<p>Jest is a JavaScript testing framework maintained by Facebook. It's a powerful and developer-friendly tool for testing JavaScript code, including React applications.</p>
<p>It provides features like test runners, assertion libraries, mocking, and code coverage out of the box.</p>
<p>Use <code>Jest's test runner to execute your tests</code>. You can do this through the command line with <code>npm test</code> or <code>yarn test</code> (if configured).</p>
<p><strong>To learn more in-depth on testing refer to the following resources</strong></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtube.com/playlist?list=PL4cUxeGkcC9gm4_-5UsNmLqMosM-dzuvQ&amp;si=-4PECEXjOuEzqQYt">https://youtube.com/playlist?list=PL4cUxeGkcC9gm4_-5UsNmLqMosM-dzuvQ&amp;si=-4PECEXjOuEzqQYt</a></div>
<p> </p>
<p>Checkout <code>React testing library documentation</code> here <a target="_blank" href="https://testing-library.com/docs/react-testing-library/intro/">Docs</a></p>
<p>📚 <strong>Stay In the Know! Follow Our Blog</strong></p>
<p>Discover a world of knowledge, inspiration, and insights right at your fingertips. Our blog is a treasure trove of valuable content that you won't want to miss. 🌟</p>
<p>Don't miss out! Click that "Follow" button now, and let the learning journey begin.</p>
<p>📖✨</p>
]]></content:encoded></item><item><title><![CDATA[Server Side Rendering vs Client Side Rendering]]></title><description><![CDATA[Server-side rendering (SSR) and client-side rendering (CSR) are two different approaches to rendering web content, and they have distinct implications for how web applications are built and how they perform.
Server-Side Rendering (SSR):
Definition: I...]]></description><link>https://blog.ratishfolio.com/server-side-rendering-vs-client-side-rendering</link><guid isPermaLink="true">https://blog.ratishfolio.com/server-side-rendering-vs-client-side-rendering</guid><category><![CDATA[Next.js]]></category><category><![CDATA[React]]></category><category><![CDATA[Client-side rendering]]></category><category><![CDATA[Server side rendering]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Wed, 18 Oct 2023 08:59:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697619289031/08e9d8b0-edda-43ca-9cb7-82712abf237e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Server-side rendering (SSR) and client-side rendering (CSR) are two different approaches to rendering web content, and they have distinct implications for how web applications are built and how they perform.</p>
<h2 id="heading-server-side-rendering-ssr"><strong>Server-Side Rendering (SSR):</strong></h2>
<p><strong>Definition:</strong> In SSR, the server generates the HTML for a web page and sends it to the client (usually a web browser) as a fully rendered page. This means that the initial page load includes all the content and is ready to be displayed immediately.</p>
<h3 id="heading-static-server-side-rendering-static-ssr"><strong>Static Server-Side Rendering (Static SSR):</strong></h3>
<ol>
<li><p><strong>Definition:</strong> In Static SSR, the server pre-generates HTML pages at build time or when content changes. Each page is pre-rendered into a static HTML file and stored on the server. These pre-rendered pages are then served to clients upon request.</p>
</li>
<li><p><strong>Key Characteristics:</strong></p>
<ul>
<li><p>Pre-Generated Pages: All the pages are generated in advance, typically during the build process. This means that content does not change on the server at runtime.</p>
</li>
<li><p>Fast and Scalable: Since the HTML pages are pre-rendered, they can be served very quickly to clients. This approach is highly scalable as it doesn't require much server-side computation for each request.</p>
</li>
<li><p>Ideal for Content-Heavy Sites: Static SSR is well-suited for websites with mostly static content, like blogs, news sites, or e-commerce platforms with infrequent product updates.</p>
</li>
</ul>
</li>
<li><p><strong>Use Cases:</strong></p>
<ul>
<li><p>Static Websites: Websites with content that doesn't change frequently, like company homepages or personal blogs, can benefit from Static SSR to achieve fast page loads.</p>
</li>
<li><p>Jamstack Architecture: Static site generators like Gatsby, Next.js (with static site generation), or Hugo often use Static SSR to create efficient and performant websites.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-dynamic-server-side-rendering-dynamic-ssr"><strong>Dynamic Server-Side Rendering (Dynamic SSR):</strong></h3>
<ol>
<li><p><strong>Definition:</strong> In Dynamic SSR, the server generates HTML pages for each request, and the content may change based on user interactions or data from external sources (e.g., a database). Unlike Static SSR, pages are created or modified at runtime.</p>
</li>
<li><p><strong>Key Characteristics:</strong></p>
<ul>
<li><p>On-Demand Rendering: Each page is generated on the server when a user requests it, allowing for dynamic content and personalization.</p>
</li>
<li><p>Real-Time Updates: Dynamic SSR can provide real-time or near-real-time updates because it can fetch and render the latest data on each request.</p>
</li>
<li><p>Suitable for Content that Changes Frequently: Applications where content is frequently updated or personalized, such as social media feeds or e-commerce product listings, benefit from Dynamic SSR.</p>
</li>
</ul>
</li>
<li><p><strong>Use Cases:</strong></p>
<ul>
<li><p>Content-Intensive Applications: Dynamic SSR is suitable for applications with frequently changing content, such as news websites, forums, or social media platforms.</p>
</li>
<li><p>Personalized User Experiences: Websites that require user-specific content, like personalized recommendations or user profiles, can use Dynamic SSR to tailor content for each user.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697619160877/28920bc1-fe9b-4cd6-9874-04765dca3da6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-client-side-rendering-csr"><strong>Client-Side Rendering (CSR):</strong></h2>
<ol>
<li><p><strong>Definition:</strong> In CSR, the server sends a minimal HTML shell to the client, which includes JavaScript. The JavaScript code is responsible for fetching data from an API and rendering the content in the browser. The page is constructed dynamically on the client-side.</p>
</li>
<li><p><strong>Key Characteristics:</strong></p>
<ul>
<li><p>Slower Initial Load: CSR typically results in a slower initial page load because the client needs to download the minimal HTML and then execute JavaScript to populate the content.</p>
</li>
<li><p>Interactive and Fast Navigation: Once the initial load is complete, CSR can provide a smoother and more interactive user experience as subsequent navigation and content updates can be faster.</p>
</li>
<li><p>Not SEO-Friendly by Default: Search engines may have difficulty indexing content initially because they might not execute JavaScript.</p>
</li>
</ul>
</li>
<li><p><strong>Use Cases:</strong></p>
<ul>
<li><p>Single-Page Applications (SPAs): Applications that require a high level of interactivity, like social media platforms or web-based productivity tools, often use CSR to provide a dynamic user experience.</p>
</li>
<li><p>Web Apps with Frequent Updates: Applications where content is frequently updated or needs real-time data often opt for CSR because it allows for quick updates without full page reloads.</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697619365674/802740c8-b7d8-41a3-9daf-a0f33f3202a0.png" alt class="image--center mx-auto" /></p>
<p>In many real-world scenarios, a combination of SSR and CSR is used. This approach, known as "Hybrid Rendering," takes advantage of the benefits of both techniques. For example, a website may use SSR for the initial page load to optimize speed and SEO and then switch to CSR for subsequent navigation and interactions to provide a more interactive user experience. This mix allows web developers to strike a balance between performance and interactivity based on the specific needs of their application.</p>
]]></content:encoded></item><item><title><![CDATA[Filter map and reduce in Javascript]]></title><description><![CDATA[In the world of JavaScript programming, the ability to manipulate arrays efficiently and elegantly is a skill that separates novice developers from seasoned experts.
map, filter, and reduce These three versatile functions are not only essential tools...]]></description><link>https://blog.ratishfolio.com/filter-map-and-reduce-in-javascript</link><guid isPermaLink="true">https://blog.ratishfolio.com/filter-map-and-reduce-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[interview]]></category><category><![CDATA[internships]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Thu, 28 Sep 2023 06:00:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695880616625/814d1639-2ae4-4d13-a705-b90cdba54899.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the world of JavaScript programming, the ability to manipulate arrays efficiently and elegantly is a skill that separates novice developers from seasoned experts.</p>
<p><code>map</code>, <code>filter</code>, and <code>reduce</code> These three versatile functions are not only essential tools in a JavaScript developer's arsenal but also shining examples of the functional programming paradigm.</p>
<p>let's learn these three very important functions in a step-by-step manner</p>
<h2 id="heading-map">Map</h2>
<ul>
<li><p>The <code>map</code> function creates a new array by applying a given function to each element of an existing array.</p>
</li>
<li><p>It does not modify the original array; instead, it returns a new array with the results.</p>
</li>
<li><pre><code class="lang-javascript">      <span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>];
      <span class="hljs-keyword">const</span> doubledNumbers = numbers.map(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num * <span class="hljs-number">2</span>);

      <span class="hljs-built_in">console</span>.log(doubledNumbers);
      <span class="hljs-comment">//output - [1,4,6,8]</span>
</code></pre>
</li>
</ul>
<h2 id="heading-filter">Filter</h2>
<ul>
<li><p>The <code>filter</code> function creates a new array containing all the elements that pass a test implemented by the provided function.</p>
</li>
<li><p>It does not modify the original array; instead, it returns a new array with the results.</p>
</li>
<li><pre><code class="lang-javascript">      <span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];
      <span class="hljs-keyword">const</span> evenNumbers = numbers.filter(<span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> num % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>);
      <span class="hljs-built_in">console</span>.log(evenNumbers);
      <span class="hljs-comment">//output [2,4]</span>
</code></pre>
</li>
</ul>
<h2 id="heading-reduce">Reduce</h2>
<ul>
<li><p>The <code>reduce</code> function reduces an array to a single value by applying a function to each element and accumulating the result.</p>
</li>
<li><p>It takes a callback function that has an accumulator (the accumulated result) and the current element as arguments.</p>
</li>
<li><p>You can also provide an initial value for the accumulator.</p>
</li>
<li><pre><code class="lang-javascript">      <span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];
      <span class="hljs-keyword">const</span> sum = numbers.reduce((accumulator, current) {
                      <span class="hljs-keyword">return</span> accumulator + current
                  }, <span class="hljs-number">0</span>);
      <span class="hljs-built_in">console</span>.log(sum);
      <span class="hljs-comment">//output - 15</span>
</code></pre>
</li>
<li><p>The second parameter 0 is the initial value given to the accumulator.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, <code>map</code> transforms each element of an array and returns a new array, <code>filter</code> selects elements that meet a specific condition, and <code>reduce</code> accumulates the elements into a single value. These functions are powerful tools for working with arrays functionally and concisely, improving code readability and maintainability.</p>
]]></content:encoded></item><item><title><![CDATA[Object Oriented Programming in Javascript]]></title><description><![CDATA[JavaScript, often referred to as the "language of the web," is a versatile and powerful programming language. One of its key strengths is its support for Object-Oriented Programming (OOP) principles. In this blog post, we'll dive into the world of OO...]]></description><link>https://blog.ratishfolio.com/object-oriented-programming-in-javascript</link><guid isPermaLink="true">https://blog.ratishfolio.com/object-oriented-programming-in-javascript</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[hashnodebootcamp]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Thu, 21 Sep 2023 16:51:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695314996159/e44d8d91-41fd-4a92-b652-bed0a96c475b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript, often referred to as the "language of the web," is a versatile and powerful programming language. One of its key strengths is its support for Object-Oriented Programming (OOP) principles. In this blog post, we'll dive into the world of OOP in JavaScript, exploring its key concepts and how to use them effectively.</p>
<h2 id="heading-understanding-objects">Understanding Objects</h2>
<p>At the core of Javascript OOP is objects. Everything in javascript under the hood is an object, An object is a collection of key-value pairs where keys are strings (or symbols) and values can be of any data type or even functions.</p>
<p>Here's an example of Object in Javascript -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">"John"</span>,
  <span class="hljs-attr">age</span>: <span class="hljs-number">30</span>,
  <span class="hljs-attr">sayHello</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, my name is <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old.`</span>);
  }
};

person.sayHello(); <span class="hljs-comment">// Output: Hello, my name is John and I am 30 years old.</span>
</code></pre>
<h2 id="heading-classes-and-constructors-in-javascript">Classes and Constructors in Javascript</h2>
<p>In ES6(ECMAScript 6), Javascript introduced a more structured and general way of creating objects. A class is a blueprint for creating objects with shared properties and methods.</p>
<p>Example -</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">constructor</span>(name, age) { <span class="hljs-comment">// constructor for the class</span>
    <span class="hljs-built_in">this</span>.name = name;
    <span class="hljs-built_in">this</span>.age = age;
  }

  Hello() { <span class="hljs-comment">//no need to use function keyword in class</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, my name is <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old.`</span>);
  }
}

<span class="hljs-keyword">const</span> person1 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'John'</span>, <span class="hljs-number">30</span>);
<span class="hljs-keyword">const</span> person2 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'Jane'</span>, <span class="hljs-number">25</span>);

person1.Hello(); <span class="hljs-comment">// Output: Hello, my name is John and I am 30 years old.</span>
person2.Hello(); <span class="hljs-comment">// Output: Hello, my name is Jane and I am 25 years old.</span>
</code></pre>
<p>The constructor function of the class gets called whenever a new keyword is used to create the object of that class and initializes initial values for the object.</p>
<p>The "this" keyword helps in getting the context of the current object and setting the values.  </p>
<h2 id="heading-inheritance-and-subclasses">Inheritance and Subclasses</h2>
<p>JavaScript also supports inheritance through prototype-based inheritance. You can create a subclass (a child class) that inherits properties and methods from a parent class (a superclass).</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Student</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Person</span> </span>{
  <span class="hljs-keyword">constructor</span>(name, age, grade) {
    <span class="hljs-built_in">super</span>(name, age); <span class="hljs-comment">// Call the parent class constructor</span>
    <span class="hljs-built_in">this</span>.grade = grade;
  }

  study() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> is studying for their <span class="hljs-subst">${<span class="hljs-built_in">this</span>.grade}</span> grade.`</span>);
  }
}

<span class="hljs-keyword">const</span> student1 = <span class="hljs-keyword">new</span> Student(<span class="hljs-string">'Alice'</span>, <span class="hljs-number">12</span>, <span class="hljs-string">'6th'</span>);
student1.sayHello(); <span class="hljs-comment">// Output: Hello, my name is Alice and I am 12 years old.</span>
student1.study();
</code></pre>
<p>The super() function calls the superclass constructor function.</p>
<p>using extends keyword class Student inherits properties and methods of class Person and now we can use the properties of Person class in a Student object.</p>
<p>This phenomena is called inheritance.</p>
<h2 id="heading-encapsulation-abstraction-and-more"><strong>Encapsulation, Abstraction, and More</strong></h2>
<p>OOP in JavaScript allows you to implement essential OOP principles such as encapsulation and abstraction. You can hide internal details and expose only the necessary interfaces, making your code more modular and maintainable.</p>
<p>Additionally, JavaScript provides tools like getters and setters to control access to object properties, further enhancing encapsulation.</p>
<p>To learn more in depth about these topics I'll be providing blogs on the topics soon.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Object-Oriented Programming in JavaScript empowers developers to create structured, reusable, and maintainable code. Understanding objects, classes, constructors, and inheritance is fundamental to harnessing the power of OOP in JavaScript. With these concepts in your toolkit, you can design elegant and efficient solutions for a wide range of applications.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Prototypes and Prototypal Inheritance]]></title><description><![CDATA[Prototypes: Foundation of Javascript
In Javascript, everything is an object and the prototype serves as a blueprint for every object containing its properties and methods.
To understand it more easily let's first understand what are constructor funct...]]></description><link>https://blog.ratishfolio.com/javascript-prototypes-and-prototypal-inheritance</link><guid isPermaLink="true">https://blog.ratishfolio.com/javascript-prototypes-and-prototypal-inheritance</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[DSA]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Mon, 18 Sep 2023 15:21:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695050317856/d17dca02-9b77-4035-8b2e-53bfe33cff2c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-prototypes-foundation-of-javascript">Prototypes: Foundation of Javascript</h2>
<p>In Javascript, everything is an object and the prototype serves as a blueprint for every object containing its properties and methods.</p>
<p>To understand it more easily let's first understand what are constructor functions</p>
<h3 id="heading-constructor-functions">Constructor Functions -</h3>
<p>Constructor functions are used to create objects. They act as templates for objects, defining their initial state and behavior.</p>
<p>Here's an example -</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">myObj</span>(<span class="hljs-params">name,age</span>)</span>{ <span class="hljs-comment">//constructor functions</span>
    <span class="hljs-built_in">this</span>.name = name;
    <span class="hljs-built_in">this</span>.age = age;
}

<span class="hljs-keyword">const</span> obj1 = <span class="hljs-keyword">new</span> myObj(<span class="hljs-string">"xyz"</span>,<span class="hljs-string">"20"</span>);
<span class="hljs-keyword">const</span> obj2 = <span class="hljs-keyword">new</span> myObj(<span class="hljs-string">"yzx"</span>,<span class="hljs-string">"21"</span>);
</code></pre>
<p>The above constructor function takes properties <strong>"name"</strong> and <strong>"age"</strong> and sets them as properties on the newly created objects with the <strong>new</strong> keyword**.**</p>
<p>However, with this approach, each object created using <code>new myObj()</code> has its own copy of the properties and methods, leading to potential memory inefficiencies if there are many instances.</p>
<h3 id="heading-prototypes">Prototypes -</h3>
<p>JavaScript's prototype system comes into play to address above issue. Every function in JavaScript has a property called <code>prototype</code>, which is an object that can hold properties and methods shared among all instances created by that constructor function.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Person</span>(<span class="hljs-params">name, age</span>) </span>{
  <span class="hljs-built_in">this</span>.name = name;
  <span class="hljs-built_in">this</span>.age = age;
}

Person.prototype.sayHello = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hello, my name is <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old.`</span>);
};

<span class="hljs-keyword">const</span> person1 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>);
<span class="hljs-keyword">const</span> person2 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>);

person1.sayHello(); <span class="hljs-comment">// "Hello, my name is Alice and I am 30 years old."</span>
person2.sayHello(); <span class="hljs-comment">// "Hello, my name is Bob and I am 25 years old."</span>
</code></pre>
<p>Since everything in javascript is an object we can use their prototype attribute to create our own set of properties for such objects common to all the instances of that object as the sayHello() function created above will be available to both person1 and person2 objects as both are instance of the same constructor function.</p>
<h2 id="heading-prototypal-inheritance">Prototypal Inheritance -</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695049273468/66a0bab0-b247-47b8-90ac-8bd346aeca8d.png" alt class="image--center mx-auto" /></p>
<p>You can achieve prototypal inheritance using the <code>__proto__</code> property in JavaScript. Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Parent object</span>
<span class="hljs-keyword">const</span> animal = {
  <span class="hljs-attr">speak</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`I am an animal.`</span>);
  },
};

<span class="hljs-comment">// Child object inheriting from the parent</span>
<span class="hljs-keyword">const</span> dog = {
  <span class="hljs-attr">__proto__</span>: animal, <span class="hljs-comment">// Set the prototype to 'animal'</span>
  <span class="hljs-attr">bark</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Woof!"</span>);
  },
};

<span class="hljs-comment">// Create instances of 'dog'</span>
<span class="hljs-keyword">const</span> dog1 = <span class="hljs-built_in">Object</span>.create(dog);
dog1.speak(); <span class="hljs-comment">// "I am an animal."</span>
dog1.bark();  <span class="hljs-comment">// "Woof!"</span>

<span class="hljs-keyword">const</span> dog2 = <span class="hljs-built_in">Object</span>.create(dog);
dog2.speak(); <span class="hljs-comment">// "I am an animal."</span>
dog2.bark();  <span class="hljs-comment">// "Woof!"</span>
</code></pre>
<p>Here, the dog object inherits the properties of the animal object with the help of <code>__proto__</code> property. so all instances of the dog object will have the speak function in their prototype methods and variables.</p>
<p>However, <code>__proto__</code> property was used in older javascript syntax in new Javascript modern syntax <code>Object.setPrototypeOf()</code> and <code>Object.getPrototypeOf()</code></p>
<p>Here's an example -</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Parent object</span>
<span class="hljs-keyword">const</span> animal = {
  <span class="hljs-attr">speak</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`I am an animal.`</span>);
  },
};

<span class="hljs-comment">// Child object</span>
<span class="hljs-keyword">const</span> dog = {
  <span class="hljs-attr">bark</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Woof!"</span>);
  },
};

<span class="hljs-comment">// Establishing prototype-based inheritance</span>
<span class="hljs-built_in">Object</span>.setPrototypeOf(dog, animal);

<span class="hljs-comment">// Create instances of 'dog'</span>
<span class="hljs-keyword">const</span> dog1 = <span class="hljs-built_in">Object</span>.create(dog);
dog1.speak(); <span class="hljs-comment">// "I am an animal."</span>
dog1.bark();  <span class="hljs-comment">// "Woof!"</span>

<span class="hljs-keyword">const</span> dog2 = <span class="hljs-built_in">Object</span>.create(dog);
dog2.speak(); <span class="hljs-comment">// "I am an animal."</span>
dog2.bark();  <span class="hljs-comment">// "Woof!"</span>
</code></pre>
<p>We use <code>Object.setPrototypeOf(dog, animal)</code> to establish prototype-based inheritance. This sets the prototype of <code>dog</code> to <code>animal</code>, creating a prototype chain where <code>dog</code> inherits from <code>animal</code>.</p>
<h2 id="heading-conclusion">Conclusion -</h2>
<p>In conclusion, JavaScript offers several mechanisms for establishing prototype-based inheritance, each with its own advantages and use cases. Whether you choose to use constructor functions, <code>Object.create()</code>, or <code>Object.setPrototypeOf()</code>, the fundamental concept remains the same: objects can inherit properties and methods from their prototypes, creating a flexible and efficient way to structure and organize your code.</p>
<p>Understanding prototype chains and how objects relate to each other through prototypes is crucial for writing maintainable and efficient JavaScript code.</p>
<h2 id="heading-subscribe-to-our-blog-post-to-learn-more-about-the-fundamentals-of-web-development">Subscribe to our blog post to learn more about the fundamentals of web development.</h2>
]]></content:encoded></item><item><title><![CDATA[Streamline Form Validation with React Hook Form and implement Email Service using EmailJS]]></title><description><![CDATA[In web development, form validation is a crucial aspect to ensure data accuracy and user experience. React Hook Form is a powerful library that simplifies the process of building robust forms in React applications. Alongside form validation, integrat...]]></description><link>https://blog.ratishfolio.com/streamline-form-validation-with-react-hook-form-and-implement-email-service-using-emailjs</link><guid isPermaLink="true">https://blog.ratishfolio.com/streamline-form-validation-with-react-hook-form-and-implement-email-service-using-emailjs</guid><category><![CDATA[CNCF]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sat, 15 Jul 2023 15:59:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689436647648/0256ebc8-2b20-40f3-8681-dd1006ddc350.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In web development, form validation is a crucial aspect to ensure data accuracy and user experience. React Hook Form is a powerful library that simplifies the process of building robust forms in React applications. Alongside form validation, integrating email services can enhance functionality by enabling automated email notifications.</p>
<p>In this blog post, we will explore how to combine the capabilities of React Hook Form and EmailJS to create a seamless form validation and email service integration.</p>
<h2 id="heading-what-is-react-hook-form">What is React Hook Form?</h2>
<p>React Hook Form is a lightweight and performant library for managing forms in React applications. It simplifies form validation, state management, and submission handling by leveraging React's hooks feature.</p>
<h2 id="heading-setting-up-a-react-application">Setting up a React Application:</h2>
<p>To get started, ensure that you have Node.js and npm (Node Package Manager) installed on your machine. Create a new React application using the following command in your terminal:</p>
<pre><code class="lang-bash">npx create-react-app form-validation-email-service
</code></pre>
<h2 id="heading-installing-react-hook-form-and-emailjs">Installing React Hook Form and EmailJS:</h2>
<p>Navigate into the project directory and install React Hook Form and EmailJS packages:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> form-validation-email-service
npm install react-hook-form @emailjs/browser --save
</code></pre>
<h2 id="heading-building-a-form-with-react-hook-form">Building a Form with React Hook Form:</h2>
<p>In your React component file, import the necessary dependencies:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-hook-form'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ContactForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { register, handleSubmit } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
      {/* Form fields */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ContactForm;
</code></pre>
<h2 id="heading-validating-form-inputs">Validating Form Inputs:</h2>
<p>React Hook Form offers a simple way to validate form inputs using built-in validation rules or custom functions. Let's add some basic validation to our form fields:</p>
<pre><code class="lang-javascript">&lt;input
  type=<span class="hljs-string">"text"</span>
  {...register(<span class="hljs-string">'name'</span>, { <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span> })}
/&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
  {<span class="hljs-attr">...register</span>('<span class="hljs-attr">email</span>', 
    { 
      <span class="hljs-attr">required:</span> <span class="hljs-attr">true</span>, 
      <span class="hljs-attr">pattern:</span> /^[<span class="hljs-attr">A-Z0-9._</span>%+<span class="hljs-attr">-</span>]+@[<span class="hljs-attr">A-Z0-9.-</span>]+\<span class="hljs-attr">.</span>[<span class="hljs-attr">A-Z</span>]{<span class="hljs-attr">2</span>,}$/<span class="hljs-attr">i</span> 
    }
  )}
/&gt;</span></span>
</code></pre>
<h2 id="heading-submitting-form-data">Submitting Form Data:</h2>
<p>To handle form submission, we'll utilize the <code>handleSubmit</code> function provided by React Hook Form. In the <code>onSubmit</code> callback, we can access the form data and perform further actions:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(data);

  <span class="hljs-comment">// Perform additional actions like API calls or email service integration</span>
};
</code></pre>
<h1 id="heading-integrating-emailjs">Integrating EmailJS</h1>
<p>EmailJS is a service that allows you to send emails directly from the client-side without any server-side code.</p>
<p>Sign up for an account on the EmailJS website and obtain your user ID and template ID. Import the EmailJS library and configure it with your credentials:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> emailjs <span class="hljs-keyword">from</span> <span class="hljs-string">'@emailjs/browser'</span>;

 <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
    <span class="hljs-keyword">const</span> params = {
        <span class="hljs-string">"user_name"</span>:data.username, <span class="hljs-comment">//key value mustbe same as in your template in emailjs</span>
        <span class="hljs-string">"user_email"</span>:data.email,
        <span class="hljs-string">"message"</span>: data.message,
    }
    emailjs.sendForm(<span class="hljs-string">'YOUR_SERVICE_ID'</span>, <span class="hljs-string">'YOUR_TEMPLATE_ID'</span>, params ,<span class="hljs-string">'YOUR_PUBLIC_KEY'</span>)
      .then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
          <span class="hljs-built_in">console</span>.log(result.text);
      }, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
          <span class="hljs-built_in">console</span>.log(error.text);
      });
  };
</code></pre>
<p>You can now test your form by filling in the required fields and submitting it. Ensure that you receive the success message and check the recipient's email inbox for the email notification.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this blog post, we explored the process of implementing form validation using React Hook Form and integrating an email service using EmailJS. React Hook Form simplified form management by providing an intuitive API for validation and submission handling. By integrating EmailJS, we were able to enhance the functionality by sending automated email notifications to the desired recipient.</p>
<p>Remember to further explore the documentation of React Hook Form and EmailJS to unleash their full potential in your projects. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Object Oriented Programming in Dart: An Extensive Guide!!]]></title><description><![CDATA[Object-oriented programming (OOP) is a programming approach that organizes code around objects, representing real-world entities. It involves encapsulating data and behavior within objects, using classes as blueprints. OOP emphasizes principles such ...]]></description><link>https://blog.ratishfolio.com/object-oriented-programming-in-dart-an-extensive-guide</link><guid isPermaLink="true">https://blog.ratishfolio.com/object-oriented-programming-in-dart-an-extensive-guide</guid><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Dart]]></category><category><![CDATA[development]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Thu, 25 May 2023 04:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684930401574/f3dca9ce-f31d-4a0a-8787-3236a0ab7772.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Object-oriented programming (OOP) is a programming approach that organizes code around objects, representing real-world entities. It involves encapsulating data and behavior within objects, using classes as blueprints. OOP emphasizes principles such as encapsulation, inheritance, polymorphism, abstraction, and modularity to promote code organization, reusability, and flexibility.</p>
<h3 id="heading-heres-an-extensive-guide-to-object-oriented-programming-oop-in-dart">Here's an extensive guide to object-oriented programming (OOP) in Dart:</h3>
<ol>
<li><p>Classes and Objects:</p>
<ul>
<li><p>Classes in Dart define the blueprint for creating objects. You can create classes using the <code>class</code> keyword.</p>
</li>
<li><p>Objects are instances of classes, and you can create objects using the <code>new</code> keyword or by omitting it in newer Dart versions.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
      <span class="hljs-built_in">String</span> name; <span class="hljs-comment">//variables of a class</span>
      <span class="hljs-built_in">int</span> age; <span class="hljs-comment">//variables of a class</span>

      <span class="hljs-keyword">void</span> sayHello() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Hello, my name is <span class="hljs-subst">$name</span>. I'm <span class="hljs-subst">$age</span> years old."</span>);
      }
    }

    <span class="hljs-keyword">void</span> main() {
      <span class="hljs-comment">// Creating an object of the Person class</span>
      <span class="hljs-keyword">var</span> person = Person();
      person.name = <span class="hljs-string">"John"</span>;
      person.age = <span class="hljs-number">30</span>;

      <span class="hljs-comment">// Calling the sayHello() method</span>
      person.sayHello(); <span class="hljs-comment">// Output: Hello, my name is John. I'm 30 years old.</span>
    }
</code></pre>
<ul>
<li><p>Properties represent the state or data associated with an object. They are declared using variables inside a class.</p>
</li>
<li><p>Methods define the behavior of an object. They are functions defined within a class and can manipulate the object's properties.</p>
</li>
</ul>
<ol>
<li>Constructors:</li>
</ol>
<ul>
<li><p>Constructors are special methods used for object initialization. Dart provides default constructors if none is defined explicitly.</p>
</li>
<li><p>You can create named constructors to provide multiple ways to create objects.</p>
</li>
<li><p>The <code>this</code> keyword refers to the current instance of the class within a constructor.</p>
</li>
<li><p>There is another type of constructor known as redirecting constructor in Dart.</p>
</li>
</ul>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span> </span>{
  <span class="hljs-built_in">double</span> x;
  <span class="hljs-built_in">double</span> y;

  <span class="hljs-comment">// Default constructor</span>
  Point(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y);

  <span class="hljs-comment">// Named constructor</span>
  Point.origin() {
    x = <span class="hljs-number">0</span>;
    y = <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">// redirecting Constructors</span>
  Point.addval(<span class="hljs-built_in">double</span> x, <span class="hljs-built_in">double</span> y) : <span class="hljs-keyword">this</span>(x,y);
}

<span class="hljs-keyword">void</span> main() {
  <span class="hljs-keyword">var</span> p1 = Point(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>); <span class="hljs-comment">// Using the default constructor</span>
  <span class="hljs-built_in">print</span>(<span class="hljs-string">"Point p1: (<span class="hljs-subst">${p1.x}</span>, <span class="hljs-subst">${p1.y}</span>)"</span>); <span class="hljs-comment">// Output: Point p1: (2.0, 3.0)</span>

  <span class="hljs-keyword">var</span> p2 = Point.origin(); <span class="hljs-comment">// Using the named constructor</span>
  <span class="hljs-built_in">print</span>(<span class="hljs-string">"Point p2: (<span class="hljs-subst">${p2.x}</span>, <span class="hljs-subst">${p2.y}</span>)"</span>); <span class="hljs-comment">// Output: Point p2: (0.0, 0.0)</span>

  <span class="hljs-keyword">var</span> p3 = Point.addval(<span class="hljs-number">4</span>,<span class="hljs-number">5</span>); <span class="hljs-comment">// Using the redirecting constructor</span>
  <span class="hljs-built_in">print</span>(<span class="hljs-string">"Point p3: (<span class="hljs-subst">${p3.x}</span>, <span class="hljs-subst">${p3.y}</span>)"</span>); <span class="hljs-comment">// Output: Point p3: (4.0, 5.0)</span>
}
</code></pre>
<h3 id="heading-important-concepts-of-oop-in-dart">Important Concepts of OOP in Dart:</h3>
<ol>
<li><p>Inheritance:</p>
<ul>
<li><p>Inheritance allows you to create new classes based on existing ones. The new class inherits the properties and methods of the parent class.</p>
</li>
<li><p>Dart supports single inheritance, meaning a class can only inherit from one superclass.</p>
</li>
<li><p>The <code>extends</code> keyword is used to establish inheritance relationships.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-keyword">void</span> eat() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Animal is eating."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-keyword">void</span> bark() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Dog is barking."</span>);
      }
    }

    <span class="hljs-keyword">void</span> main() {
      <span class="hljs-keyword">var</span> dog = Dog();
      dog.eat(); <span class="hljs-comment">// Output: Animal is eating.</span>
      dog.bark(); <span class="hljs-comment">// Output: Dog is barking.</span>
    }
</code></pre>
<ol>
<li><p>Polymorphism:</p>
<ul>
<li><p>Polymorphism allows objects of different classes to be treated as objects of a common superclass.</p>
</li>
<li><p>Dart achieves polymorphism through method overriding. You can override methods in a subclass to provide different implementations.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-keyword">void</span> makeSound() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Animal is making a sound."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-meta">@override</span>
      <span class="hljs-keyword">void</span> makeSound() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Dog is barking."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-meta">@override</span>
      <span class="hljs-keyword">void</span> makeSound() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Cat is meowing."</span>);
      }
    }

    <span class="hljs-keyword">void</span> main() {
      <span class="hljs-keyword">var</span> dog = Dog();
      <span class="hljs-keyword">var</span> cat = Cat();

      dog.makeSound(); <span class="hljs-comment">// Output: Dog is barking.</span>
      cat.makeSound(); <span class="hljs-comment">// Output: Cat is meowing.</span>

      <span class="hljs-comment">// Polymorphism in action</span>
      Animal animal = dog;
      animal.makeSound(); <span class="hljs-comment">// Output: Dog is barking.</span>

      animal = cat;
      animal.makeSound(); <span class="hljs-comment">// Output: Cat is meowing.</span>
    }
</code></pre>
<ol>
<li><p>Encapsulation:</p>
<ul>
<li><p>Encapsulation refers to the practice of hiding internal implementation details and exposing only necessary information.</p>
</li>
<li><p>In Dart, you can mark properties and methods as <code>private</code> using the underscore (_) prefix.</p>
</li>
<li><p>You can provide getter and setter methods to control access to private properties.</p>
</li>
</ul>
</li>
<li><p>Abstraction:</p>
<ul>
<li><p>Abstraction focuses on defining interfaces or abstract classes that provide a common set of methods that subclasses must implement.</p>
</li>
<li><p>Dart supports abstract classes and methods using the <code>abstract</code> keyword.</p>
</li>
<li><p>Abstract classes cannot be instantiated directly; they serve as a base for subclasses.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-keyword">void</span> makeSound();
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-meta">@override</span>
      <span class="hljs-keyword">void</span> makeSound() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Dog is barking."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-meta">@override</span>
      <span class="hljs-keyword">void</span> makeSound() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Cat is meowing."</span>);
      }
    }

    <span class="hljs-keyword">void</span> main() {
      Animal dog = Dog();
      dog.makeSound(); <span class="hljs-comment">// Output: Dog is barking.</span>

      Animal cat = Cat();
      cat.makeSound(); <span class="hljs-comment">// Output: Cat is meowing.</span>
    }
</code></pre>
<ol>
<li><p>Interfaces:</p>
<ul>
<li><p>Dart does not have a separate <code>interface</code> keyword, as every class defines an interface.</p>
</li>
<li><p>You can implement multiple interfaces in a class using the <code>implements</code> keyword.</p>
</li>
<li><p>Classes implementing an interface must provide implementations for all the interface's methods.</p>
</li>
</ul>
</li>
<li><p>Static Members:</p>
<ul>
<li><p>Static members belong to the class itself rather than instances of the class.</p>
</li>
<li><p>You can declare static properties and methods using the <code>static</code> keyword.</p>
</li>
<li><p>Static members can be accessed without creating an object of the class.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> </span>{
      <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-built_in">double</span> pi = <span class="hljs-number">3.14159</span>;
      <span class="hljs-keyword">static</span> <span class="hljs-built_in">int</span> numberOfCircles = <span class="hljs-number">0</span>;

      Circle() {
        numberOfCircles++;
      }

      <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> printPi() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"The value of pi is: <span class="hljs-subst">$pi</span>"</span>);
      }
    }

    <span class="hljs-keyword">void</span> main() {
      Circle();
      Circle();

      <span class="hljs-built_in">print</span>(<span class="hljs-string">"Number of circles: <span class="hljs-subst">${Circle.numberOfCircles}</span>"</span>); <span class="hljs-comment">// Output: Number of circles: 2</span>

      Circle.printPi(); <span class="hljs-comment">// Output: The value of pi is: 3.14159</span>
    }
</code></pre>
<ol>
<li><p>Mixins:</p>
<ul>
<li><p>Mixins are a way to reuse a set of methods in multiple classes without using inheritance.</p>
</li>
<li><p>They allow you to add behavior to a class without becoming its superclass.</p>
</li>
<li><p>You can define a mixin using the <code>mixin</code> keyword and apply it to a class using the <code>with</code> keyword.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-dart">    <span class="hljs-keyword">mixin</span> Swimmer {
      <span class="hljs-keyword">void</span> swim() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Swimming..."</span>);
      }
    }

    <span class="hljs-keyword">mixin</span> Flyer {
      <span class="hljs-keyword">void</span> fly() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Flying..."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
      <span class="hljs-keyword">void</span> eat() {
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Eating..."</span>);
      }
    }

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dolphin</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> <span class="hljs-title">with</span> <span class="hljs-title">Swimmer</span> </span>{}

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> <span class="hljs-title">with</span> <span class="hljs-title">Swimmer</span>, <span class="hljs-title">Flyer</span> </span>{}

    <span class="hljs-keyword">void</span> main() {
      <span class="hljs-keyword">var</span> dolphin = Dolphin();
      dolphin.eat(); <span class="hljs-comment">// Output: Eating...</span>
      dolphin.swim(); <span class="hljs-comment">// Output: Swimming...</span>

      <span class="hljs-keyword">var</span> bird = Bird();
      bird.eat(); <span class="hljs-comment">// Output: Eating...</span>
      bird.swim(); <span class="hljs-comment">// Output: Swimming...</span>
      bird.fly(); <span class="hljs-comment">// Output: Flying...</span>
    }
</code></pre>
<p>This guide covers the key concepts of object-oriented programming in Dart. By understanding these concepts and their implementation in Dart, you can build robust and scalable applications.</p>
<p>Thank you for reading! Stay connected for more valuable content. Be sure to follow us to receive regular updates, exclusive content, and special offers. Join our vibrant community of learners by visiting our website and exploring all that we have to offer. Let's continue our journey of knowledge and growth together!!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684930546295/abbfdd00-5212-4e1d-9860-5dc42dc87a3d.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Simplifying State Management in Flutter with Provider]]></title><description><![CDATA[What is State Management?
State management is the process of managing the state of your Flutter application. The state of an application is the data that changes over time, such as the current user, the current page, or the contents of a shopping car...]]></description><link>https://blog.ratishfolio.com/simplifying-state-management-in-flutter-with-provider</link><guid isPermaLink="true">https://blog.ratishfolio.com/simplifying-state-management-in-flutter-with-provider</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Provider]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Tue, 16 May 2023 04:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684152159848/b5eb5dbd-84d8-4015-9941-af18ef5f26af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-state-management"><strong>What is State Management?</strong></h2>
<p>State management is the process of managing the state of your Flutter application. The state of an application is the data that changes over time, such as the current user, the current page, or the contents of a shopping cart.</p>
<h2 id="heading-why-do-you-need-state-management"><strong>Why do you need State Management?</strong></h2>
<p>Flutter apps are built using a declarative programming language, which means that you describe the UI of your app in terms of how it should look, rather than how it should behave. This makes it easy to create beautiful and complex UIs, but it can also make it difficult to manage the state of your app.</p>
<p>Without state management, you would have to manually update the state of your app whenever it changes. This would be very tedious and error-prone, especially for large and complex apps.</p>
<h2 id="heading-what-is-provider"><strong>What is Provider?</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684151208912/4bba9a11-9342-4282-891b-3be22e6f1446.avif" alt class="image--center mx-auto" /></p>
<p>provider is a state management package for Flutter that makes it easy to manage the state of your app. Provider uses a concept called dependency injection to manage the state of your app.</p>
<p>Dependency injection is a technique where you pass the dependencies of a class into the constructor of that class. This makes it easy to change the dependencies of a class without having to modify the class itself.</p>
<p>Provider uses dependency injection to manage the state of your app. When you create a Provider, you pass the state of your app into the constructor of the Provider. This makes it easy to change the state of your app without having to modify the code that uses the state.</p>
<h2 id="heading-how-to-use-provider"><strong>How to use Provider</strong></h2>
<p>To use Provider, you first need to install the package. You can do this by running the following command in your terminal:</p>
<pre><code class="lang-bash">flutter pub add provider
</code></pre>
<p>Once the package is installed, you can start using it in your app. The following code shows how to create a simple state management solution with Provider:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'package:provider/provider.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Provider(
      builder: (context, child) {
        <span class="hljs-keyword">return</span> MaterialApp(
          home: MyHomePage(),
        );
      },
    );
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHomePage</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
  <span class="hljs-meta">@override</span>
  Widget build(BuildContext context) {
    <span class="hljs-comment">// Get the current count from the provider</span>
    <span class="hljs-built_in">int</span> count = Provider.of&lt;Counter&gt;(context).count;

    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(
        title: Text(<span class="hljs-string">'My App'</span>),
      ),
      body: Center(
        child: Text(<span class="hljs-string">'The count is <span class="hljs-subst">$count</span>'</span>),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          <span class="hljs-comment">// Increment the count</span>
          Provider.of&lt;Counter&gt;(context).increment();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> <span class="hljs-title">with</span> <span class="hljs-title">ChangeNotifier</span> </span>{
  <span class="hljs-built_in">int</span> count = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">void</span> increment() {
    count++;
    notifyListeners();
  }
}
</code></pre>
<ul>
<li><p>In this code, we create a <code>Counter</code> class that extends the <code>ChangeNotifier</code> class. The <code>ChangeNotifier</code> class provides a mechanism for notifying listeners when the state of the object changes.</p>
</li>
<li><p>We then create a <code>MyHomePage</code> widget that uses Provider to get the current count from the <code>Counter</code> object. When the user clicks the floating action button, the count is incremented and the <code>Counter</code> object is notified.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Provider is a powerful state management library that can make it easy to manage the state of your Flutter apps.</p>
<p>With Provider, you can create a single source of truth for your app's state, and you can access the state from any widget in your app.</p>
<p>Provider also provides a number of features that make it easy to manage state, such as change notification,inheritance, and lazy loading.</p>
<p>If you are looking for a state management library for your Flutter app, I encourage you to check out Provider.</p>
]]></content:encoded></item><item><title><![CDATA[Hashing in Data Structures: Understanding the Key Concepts and Applications]]></title><description><![CDATA[Hashing is a fundamental concept in computer science and is used in various applications, from data storage to cryptography. In this blog, we will explore the basics of hashing, its advantages, and the different types of hash functions. Additionally,...]]></description><link>https://blog.ratishfolio.com/hashing-in-data-structures-understanding-the-key-concepts-and-applications</link><guid isPermaLink="true">https://blog.ratishfolio.com/hashing-in-data-structures-understanding-the-key-concepts-and-applications</guid><category><![CDATA[datastructure]]></category><category><![CDATA[Hashing]]></category><category><![CDATA[Security]]></category><category><![CDATA[development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Mon, 01 May 2023 04:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682759052605/42387268-d5ef-445d-8c39-d61900ee1a63.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hashing is a fundamental concept in computer science and is used in various applications, from data storage to cryptography. In this blog, we will explore the basics of hashing, its advantages, and the different types of hash functions. Additionally, we will discuss some of the popular applications of hashing.</p>
<p>What is Hashing? Hashing is the process of mapping data of arbitrary size to a fixed-size output. This fixed-size output is called a hash or a message digest. The hash function takes input data and produces a fixed-length output, which is typically a unique representation of the input data. The resulting hash is often used for indexing, searching, and data integrity verification.</p>
<p>Advantages of Hashing: Hashing provides several advantages, such as:</p>
<ol>
<li><p>Data Integrity Verification: Hashing is widely used for verifying data integrity. By comparing the hash value of the original data with the hash value of the received data, one can determine whether the data has been modified or corrupted during transmission.</p>
</li>
<li><p>Fast Retrieval: Hashing allows for quick retrieval of data from large datasets. Instead of searching through the entire dataset, hash functions can be used to index data and retrieve it quickly.</p>
</li>
<li><p>Security: Hashing is an essential tool in cryptography. It is used to store passwords securely and to authenticate data.</p>
</li>
</ol>
<p>Types of Hash Functions: There are various types of hash functions, including:</p>
<ol>
<li><p>Cryptographic Hash Functions: Cryptographic hash functions are designed to be secure and are commonly used in cryptography. Examples of cryptographic hash functions include SHA-256 and SHA-512.</p>
</li>
<li><p>Non-Cryptographic Hash Functions: Non-cryptographic hash functions are used for indexing, searching, and data integrity verification. Examples of non-cryptographic hash functions include MurmurHash and FNV.</p>
</li>
</ol>
<p>Applications of Hashing: Hashing has several applications, including:</p>
<ol>
<li><p>Password Storage: Hashing is used to store passwords securely. When a user enters a password, it is hashed and compared with the stored hash value. If the values match, the user is granted access.</p>
</li>
<li><p>Data Integrity Verification: Hashing is used to verify the integrity of data during transmission. The hash value of the original data is compared with the hash value of the received data to determine whether the data has been modified or corrupted.</p>
</li>
<li><p>Indexing and Searching: Hashing is used to index and search large datasets quickly. Hash functions can be used to map data to a fixed-size index, allowing for fast retrieval of data.</p>
</li>
</ol>
<p>In Hashing Hash Tables are used but many times collision occurs when new data is being added to the Hash Table to avoid this there are many collision resolution techniques like linear probing, separate chaining and quadratic probing below there is an in-depth explanation of these techniques -</p>
<ol>
<li><p>Linear Probing: Linear probing is a simple method for resolving collisions. When a collision occurs, the algorithm checks the next available slot in the table and places the item there. This process continues until an empty slot is found. The main disadvantage of linear probing is that it can result in clustering, where items are stored in adjacent slots, making it more difficult to search the table efficiently.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682756439665/c31eec5d-95c1-476a-882b-03fdb94a1896.jpeg" alt class="image--center mx-auto" /></p>
</li>
<li><p>Separate Chaining: Separate chaining is a technique where each slot in the hash table contains a linked list of items that hash to that location. When a collision occurs, the item is added to the linked list. This method avoids clustering and is more efficient for large datasets. However, it requires additional memory to store the linked lists and may result in slower search times if the lists become too long.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682751787845/0cd4dba9-16e2-427a-bf24-65f189cf55a1.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>Quadratic Probing: Quadratic probing is a variation of linear probing that tries to distribute items more evenly across the table. Instead of checking the next available slot, the algorithm searches for the next available slot using a quadratic function. This method reduces clustering and provides better search efficiency than linear probing. However, it may result in longer search times for some inputs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682756944474/7ae20656-36eb-4c86-b160-db11ca328f21.png" alt class="image--center mx-auto" /></p>
<p>In conclusion, hashing is an essential concept in computer science, providing several benefits such as data integrity verification, fast retrieval, and security. Understanding the different types of hash functions and their applications can help developers make informed decisions when implementing hashing in their applications.</p>
]]></content:encoded></item><item><title><![CDATA[A  Developer's Guide to Integrating
ChatGPT and DALL-E  APIs in Your Flutter App 🚀]]></title><description><![CDATA[Open AI recently released ChatGPT and DALL-E which are AI-powered tools helping you to boost your productivity and do work efficiently without any hassle. They are natural language processing technology that enables the automation of chat conversatio...]]></description><link>https://blog.ratishfolio.com/a-developers-guide-to-integrating-chatgpt-and-dall-e-apis-in-your-flutter-app</link><guid isPermaLink="true">https://blog.ratishfolio.com/a-developers-guide-to-integrating-chatgpt-and-dall-e-apis-in-your-flutter-app</guid><category><![CDATA[chatgptguide]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Artificial Intelligence]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Mon, 10 Apr 2023 04:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680948294382/9e93d805-0f7a-4fdc-a3bb-210726360516.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Open AI recently released ChatGPT and DALL-E which are AI-powered tools helping you to boost your productivity and do work efficiently without any hassle. They are natural language processing technology that enables the automation of chat conversations and generating images based on the prompts the user provides.</p>
<p>ChatGPT API helps developers to integrate ChatGPT features into their projects which can be either chat-based or voice assistant ie - using your commands as input and the API will generate a response based on that command.</p>
<p>DALL-E API is used for image generation based on user prompts</p>
<h2 id="heading-pre-requisites-before-integration">Pre-requisites before integration</h2>
<ul>
<li><p>Create an account on Open AI by going to their documentation page</p>
</li>
<li><p>Generate your <strong>API Key</strong> which will be used to make an API call to the ChatGPT API and DALL-E API by clicking on <strong>Create new secret key</strong></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680942560910/a812c187-5c6f-4234-9fc8-01ee4abfe156.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Make sure to store the API Key somewhere like the .env file as you will only be able to see it on the website only once.</li>
</ul>
<h2 id="heading-integrate-apis-in-your-flutter-project">Integrate APIs in your Flutter Project</h2>
<ul>
<li><p>Create a dart file which will contain all the functions regarding the API calls to</p>
<p>  ChatGPT and DALL-E and name it for example <strong>openai_service.dart</strong></p>
</li>
<li><p>We are gonna use the <strong>HTTP</strong> package for the API call but you can also use the dart_openai package for the API calls(<a target="_blank" href="https://pub.dev/packages/dart_openai">dart_openai</a>)</p>
</li>
<li><p>Now we are gonna use chat API(chat completions) which supports two open AI models: <strong>GPT-4</strong> and <strong>GPT-3.5-turbo</strong></p>
</li>
<li><p>Now as we are also using DALL-E API together we need some way to distinguish whether the user is asking to generate an image or not for that we will be using an async function named as isArtPrompt() and use Chat completions for it.</p>
<p>  This function returns a yes or no based on which API call is made either to ChatGPT API or DALL-E API.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680944704997/c1186abc-f624-42a7-b170-b7a170d5d871.png" alt class="image--center mx-auto" /></p>
</li>
<li><pre><code class="lang-dart">  Future&lt;<span class="hljs-built_in">String</span>&gt; isArtPrompt(<span class="hljs-built_in">String</span> prompt) <span class="hljs-keyword">async</span> {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">final</span> res = <span class="hljs-keyword">await</span> http.post(
            <span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">"https://api.openai.com/v1/chat/completions"</span>),
            headers: {
              <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
              <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer <span class="hljs-subst">$OpenAIApiKey</span>'</span>
            },
            body: jsonEncode({
              <span class="hljs-string">'model'</span>: <span class="hljs-string">"gpt-3.5-turbo"</span>,
              <span class="hljs-string">'messages'</span>: [
                {
                  <span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>,
                  <span class="hljs-string">"content"</span>:
                      <span class="hljs-string">"Does this message want to generate an AI picture, image, art or anything similar? <span class="hljs-subst">$prompt</span> . Simply answer with a yes or no."</span>
  <span class="hljs-comment">//this content asks chatGPT and retrieves answer in yes or no </span>
                }
              ],
            }));
        <span class="hljs-built_in">print</span>(res.body);
        <span class="hljs-keyword">if</span> (res.statusCode == <span class="hljs-number">200</span>) {
          <span class="hljs-built_in">String</span> content =
              jsonDecode(res.body)[<span class="hljs-string">'choices'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'message'</span>][<span class="hljs-string">"content"</span>];
          content = content.trim(); <span class="hljs-comment">//trimming all space from output</span>
          <span class="hljs-keyword">switch</span> (content) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'yes'</span>:
            <span class="hljs-keyword">case</span> <span class="hljs-string">'Yes'</span>:
            <span class="hljs-keyword">case</span> <span class="hljs-string">'Yes.'</span>:
            <span class="hljs-keyword">case</span> <span class="hljs-string">'yes.'</span>:
                 <span class="hljs-keyword">final</span> res = <span class="hljs-keyword">await</span> dallEAPI(prompt); 
                 <span class="hljs-comment">// dalle api call if yes</span>
              <span class="hljs-keyword">return</span> res;
            <span class="hljs-keyword">default</span>:
              <span class="hljs-keyword">final</span> res = <span class="hljs-keyword">await</span> chatGPTAPI(prompt);
              <span class="hljs-comment">// ChatGPT api call if no</span>
              <span class="hljs-keyword">return</span> res;
          }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-string">"An internal error!!"</span>;
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-keyword">return</span> e.toString();
      }
    }
</code></pre>
<p>  Now the functions chatGPT API and DALL-E are as follows</p>
</li>
<li><pre><code class="lang-dart">  <span class="hljs-keyword">final</span> <span class="hljs-built_in">List</span>&lt;<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">String</span>&gt;&gt; messages = [];
  <span class="hljs-comment">// Chat Completetion API call</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; chatGPTAPI(<span class="hljs-built_in">String</span> prompt) <span class="hljs-keyword">async</span> {
      messages.add({<span class="hljs-string">'role'</span>: <span class="hljs-string">'user'</span>, <span class="hljs-string">'content'</span>: prompt});
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">final</span> res = <span class="hljs-keyword">await</span> http.post(
            <span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">"https://api.openai.com/v1/chat/completions"</span>),
            headers: {
              <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
              <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer <span class="hljs-subst">$OpenAIApiKey</span>'</span>
            },
            body: jsonEncode({
              <span class="hljs-string">'model'</span>: <span class="hljs-string">"gpt-3.5-turbo"</span>,
              <span class="hljs-string">'messages'</span>: messages,
            }));
        <span class="hljs-built_in">print</span>(res.body);
        <span class="hljs-keyword">if</span> (res.statusCode == <span class="hljs-number">200</span>) {
          <span class="hljs-built_in">String</span> content =
              jsonDecode(res.body)[<span class="hljs-string">'choices'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'message'</span>][<span class="hljs-string">"content"</span>];
          content = content.trim();
          messages.add({<span class="hljs-string">'role'</span>: <span class="hljs-string">'assistant'</span>, <span class="hljs-string">'content'</span>: content});
          <span class="hljs-keyword">return</span> content;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-string">"An internal error!!"</span>;
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-keyword">return</span> e.toString();
      }
    }

  <span class="hljs-comment">// image generation API call</span>
  Future&lt;<span class="hljs-built_in">String</span>&gt; dallEAPI(<span class="hljs-built_in">String</span> prompt) <span class="hljs-keyword">async</span> {
      messages.add({<span class="hljs-string">'role'</span>: <span class="hljs-string">'user'</span>, <span class="hljs-string">'content'</span>: prompt});
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">final</span> res = <span class="hljs-keyword">await</span> http.post(
            <span class="hljs-built_in">Uri</span>.parse(<span class="hljs-string">"https://api.openai.com/v1/images/generations"</span>),
            headers: {
              <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
              <span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer <span class="hljs-subst">$OpenAIApiKey</span>'</span>
            },
            body: jsonEncode({
              <span class="hljs-string">'prompt'</span>: prompt,
              <span class="hljs-string">'n'</span>: <span class="hljs-number">1</span>, <span class="hljs-comment">// number of images to be generated</span>
            }));
        <span class="hljs-built_in">print</span>(res.body);
        <span class="hljs-keyword">if</span> (res.statusCode == <span class="hljs-number">200</span>) {
          <span class="hljs-built_in">String</span> imgUrl = jsonDecode(res.body)[<span class="hljs-string">'data'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'url'</span>];
          imgUrl = imgUrl.trim();
          messages.add({<span class="hljs-string">'role'</span>: <span class="hljs-string">'assistant'</span>, <span class="hljs-string">'content'</span>: imgUrl});
          <span class="hljs-keyword">return</span> imgUrl;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-string">"An internal error!!"</span>;
      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-keyword">return</span> e.toString();
      }
    }
</code></pre>
<p>  Thats it !! Now you can use the isArtPrompt() function and pass it your desired prompt, the function will call either of the APIs and give a response which you can use in your Flutter app to showcase the user.</p>
</li>
</ul>
<p>You can check out my Voice assistant Flutter App using ChatGPT API and DALL-E API for text response and image generation based on user prompts(<a target="_blank" href="https://github.com/ratishjain12/ChatGPT-DALLE-FLUTTER-APP">Voice Assistant App</a>).</p>
<p>Make sure to follow me and subscribe to this blog for more tech blogs like this on daily basis, P.S. - your support is much appreciated!!!</p>
]]></content:encoded></item><item><title><![CDATA[What is CRUD functionality? Learn All Crud Operations.]]></title><description><![CDATA[CRUD (Create, Read, Update, Delete) functionality is an essential feature in any application that deals with data. It is a set of operations that allow users to interact with data stored in a database. In this blog, we will explore the importance of ...]]></description><link>https://blog.ratishfolio.com/what-is-crud-functionality-learn-all-crud-operations</link><guid isPermaLink="true">https://blog.ratishfolio.com/what-is-crud-functionality-learn-all-crud-operations</guid><category><![CDATA[Developer]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[coding]]></category><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Mon, 20 Mar 2023 11:30:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679201875081/62ea6361-3ae3-4658-9797-8a3df4aecfff.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>CRUD (Create, Read, Update, Delete) functionality is an essential feature in any application that deals with data. It is a set of operations that allow users to interact with data stored in a database. In this blog, we will explore the importance of CRUD functionality and how it works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679066731911/68d95908-9bd5-42b3-9e44-784e6057ab41.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Create:</strong> The Create operation allows users to create new data entries in the database. This can be done using a web form or an API endpoint. When the user submits the data, it is sent to the server and stored in the database. The data is validated to ensure that it meets the required criteria before it is stored in the database.</p>
<p><strong>Read:</strong> The Read operation allows users to retrieve data from the database. This can be done by querying the database using specific criteria. For example, a user might search for all the products in a specific category or all the users who have signed up in the last week. The data is returned in a format that can be easily understood by the user, such as a table or a list.</p>
<p><strong>Update:</strong> The Update operation allows users to modify existing data in the database. This can be done using a web form or an API endpoint. When the user submits the updated data, it is sent to the server and stored in the database. The data is validated to ensure that it meets the required criteria before it is updated in the database.</p>
<p><strong>Delete:</strong> The Delete operation allows users to remove data from the database. This can be done using a web form or an API endpoint. When the user confirms the deletion, the data is removed from the database. It is important to note that this operation should be used with caution, as it can result in the loss of important data.</p>
<p>Suppose, you are on Instagram and you create a post, this is called create functionality and now in that post after uploading you are trying to change the caption of the post, this is update functionality similarly you delete a post triggering delete functionality and while you are searching for an account to follow you are triggering read functionality as you are trying to search the account which Instagram will provide by reading from its database.</p>
<p>The above example, tells you that CRUD functionality is most crucial for big tech companies to maintain their product.</p>
<p>The importance of CRUD functionality: CRUD functionality is important for several reasons. First, it allows users to interact with data simply and intuitively. This makes it easier for users to manage their data and reduces the likelihood of errors.</p>
<p>Second, CRUD functionality ensures that data is consistent and accurate. When users create, read, update, and delete data using a standardized set of operations, the data remains consistent across the entire system.</p>
<p>Finally, CRUD functionality helps to ensure the security of the system. By controlling access to the Create, Read, Update, and Delete operations, the system can prevent unauthorized access to sensitive data.</p>
<p>In conclusion, CRUD functionality is an essential feature of any application that deals with data. It provides users with a simple and intuitive way to manage their data, ensures the consistency and accuracy of the data, and helps to ensure the security of the system.</p>
<h2 id="heading-to-learn-more-about-what-is-an-api-checkout-my-blog">To Learn More about what is an API checkout my Blog</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://devcon.hashnode.dev/what-is-an-api-how-does-it-work-and-why-it-is-very-important-for-businesses-around-the-world">https://devcon.hashnode.dev/what-is-an-api-how-does-it-work-and-why-it-is-very-important-for-businesses-around-the-world</a></div>
]]></content:encoded></item><item><title><![CDATA[What is an API? How does it work and why it is very important for Businesses around the world]]></title><description><![CDATA[An API is an Application Programming Interface which is a set of tools that allow developers to create software and applications. API provides many facilities from providing access to data or services to providing an interface for developers to creat...]]></description><link>https://blog.ratishfolio.com/what-is-an-api-how-does-it-work-and-why-it-is-very-important-for-businesses-around-the-world</link><guid isPermaLink="true">https://blog.ratishfolio.com/what-is-an-api-how-does-it-work-and-why-it-is-very-important-for-businesses-around-the-world</guid><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Blogging]]></category><category><![CDATA[Developer]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sat, 04 Mar 2023 11:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677856959624/d693da24-a801-4ec8-8078-eeb7251f043a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>An API is an Application Programming Interface which is a set of tools that allow developers to create software and applications. API provides many facilities from providing access to data or services to providing an interface for developers to create applications that interact with other software.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677647843051/b690396d-f559-4e22-9e90-c25248db55e9.png" alt class="image--center mx-auto" /></p>
<p>APIs are an essential part of software development and they are becoming highly important for businesses around the world as they are moving their operations to the cloud. APIs allow applications to access data and interact with other applications seamlessly and efficiently.</p>
<p>For example, suppose you are building an app which allows users to search for weather conditions across countries and states for this you can use a Weather API which has all the data and integrates it into your application making it very efficient and easy to build. Moreover, you can also add more features to your app by using multiple APIs.</p>
<p>Without APIs, most of your favourite software wouldn't exist today such as Google Maps API lets you integrate Google Maps on your mobile which is allowing many tech startups like Ola, Uber etc. to provide location service.</p>
<h3 id="heading-why-should-you-use-apis-in-your-application">Why should you use APIs in your application?</h3>
<ul>
<li><p>It extends application capabilities.</p>
</li>
<li><p>Allows developers to reuse certain application logic.</p>
</li>
<li><p>APIs are platform-independent, they deliver data without being affected by the requesting platform.</p>
</li>
<li><p>Enables the app to access outside resources.</p>
</li>
</ul>
<h3 id="heading-so-how-does-an-api-work">So How Does an API Work?</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677676738338/de074208-3736-40e7-8e5b-c8328f991b14.png" alt /></p>
<p>Imagine you are trying to order an item from an online e-commerce store now when you click on buy item your request gets transferred to the backend web server of the e-commerce store via an API request.</p>
<p>Now, the backend server will respond to the API request and pass on your order request to the delivery partner and the delivery partner will deliver the requested item to you.</p>
<p>This process of sending a request is called an API request and the response to the API request is called an API response.</p>
<p>So API helps in providing a secured layer between applications and the data they access, protecting sensitive information from unauthorized access.</p>
<h2 id="heading-types-of-apis">Types of APIs</h2>
<ul>
<li><p><strong>Open/Public APIs</strong> -</p>
<p>  These APIs are available to everyone as a result, open APIs typically have relatively low authentication and authorization measures and are often restricted in the assets they share. These are either free to access or have a subscription fee.</p>
</li>
<li><p><strong>Partner APIs</strong> -</p>
<p>  Partner APIs are shared externally, but only among those with a business relationship with the API company. Access is limited to authorized clients with official licenses</p>
</li>
<li><p><strong>Internal APIs</strong> -</p>
<p>  internal APIs (also called private APIs) are not intended for use by third parties. Internal APIs are only made available for use inside a company and are meant to streamline data transfers between teams and systems.</p>
</li>
<li><p><strong>Composite APIs</strong> -</p>
<p>  Composite APIs combine multiple APIs allowing developers to bundle calls or requests and receive one unified response from different servers.</p>
</li>
</ul>
<h3 id="heading-10-apis-you-can-use-in-your-applications">10 APIs you can use in your Applications -</h3>
<ul>
<li><p>Google Maps API (<a target="_blank" href="https://mapsplatform.google.com/maps-products/#embed">Checkout</a>)</p>
</li>
<li><p>Omdb API (<a target="_blank" href="https://www.omdbapi.com/">Checkout</a>)</p>
</li>
<li><p>Open Weather Map API (<a target="_blank" href="https://openweathermap.org/">Checkout</a>)</p>
</li>
<li><p>Spotify API (<a target="_blank" href="https://developer.spotify.com/documentation/web-api/">Checkout</a>)</p>
</li>
<li><p>Coinbase API (<a target="_blank" href="https://help.coinbase.com/en/cloud/api">Checkout</a>)</p>
</li>
<li><p>Fake Store API (Checkout)</p>
</li>
<li><p>Novu API (<a target="_blank" href="https://docs.novu.co/api/overview/">Checkout</a>)</p>
</li>
<li><p>Zenserp API (<a target="_blank" href="https://zenserp.com/">Checkout</a>)</p>
</li>
<li><p>Number verification API (<a target="_blank" href="https://numverify.com/?utm_source=Sitepoint&amp;utm_medium=Leads%20Acquisition&amp;utm_content=articlenumverify">Checkout</a>)</p>
</li>
<li><p>Stripe API (<a target="_blank" href="https://stripe.com/docs/api">Checkout</a>)</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Learn To Think Recursively and Solve Recursion Problems in an Interview in 4 Steps]]></title><description><![CDATA[What is Recursion?

The process in which a function calls itself either directly or indirectly is called recursion and the corresponding function is called a recursive function with recursion you can solve some complex problems quite easily examples ...]]></description><link>https://blog.ratishfolio.com/learn-to-think-recursively-and-solve-recursion-problems-in-an-interview-in-4-steps</link><guid isPermaLink="true">https://blog.ratishfolio.com/learn-to-think-recursively-and-solve-recursion-problems-in-an-interview-in-4-steps</guid><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[Recursion]]></category><category><![CDATA[DSA]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Ratish Jain]]></dc:creator><pubDate>Sun, 05 Feb 2023 18:01:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675620028223/901a09ec-f307-4781-90d9-8b3caee0dea7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-recursion">What is Recursion?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675619578628/d00e72bb-01e5-42f5-8d3d-f553862f36a4.png" alt class="image--center mx-auto" /></p>
<p>The process in which a function calls itself either directly or indirectly is called recursion and the corresponding function is called a recursive function with recursion you can solve some complex problems quite easily examples of such problems are tower of hanoi, tree traversals, DFS of graph etc.</p>
<p>properties of recursion -</p>
<ul>
<li><p>performing the same operation multiple times with different inputs</p>
</li>
<li><p>At every step, the input is reduced to make the problem smaller</p>
</li>
<li><p>A base condition is required to stop the recursion process otherwise infinite loop will occur</p>
</li>
</ul>
<p>Many people when try to solve a problem using recursion they try to trace each recursive call to determine what each function call is doing but this is a trap of endless confusion to avoid this trap you need not need to know what each function call is doing rather you just need to pick a subproblem and believe that your function will solve the rest of the problem, you need to take a leap of faith and believe in your function.</p>
<h2 id="heading-steps-to-approach-a-problem-and-think-recursively">Steps to approach a problem and think recursively</h2>
<ul>
<li><p>Step 1) Know what your function is supposed to do.</p>
</li>
<li><p>Step 2) Determine a subproblem from the main problem.</p>
</li>
<li><p>Step 3) Find out the answer to the subproblem and use it to solve the main problem.</p>
</li>
<li><p>Step 4) Last step is to determine the base condition of the problem</p>
</li>
</ul>
<p>Let's take a simple problem such as finding the sum of 1 to n numbers and follow the 4 steps mentioned above to solve the problem.</p>
<h3 id="heading-know-what-your-function-is-supposed-to-do">Know what your function is supposed to do</h3>
<p>This is the most basic and general step but a very important one. Now in the question above, we know that we need to calculate the sum of numbers from 1 to n</p>
<p>So our function needs to take a value n and return the sum from 1 up to n so our inputs of the function cant exceed n.</p>
<p>let's say the function is sumTo().</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sumTo</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span></span>{

}
</code></pre>
<h3 id="heading-determine-the-subproblem-from-the-main-problem">Determine the subproblem from the main problem</h3>
<p>A subproblem is any problem that is smaller than the main problem and it is important to find the appropriate subproblem</p>
<p>In the above case, the subproblem can be solving the sum of all numbers less than n.</p>
<p>so the appropriate subproblem will be solving for the sum of (n-1) numbers.</p>
<h3 id="heading-finding-out-the-answer-to-the-subproblem-and-using-it-to-solve-the-main-problem">Finding out the answer to the subproblem and using it to solve the main problem</h3>
<p>The solution for the sum of n-1 numbers will be</p>
<p>sumToSubProblem = 1+2+3 ...... + n-1</p>
<p>Now to find the solution to the main problem we just need to add the nth number -</p>
<p>mainProblem = subProblem + n</p>
<p>So the code will be</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sumTo</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span></span>{
     <span class="hljs-keyword">int</span> subProblem = sumTo(n<span class="hljs-number">-1</span>);
     <span class="hljs-keyword">return</span> subProblem + n;
}
</code></pre>
<h3 id="heading-the-last-step-is-to-find-the-base-case-for-the-recursion-process">The last step is to find the base case for the recursion process -</h3>
<p>A base case condition is any condition that stops the recursion process and is necessary to avoid the infinite loop.</p>
<p>So to find the base condition we need to find at what input the function becomes irrelevant in the above case we know if n = 0 the function will become irrelevant as 0+0 will give 0 only.</p>
<p>so on applying this base condition we will have a complete solution to the main problem</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sumTo</span><span class="hljs-params">(n<span class="hljs-number">-1</span>)</span></span>{
    <span class="hljs-keyword">if</span>(n == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">int</span> subProblem = sumTo(n<span class="hljs-number">-1</span>);
    <span class="hljs-keyword">return</span> subProblem + n;
}
</code></pre>
<h2 id="heading-more-examples">More examples -</h2>
<p>Reversing a string using recursion</p>
<p>As per the first step, we know that we need a function that takes a string as input and return a reversed string.</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-built_in">string</span> <span class="hljs-title">reverseString</span><span class="hljs-params">(<span class="hljs-built_in">string</span> s)</span></span>{

}
</code></pre>
<p>Now we need to determine a subproblem which in this case will be leaving the first character and solving for the rest of the characters.</p>
<p>ie - string s = "hello";</p>
<p>so the subproblem will be reversing "ello" to "olle" and adding the first character 'h' in the end.</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-built_in">string</span> <span class="hljs-title">reverseString</span><span class="hljs-params">(<span class="hljs-built_in">string</span> s)</span></span>{
     <span class="hljs-built_in">string</span> substring = s.substr(<span class="hljs-number">1</span>,s.length());
     <span class="hljs-built_in">string</span> reversedSubProblem = reverseString(substring);
     <span class="hljs-keyword">return</span> reversedSubProblem + s[<span class="hljs-number">0</span>];
}
</code></pre>
<p>Now the last step will be finding the base case condition which in this case will be if string s become empty string because that is the most basic string a user can provide.</p>
<p>so,</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-built_in">string</span> <span class="hljs-title">reverseString</span><span class="hljs-params">(<span class="hljs-built_in">string</span> s)</span></span>{
     <span class="hljs-keyword">if</span>(s == <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
     <span class="hljs-built_in">string</span> substring = s.substr(<span class="hljs-number">1</span>,s.length());
     <span class="hljs-built_in">string</span> reversedSubProblem = reverseString(substring);
     <span class="hljs-keyword">return</span> reversedSubProblem + s[<span class="hljs-number">0</span>];
}
</code></pre>
<p>Similarly to find the nth Fibonacci number the subproblems will be finding the Fibonacci terms (n-1) and (n-2) and the addition of these two terms will give the solution for the nth Fibonacci term.</p>
<p>and the base condition, in this case, will be for n = 0 and n = 1 as there are no two previous terms for these values</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">fibonacci</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span></span>{
    <span class="hljs-keyword">if</span>(n == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    <span class="hljs-keyword">if</span>(n == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">int</span> term1 = fibonacci(n<span class="hljs-number">-1</span>);
    <span class="hljs-keyword">int</span> term2 = fibonacci(n<span class="hljs-number">-2</span>);
    <span class="hljs-keyword">return</span> term1+term2;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675619398478/cbb6ceb4-c237-4329-8fd2-186b695eb6f5.jpeg" alt class="image--center mx-auto" /></p>
]]></content:encoded></item></channel></rss>