<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Anzal Abidi</title>
    <link>https://anzalabidi.dev/</link>
    <description>I build things, then find out what breaks. Lately that has meant AI, taking it from prototype to something a business can actually run on.</description>
    <language>en</language>
    <atom:link href="https://anzalabidi.dev/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Your Wiki Doesn&#39;t Know What It Doesn&#39;t Know</title>
      <link>https://anzalabidi.dev/writing/your-wiki-doesn-t-know-what-it-doesn-t-know/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/your-wiki-doesn-t-know-what-it-doesn-t-know/</guid>
      <pubDate>Wed, 15 Apr 2026 06:06:07 GMT</pubDate>
      <description>Why every LLM-powered knowledge base is broken the same way — and what we built instead The Karpathy Moment On April 4, 2026, Andrej Karpathy published a gist describing a pattern: use an LLM to mai</description>
      <category>llm</category>
      <category>Wikipedia</category>
      <category>AI</category>
      <category>knowledge</category>
      <category>software development</category>
      <content:encoded><![CDATA[<p><em>Why every LLM-powered knowledge base is broken the same way — and what we built instead</em></p>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182710/quicky-wiki-blog/hero-vangogh.jpg" alt="Hero Image"></p>
<hr>
<h2>The Karpathy Moment</h2>
<p>On April 4, 2026, Andrej Karpathy published a <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">gist</a> describing a pattern: use an LLM to maintain a personal wiki from raw source documents. Within 48 hours: 5,000+ stars, 1,300+ forks, and a dozen implementations.</p>
<p>Everyone rushed to build it. We looked at what they all built — and noticed they all missed the same things.</p>
<hr>
<h2>The Six Gaps Nobody Filled</h2>
<p>Every implementation that appeared — MindOS, agent-wiki, obsidian-wiki, second-brain, cerefox, LLM-wiki — shares the same blind spots:</p>
<p><strong>1. Static snapshots.</strong> The wiki is a pile of current-state markdown. You can&#39;t ask &quot;what did I believe about X last month?&quot; or &quot;how has my thesis evolved?&quot; Git blame shows file changes. It doesn&#39;t show <em>belief changes</em>.</p>
<p><strong>2. Binary confidence.</strong> A fact is either in the wiki or it isn&#39;t. But some claims are backed by five peer-reviewed papers and others by a single tweet. There&#39;s no way to know which is which.</p>
<p><strong>3. No metabolism.</strong> Once a page is written, it sits there forever. That competitive analysis from three months ago? Probably stale. That API reference from last week? Still fresh. Nothing models freshness or decay.</p>
<p><strong>4. No gap discovery.</strong> Lint finds broken links. It doesn&#39;t find <em>blind spots</em>. If your wiki covers ML architectures but never mentions training data quality, no existing system will notice.</p>
<p><strong>5. No knowledge diffs.</strong> When you ingest a new source, you get updated pages. You don&#39;t get &quot;before this paper, you believed X; now the evidence suggests Y; these 3 claims are stronger, this 1 is weaker.&quot;</p>
<p><strong>6. Single output format.</strong> Everything renders to markdown. But knowledge has many useful forms — flashcards, slide decks, interactive graphs, timelines, fine-tuning datasets.</p>
<p>These aren&#39;t edge cases. These are fundamental properties of how human knowledge actually works. And no one was building for them.</p>
<hr>
<h2>The Core Thesis</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182713/quicky-wiki-blog/knowledge-compiler-vangogh.jpg" alt="Knowledge Compiler"></p>
<blockquote>
<p>A wiki is not a document store. It&#39;s a <strong>knowledge compiler</strong> — a system that takes raw sources as input and produces <em>verified, temporally-aware, confidence-scored, interlinked knowledge</em> as output, compilable to any format.</p>
</blockquote>
<p>That&#39;s the idea behind <a href="https://github.com/anzal1/quicky-wiki">Quicky Wiki</a>. An open-source, CLI-first tool that treats your knowledge the way a compiler treats code: with rigor, with type safety, and with the understanding that correctness is a spectrum, not a binary.</p>
<hr>
<h2>How It Works</h2>
<pre><code>Source Document (PDF, URL, markdown, notes)
     ↓
LLM Extraction → Claims (atomic, verifiable, with confidence scores)
     ↓                               ↓
Knowledge Graph (SQLite)          Epistemic Events (temporal log)
     ↓
Compiled Outputs → Wiki pages, slides, flashcards, graph, timeline
     ↓
Dashboard (interactive visualization + chat)
</code></pre>
<p>You drop a document into <code>raw/</code>. The compiler breaks it into atomic <em>claims</em> — not paragraphs, not summaries, but individual verifiable statements. Each claim gets a confidence score based on source quality, corroboration, and recency. These claims link into a knowledge graph that tracks how they relate to each other.</p>
<pre><code class="language-bash">npx quicky-wiki init --name &quot;My Research&quot;
qw ingest paper.pdf --type paper --quality peer-reviewed
qw ingest https://arxiv.org/abs/2401.12345
qw serve    # → http://localhost:3737
</code></pre>
<p>Three commands and you have a confidence-scored knowledge base with an interactive dashboard.</p>
<hr>
<h2>Confidence Isn&#39;t a Feature. It&#39;s the Architecture.</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182706/quicky-wiki-blog/confidence-vangogh.jpg" alt="Confidence Scoring"></p>
<p>Every claim in Quicky Wiki carries a confidence score from 0.0 to 1.0, computed from:</p>
<ul>
<li><strong>Source count</strong> — More independent sources confirming a claim → higher confidence</li>
<li><strong>Source quality</strong> — A peer-reviewed paper weighs more than a blog post, which weighs more than a tweet</li>
<li><strong>Recency</strong> — Newer sources are weighted higher for fast-moving fields</li>
<li><strong>Corroboration</strong> — Do your sources agree or contradict?</li>
<li><strong>Dependency depth</strong> — If a claim depends on other claims, confidence compounds downward</li>
</ul>
<p>This isn&#39;t decoration. It&#39;s the foundation. When you query your wiki, you can ask:</p>
<pre><code class="language-bash">qw query --min-confidence 0.8 &quot;quantum error correction&quot;   # only high-confidence claims
qw query --contested &quot;scaling laws&quot;                         # where sources disagree
qw claims --weakest --limit 10                              # your shakiest beliefs
</code></pre>
<p>When a foundational claim gets weakened by new evidence, Quicky Wiki doesn&#39;t just update that one claim. It runs a <strong>cascade</strong> — tracing every downstream claim that depends on it and adjusting their confidence accordingly. One challenged assumption can ripple through your entire knowledge graph.</p>
<hr>
<h2>Knowledge That Decays, Resurfaces, and Challenges Itself</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182715/quicky-wiki-blog/metabolism-vangogh.jpg" alt="Metabolism"></p>
<p>We call it the <strong>metabolism engine</strong>. It&#39;s what keeps a knowledge base alive instead of slowly rotting.</p>
<p><strong>Decay.</strong> Claims that haven&#39;t been reinforced by new sources gradually lose confidence. That competitive analysis from six months ago auto-flags as potentially stale. This isn&#39;t arbitrary — it models the real-world phenomenon that knowledge has a half-life.</p>
<p><strong>Resurfacing.</strong> Like spaced repetition for your entire wiki. The system surfaces concepts you haven&#39;t engaged with recently: &quot;You haven&#39;t revisited your notes on X in 45 days. 3 new sources have appeared since then.&quot;</p>
<p><strong>Red-teaming.</strong> Periodic adversarial self-critique powered by the LLM: &quot;What claims in this wiki would a domain expert challenge? What&#39;s the strongest counter-argument to your central thesis?&quot;</p>
<pre><code class="language-bash">qw metabolism --report        # full knowledge health report
qw metabolism --decay         # apply confidence decay
qw metabolism --resurface     # find stale claims worth revisiting
qw metabolism --redteam       # challenge your high-confidence claims
</code></pre>
<pre><code>┌─────────────────────────────────────────────┐
│  KNOWLEDGE HEALTH REPORT                    │
├─────────────────────────────────────────────┤
│  Total claims: 847                          │
│  High confidence (&gt;0.8): 312 (37%)          │
│  Medium (0.4-0.8): 419 (49%)               │
│  Low (&lt;0.4): 116 (14%)                      │
│                                             │
│  ⚠️  Stale (&gt;30 days, no reinforcement): 23 │
│  ⚡ Contested (sources disagree): 8          │
│  🔗 Cascade risk (depends on weak claims): 5│
│  🕳️  Gaps detected: 12                      │
└─────────────────────────────────────────────┘
</code></pre>
<p>No other LLM wiki does this. Most don&#39;t even have the concept.</p>
<hr>
<h2>Differential Ingestion: See What Changed in Your Understanding</h2>
<p>When you ingest a new source, the system doesn&#39;t silently update pages. It shows you a <strong>knowledge diff</strong> — exactly how your understanding shifted:</p>
<pre><code>$ qw ingest paper-new-scaling-laws.pdf

📄 Ingested: &quot;Scaling Laws Revisited&quot; (Chen et al., 2026)

KNOWLEDGE DIFF:
━━━━━━━━━━━━━━
  REINFORCED (3 claims):
  ✅ &quot;Loss scales as power law with compute&quot; — confidence 0.72 → 0.88
  ✅ &quot;Data quality matters more than quantity&quot; — confidence 0.65 → 0.78

  CHALLENGED (1 claim):
  ⚠️  &quot;Scaling laws plateau above 1T parameters&quot;
      Your wiki says: plateau likely (confidence 0.60)
      This paper says: no plateau observed up to 10T
      New confidence: 0.35
      → 2 downstream claims affected

  NEW CONCEPTS (2):
  🆕 &quot;Inference-time scaling&quot; — new concept page created
  🆕 &quot;Test-time compute&quot; — linked to existing &quot;inference optimization&quot; page

  GAPS IDENTIFIED (1):
  🕳️  Paper references &quot;mixture of experts efficiency&quot; — no wiki page exists
</code></pre>
<p>Every ingestion is a learning event. And the system makes the learning visible.</p>
<hr>
<h2>The Discovery Engine: What Should You Learn Next?</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182708/quicky-wiki-blog/discovery-vangogh.jpg" alt="Discovery"></p>
<p>Most wikis wait passively for you to feed them. Quicky Wiki identifies what&#39;s missing and suggests where to look:</p>
<pre><code class="language-bash">qw discover --mode gaps            # what&#39;s missing in your knowledge?
qw discover --mode horizon         # frontier topics you should explore
qw discover --mode bridges         # connections between distant concepts
qw discover --mode contradictions  # conflicting claims to resolve
</code></pre>
<p><strong>Gap analysis</strong> finds blind spots: &quot;Your wiki discusses concepts A, B, and D but never C, which connects them.&quot;</p>
<p><strong>Horizon scanning</strong> looks ahead: &quot;Based on your research interests, here are 5 recent papers you should consider ingesting.&quot;</p>
<p><strong>Bridge detection</strong> finds cross-domain connections: &quot;Your neuroscience notes and your ML notes both discuss attention mechanisms but never cross-reference.&quot;</p>
<hr>
<h2>Compile Your Knowledge Into Anything</h2>
<p>The wiki is the source of truth. But the output doesn&#39;t have to be markdown:</p>
<pre><code class="language-bash">qw compile slides --topic &quot;quantum error correction&quot;    # Marp slide deck
qw compile anki --topic &quot;ML scaling laws&quot;               # Anki flashcards
qw compile graph --interactive                          # D3 knowledge graph
qw compile timeline --topic &quot;quantum computing&quot;         # temporal visualization
qw compile markdown                                     # Obsidian-compatible wiki
</code></pre>
<p>Same knowledge. Different lenses. A concept you explore as a graph, study as flashcards, and present as slides — all generated from the same underlying claims.</p>
<hr>
<h2>Built for AI Agents</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1776182714/quicky-wiki-blog/mcp-vangogh.jpg" alt="MCP Server"></p>
<p>Quicky Wiki includes a built-in <a href="https://modelcontextprotocol.io/">Model Context Protocol</a> server. Point Claude Desktop, Cursor, or any MCP client at it:</p>
<pre><code class="language-bash">qw mcp              # stdio mode (for Claude Desktop, etc.)
qw mcp --http       # HTTP mode for remote agents
</code></pre>
<p>Your AI agent can query the knowledge base, search across content with full-text search, list and filter entities, ingest new sources, and update metadata — all through the MCP protocol. The wiki becomes a first-class tool in any AI agent&#39;s toolkit.</p>
<p>You can also embed the engine directly in your Node.js application:</p>
<pre><code class="language-javascript">import { KnowledgeStore, ingestSource, queryKnowledge } from &quot;quicky-wiki&quot;;

const store = new KnowledgeStore(&quot;./data/graph.sqlite&quot;);
await ingestSource(store, &quot;research-paper.pdf&quot;, { kind: &quot;paper&quot; });
const answer = await queryKnowledge(store, &quot;What are the key findings?&quot;);
// → Answer with confidence scores and citations
</code></pre>
<p>No subprocess, no server, no MCP overhead. Just the knowledge compiler as a library.</p>
<hr>
<h2>The Dashboard</h2>
<p>The web dashboard gives you everything at a glance:</p>
<ul>
<li><strong>Knowledge Graph</strong> — Interactive canvas visualization. Hover to see connections, click to explore.</li>
<li><strong>Claims</strong> — Every extracted claim with its confidence score, sources, and history.</li>
<li><strong>Pages</strong> — Wiki pages grouped by entity kind. Obsidian-style wikilinks work: <code>[[Page Title]]</code> is clickable.</li>
<li><strong>Timeline</strong> — Temporal view of how your knowledge has evolved.</li>
<li><strong>Health</strong> — Stale claims, contradictions, gaps, cascade risks.</li>
<li><strong>Ask Wiki</strong> — Chat with your knowledge base. Get answers with confidence scores and source citations.</li>
</ul>
<hr>
<h2>Why This Matters</h2>
<p>We&#39;re in an era where LLMs can generate convincing text about anything. That&#39;s the problem — <em>everything sounds equally true</em>. There&#39;s no built-in mechanism to tell you &quot;this fact is well-supported&quot; vs. &quot;this fact came from one source and contradicts newer evidence.&quot;</p>
<p>Quicky Wiki doesn&#39;t solve hallucination. What it does is make the <em>epistemic status</em> of your knowledge explicit. Every claim has a provenance trail. Every confidence score has a reason. When something decays, you know. When something contradicts, you see it. When there&#39;s a gap, the system finds it.</p>
<p>Knowledge management shouldn&#39;t be a filing system. It should be a living process — one that strengthens over time, weakens when evidence changes, and tells you honestly what it doesn&#39;t know.</p>
<hr>
<h2>Get Started</h2>
<pre><code class="language-bash">npm install -g quicky-wiki
qw init --name &quot;My Research&quot;
qw ingest your-sources/
qw serve
</code></pre>
<p>Open <code>http://localhost:3737</code>. That&#39;s it.</p>
<p>The source is at <a href="https://github.com/anzal1/quicky-wiki">github.com/anzal1/quicky-wiki</a>. MIT licensed. Stars and contributions welcome.</p>
<hr>
]]></content:encoded>
    </item>
    <item>
      <title>The Authentication Gap That Every AI Agent Lives In</title>
      <link>https://anzalabidi.dev/writing/the-authentication-gap-that-every-ai-agent-lives-in/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/the-authentication-gap-that-every-ai-agent-lives-in/</guid>
      <pubDate>Sun, 15 Feb 2026 15:38:18 GMT</pubDate>
      <description>Why existing auth was never built for autonomous agents — and how we fixed it with open-source cryptography The Uncomfortable Truth Your AI agent is authenticating like it&#39;s 2009. Every day, millions of AI agents make HTTP requests on behalf of the h...</description>
      <category>AI</category>
      <category>agentic AI</category>
      <category>authentication</category>
      <category>authorization</category>
      <category>Computer Science</category>
      <category>Security</category>
      <category>Artificial Intelligence</category>
      <content:encoded><![CDATA[<p><em>Why existing auth was never built for autonomous agents — and how we fixed it with open-source cryptography</em></p>
<h2>The Uncomfortable Truth</h2>
<p>Your AI agent is authenticating like it&#39;s 2009.</p>
<p>Every day, millions of AI agents make HTTP requests on behalf of the humans who run them. They create pull requests. They read databases. They call third-party services. And every single time, they authenticate with the same mechanism a curl script would — a static API key or an OAuth token designed for a human clicking &quot;Allow&quot; in a browser.</p>
<p>This works. Until it doesn&#39;t.</p>
<hr>
<h2>The Gap Nobody Talks About</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169540/pact-blog/identity-gap.jpg" alt="The Identity Gap"></p>
<p>Here&#39;s what&#39;s broken — not in theory, but in production, right now:</p>
<p><strong>No provenance.</strong> When an agent hits your API with a bearer token, you see the token. You don&#39;t see the human behind it. You don&#39;t see the chain of trust. If the agent goes rogue — context poisoned, prompt injected, session hijacked — the token still works.</p>
<p><strong>No scope boundaries.</strong> A human gives their agent access to &quot;the GitHub API.&quot; They mean &quot;create PRs on this one repo.&quot; The token doesn&#39;t know that. It carries the full blast radius of every permission the human has.</p>
<p><strong>No accountability.</strong> When something goes wrong — and it will — there&#39;s no audit trail that says &quot;this specific agent, delegated by this specific human, with these specific permissions, signed this specific request at this specific time.&quot; There&#39;s a token in a log. Maybe.</p>
<p><strong>No identity.</strong> The agent has no cryptographic existence. Clone its token, and nobody can tell you apart.</p>
<hr>
<h2>Why Existing Solutions Don&#39;t Fit</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169529/pact-blog/broken-auth.jpg" alt="Broken Lock"></p>
<p>We looked at everything:</p>
<p>→ <strong>OAuth 2.0</strong> — A delegation framework where the delegator is a browser redirect and the scope is a string the provider invented. Designed for users clicking buttons, not agents operating autonomously.</p>
<p>→ <strong>API Keys</strong> — Shared secrets with no provenance, no enforced expiry, and no capability narrowing. The skeleton key approach.</p>
<p>→ <strong>mTLS</strong> — Proves a machine, not a delegation chain. No concept of &quot;who authorized this machine to do this specific thing.&quot;</p>
<p>→ <strong>OIDC for Agents</strong> — Adds agent claims to existing identity providers. Still centralized. Still requires token introspection endpoints.</p>
<p>None of them answer the three questions every provider should be asking:</p>
<ol>
<li><strong>Which human authorized this agent?</strong></li>
<li><strong>What specifically is the agent allowed to do?</strong></li>
<li><strong>Can I verify all of this without calling anyone?</strong></li>
</ol>
<hr>
<h2>Enter Pact</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169544/pact-blog/pact-protocol.jpg" alt="Pact Protocol"></p>
<p>Pact is a <strong>protocol</strong> — not a service, not a platform. Like HTTPS, but for agents proving who they are, who sent them, and what they&#39;re allowed to do.</p>
<p><strong>The core idea is simple:</strong></p>
<p>Humans sign cryptographic delegations to agents. Agents carry these delegation chains with every request. Providers verify everything locally — no token introspection, no authorization servers, no network calls. Just math.</p>
<hr>
<h2>How It Works</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169527/pact-blog/architecture.jpg" alt="Architecture"></p>
<p>The protocol has five primitives:</p>
<table>
<thead>
<tr>
<th>Primitive</th>
<th>What It Does</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Identity</strong></td>
<td>Ed25519 keypair. ID = <code>sha256(public_key)</code>. No registration needed.</td>
</tr>
<tr>
<td><strong>Delegation</strong></td>
<td>Signed capability grant: human → agent, narrowing-only, with expiry</td>
</tr>
<tr>
<td><strong>Capability</strong></td>
<td>Machine-parseable permission: <code>resource:action,constraint=value</code></td>
</tr>
<tr>
<td><strong>Request Signing</strong></td>
<td>Per-request Ed25519 signature over method + path + timestamp + body</td>
</tr>
<tr>
<td><strong>Verification</strong></td>
<td>Walk chain → check sigs → check caps → check freshness. All local.</td>
</tr>
</tbody></table>
<h3>The Flow</h3>
<pre><code>Human (Alice)
  │
  │  Signs delegation: &quot;Agent X can do api:read, api:write for 1 hour&quot;
  │
  ▼
Agent (carries chain)
  │
  │  Makes HTTP request, signs it with own key
  │  Attaches: identity + delegation chain + signature
  │
  ▼
Provider
  │
  │  Walks delegation chain (every signature valid?)
  │  Capabilities cover this endpoint?
  │  Request signature fresh?
  │  → All local. Zero network calls.
  │
  ▼
  Verified. ✓
</code></pre>
<hr>
<h2>Capability Narrowing — The Key Insight</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169532/pact-blog/capability-narrowing.jpg" alt="Capability Narrowing"></p>
<p>This is what makes Pact fundamentally different from scope-based auth.</p>
<p>Delegations are <strong>narrowing-only</strong>. A human can delegate <code>storage:*</code> to an agent. That agent can sub-delegate <code>storage:read</code> to a sub-agent. But the sub-agent can never escalate back to <code>storage:write</code>. It&#39;s mathematically enforced — not by policy, but by cryptographic signatures.</p>
<pre><code>Human: storage:*
  └→ Agent A: storage:read, storage:write
       └→ Agent B: storage:read          ← Can narrow
       └→ Agent C: storage:delete        ← REJECTED (escalation)
</code></pre>
<p>Capabilities support glob patterns, numeric constraints, and hierarchical resources:</p>
<pre><code>github:pr:create,repo=myorg/*           ← Only PRs in myorg repos
api:write,max_cost&lt;100                  ← Spend limit
storage:read,path=/data/public/**       ← Path-scoped access
</code></pre>
<hr>
<h2>Cross-Language Proof</h2>
<p>We didn&#39;t just build a protocol spec. We built two complete implementations — <strong>Go</strong> and <strong>Python</strong> — and proved they work together.</p>
<p>A Python agent creates an Ed25519 keypair, obtains a delegation from a Go server, signs HTTP requests with the Python SDK, and the Go server verifies every signature. Different languages. Same bytes. Same math.</p>
<p><strong>The test:</strong> 88 cross-language test vectors validating byte-level compatibility — seed derivation, canonical JSON, capability narrowing, content digests, delegation signatures.</p>
<p><strong>The demo:</strong> A 7-step end-to-end flow:</p>
<ol>
<li>✓ Python agent creates identity</li>
<li>✓ Obtains delegation from Go server</li>
<li>✓ Authenticated read (api:read)</li>
<li>✓ Authenticated write (api:write)</li>
<li>✓ Correctly denied (lacks deploy:create)</li>
<li>✓ Ephemeral session identity works</li>
<li>✓ Sub-delegation (agent → sub-agent) works</li>
</ol>
<hr>
<h2>What Makes Pact Different</h2>
<table>
<thead>
<tr>
<th></th>
<th>OAuth 2.0</th>
<th>API Keys</th>
<th>mTLS</th>
<th><strong>Pact</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Proves delegation chain</strong></td>
<td>No</td>
<td>No</td>
<td>No</td>
<td><strong>Yes</strong></td>
</tr>
<tr>
<td><strong>Capability narrowing</strong></td>
<td>Provider-defined</td>
<td>No</td>
<td>No</td>
<td><strong>Delegator-defined</strong></td>
</tr>
<tr>
<td><strong>Per-request signatures</strong></td>
<td>No (bearer)</td>
<td>No (shared secret)</td>
<td>Yes (TLS)</td>
<td><strong>Yes (app layer)</strong></td>
</tr>
<tr>
<td><strong>Offline verification</strong></td>
<td>No (introspection)</td>
<td>No (DB lookup)</td>
<td>Partial</td>
<td><strong>Fully local</strong></td>
</tr>
<tr>
<td><strong>Agent-native</strong></td>
<td>No</td>
<td>No</td>
<td>No</td>
<td><strong>Yes</strong></td>
</tr>
<tr>
<td><strong>Zero dependencies</strong></td>
<td>Auth server</td>
<td>Key store</td>
<td>CA</td>
<td><strong>Nothing</strong></td>
</tr>
</tbody></table>
<hr>
<h2>The Technical Choices</h2>
<p><strong>Ed25519 everywhere.</strong> Fast, small signatures (64 bytes), deterministic, no random number generator needed during signing. The same algorithm Signal, SSH, and WireGuard use.</p>
<p><strong>Canonical JSON (RFC 8785).</strong> Delegation payloads are serialized deterministically — sorted keys, no whitespace ambiguity. Same bytes in Go and Python. Same bytes on every platform.</p>
<p><strong>RFC 9421 signatures.</strong> Request signatures cover method, path, authority, timestamp, and body digest. This isn&#39;t a custom scheme — it&#39;s the IETF standard for HTTP message signatures.</p>
<p><strong>Zero dependencies in Go.</strong> The entire implementation uses only the Go standard library. No crypto imports beyond <code>crypto/ed25519</code>. No frameworks. No build complexity.</p>
<hr>
<h2>Session Identity — Solving Agent Ephemerality</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1771169548/pact-blog/sessions.jpg" alt="Session Identity"></p>
<p>Agents are ephemeral. They spin up, do work, and disappear. But they need stable, verifiable identity during their lifetime.</p>
<p>Pact introduces <strong>hierarchical session identity:</strong></p>
<pre><code>Human (long-lived)
  └→ Root Agent (medium-lived, stored keypair)
       └→ Session Agent (ephemeral, in-memory only)
</code></pre>
<p>Session agents get their own Ed25519 keypair, a delegation from the root, and automatic key zeroization when the session ends. The provider still sees a clean delegation chain back to the human.</p>
<hr>
<h2>Try It</h2>
<p>Pact is open source. MIT licensed. Zero dependencies.</p>
<pre><code class="language-bash"># Go
go get github.com/anzal1/pact

# Python
pip install pact-auth

# CLI
pact init --name alice --type human
pact delegate --to agent.pub --capabilities &quot;api:read&quot; --ttl 1h
</code></pre>
<p>The full spec, implementations, and cross-language demo are at <a href="https://github.com/anzal1/pact">github.com/anzal1/pact</a>.</p>
<hr>
<h2>The Bigger Picture</h2>
<p>AI agents are the fastest-growing category of API consumers. They&#39;re operating autonomously, at scale, with credentials designed for a different era.</p>
<p>The question isn&#39;t whether agent authentication needs to evolve. It&#39;s whether the evolution will be centralized — agents authenticating through platforms, gatekeepers, and introspection endpoints — or decentralized, where any agent can prove its authorization to any provider using nothing but cryptography.</p>
<p>Pact bets on the latter. No servers. No platforms. No trust assumptions. Just a keypair, a delegation chain, and a signature on every request.</p>
<hr>
]]></content:encoded>
    </item>
    <item>
      <title>Building Production-Grade Voice AI: The Pain Points Nobody Talks About</title>
      <link>https://anzalabidi.dev/writing/building-production-grade-voice-ai-the-pain-points-nobody-talks-about/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/building-production-grade-voice-ai-the-pain-points-nobody-talks-about/</guid>
      <pubDate>Fri, 06 Feb 2026 18:24:57 GMT</pubDate>
      <description>How we engineered a conversational voice system that actually works The Reality Check Voice AI demos are easy. Production is hard. Real phone calls, real network conditions, real users who don&#39;t speak perfectly—everything breaks. This post shares o...</description>
      <category>voice ai</category>
      <category>AI</category>
      <category>llm</category>
      <category>agentic AI</category>
      <category>RAG</category>
      <category>Computer Science</category>
      <content:encoded><![CDATA[<p><em>How we engineered a conversational voice system that actually works</em></p>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1770401604/voice-blog/hero-vangogh.jpg" alt="Voice AI Pipeline"></p>
<hr>
<h2>The Reality Check</h2>
<p>Voice AI demos are easy. Production is hard. Real phone calls, real network conditions, real users who don&#39;t speak perfectly—everything breaks.</p>
<p>This post shares our journey: <strong>architectural patterns</strong>, not implementation details.</p>
<hr>
<h2>The Cascade Pipeline</h2>
<pre><code>User Audio → STT → LLM → TTS → Speaker Audio
</code></pre>
<p>Simple in theory. In reality:</p>
<ul>
<li><strong>Latency compounds</strong> across each hop</li>
<li><strong>Context bleeds</strong> between stateless services</li>
<li><strong>State fragments</strong> in an inherently stateful conversation</li>
</ul>
<hr>
<h2>The Six Pain Points We Solved</h2>
<h3>1. Turn Detection</h3>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1770401608/voice-blog/turn-detection-vangogh.jpg" alt="Turn Detection"></p>
<p><strong>Problem:</strong> When does the user stop talking? Humans pause mid-sentence, use fillers, have background noise.</p>
<p><strong>Solution:</strong> Layered approach—Voice Activity Detection for audio signals + semantic turn analyzer for conversational understanding.</p>
<hr>
<h3>2. Multilingual Conversations</h3>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1770401606/voice-blog/multilingual-vangogh.jpg" alt="Multilingual"></p>
<p><strong>Problem:</strong> Users code-switch constantly. &quot;My age twenty-four hai&quot; is neither pure English nor Hindi—it&#39;s how people actually speak.</p>
<p><strong>Solution:</strong></p>
<ul>
<li>Language Manager with sticky language state</li>
<li>Code-switching ≠ language change request</li>
<li>Domain-specific pronunciation rules for proper nouns</li>
</ul>
<hr>
<h3>3. The Latency Monster</h3>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1770401605/voice-blog/latency-vangogh.jpg" alt="Latency"></p>
<p><strong>Problem:</strong> Humans expect 200-400ms response time. We were hitting 1-2 seconds.</p>
<p><strong>Solution:</strong></p>
<ul>
<li><strong>Early warmup</strong>: Prime LLM before user speaks</li>
<li><strong>Stream everything</strong>: TTS speaks while LLM generates</li>
<li><strong>Intelligent fillers</strong>: &quot;Just a moment...&quot; while processing</li>
</ul>
<p>Result: First response 400-600ms, subsequent 200-400ms.</p>
<hr>
<h3>4. Context Loops</h3>
<p><strong>Problem:</strong> Bots get stuck asking the same question. Language switches reset context.</p>
<p><strong>Solution:</strong></p>
<ul>
<li>Track collected information persistently</li>
<li>Language switches preserve conversational state</li>
<li>Anti-loop guardrails in prompt design</li>
</ul>
<hr>
<h3>5. Tool Execution</h3>
<p><strong>Problem:</strong> LLMs sometimes expose internal workings: &quot;Let me call the schedule_callback function...&quot;</p>
<p><strong>Solution:</strong> Strict output guardrails. Tools execute silently; bot speaks naturally about results.</p>
<hr>
<h3>6. Regional Audio Quality</h3>
<p><strong>Problem:</strong> Phone audio with compression, jitter, noise, non-standard codecs.</p>
<p><strong>Solution:</strong></p>
<ul>
<li>STT correction layer for common transcription errors</li>
<li>Confidence-based confirmation</li>
<li>Graceful recovery with rephrased clarification</li>
</ul>
<hr>
<h2>The Architecture</h2>
<p><img src="https://res.cloudinary.com/dho3mopsg/image/upload/v1770401602/voice-blog/architecture-vangogh.jpg" alt="Voice Service Architecture"></p>
<p>Six layers, each with clear responsibilities:</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Responsibility</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Telephony</strong></td>
<td>WebSocket, audio serialization, call control</td>
</tr>
<tr>
<td><strong>Audio Pipeline</strong></td>
<td>VAD, turn detection, buffering</td>
</tr>
<tr>
<td><strong>Speech</strong></td>
<td>STT with corrections, TTS with pronunciation</td>
</tr>
<tr>
<td><strong>Conversation</strong></td>
<td>LLM, tools, context management</td>
</tr>
<tr>
<td><strong>State</strong></td>
<td>Language, transcript, analytics</td>
</tr>
<tr>
<td><strong>Integration</strong></td>
<td>Agent configs, knowledge base, callbacks</td>
</tr>
</tbody></table>
<hr>
<h2>Key Lessons</h2>
<ol>
<li><strong>Latency compounds</strong> — Shave milliseconds everywhere</li>
<li><strong>Real speech is messy</strong> — Multilingual, noisy, unpredictable</li>
<li><strong>Embrace statefulness</strong> — Don&#39;t fight it, manage it explicitly</li>
<li><strong>Guardrails are features</strong> — Preventing bad outputs matters</li>
<li><strong>Warmup is mandatory</strong> — Cold starts kill conversations</li>
</ol>
<hr>
<h2>What&#39;s Next</h2>
<ul>
<li>Semantic VAD with conversation context</li>
<li>Zero-shot language switching</li>
<li>Emotion-aware responses</li>
<li>Predictive response generation</li>
</ul>
<p>The gap between demo and production is closing. The engineering still matters more than the model.</p>
<hr>
]]></content:encoded>
    </item>
    <item>
      <title>UnClaude: Building an Open-Source AI Engineer with No Model Lock-In</title>
      <link>https://anzalabidi.dev/writing/unclaude-building-an-open-source-ai-engineer-with-no-model-lock-in/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/unclaude-building-an-open-source-ai-engineer-with-no-model-lock-in/</guid>
      <pubDate>Sat, 10 Jan 2026 14:58:12 GMT</pubDate>
      <description>I believe the future of software engineering isn&#39;t just \&quot;AI-assisted\&quot;—it’s agentic. We are moving away from simple chat boxes and toward agents that can plan, execute, and verify tasks autonomously. While the market is flooded with proprietary tools,...</description>
      <category>AI</category>
      <category>claude.ai</category>
      <category>automation</category>
      <category>Web Development</category>
      <content:encoded><![CDATA[<p>I believe the future of software engineering isn&#39;t just &quot;AI-assisted&quot;—it’s <strong>agentic</strong>. We are moving away from simple chat boxes and toward agents that can plan, execute, and verify tasks autonomously.</p>
<p>While the market is flooded with proprietary tools, I wanted to build something that prioritized two things: <strong>total model flexibility</strong> and <strong>local control</strong>.</p>
<p>That experiment became <strong>UnClaude</strong>.</p>
<hr>
<h2>What is UnClaude?</h2>
<p>UnClaude is a CLI-based autonomous pair programmer. It sits between you and your Large Language Model (LLM) of choice, providing the agent with a &quot;body&quot; to interact with your local environment through three core tools:</p>
<ul>
<li>📂 <strong>File System</strong>: Permission-based reading and editing of your codebase.</li>
<li>💻 <strong>Terminal</strong>: The ability to run compilers, linters, and test suites securely.</li>
<li>🌐 <strong>Browser</strong>: Real-time verification of web applications to &quot;see&quot; the UI.</li>
</ul>
<p>Because it runs locally, your code stays on your machine, and you maintain full oversight of every command the agent executes.</p>
<hr>
<h2>The Core Principles</h2>
<h3>1. Model Independence (Break the Lock-in)</h3>
<p>Different tasks require different &quot;brains.&quot; UnClaude is built on top of <code>LiteLLM</code>, allowing you to hot-swap providers instantly. Need the 2M context window of <strong>Gemini 2.5 Pro</strong>? No problem. Prefer the logic of <strong>GPT-4o</strong> or the privacy of a local <strong>Llama 3</strong> via Ollama? UnClaude supports them all.</p>
<h3>2. Autonomy via Feedback Loops (&quot;Ralph Mode&quot;)</h3>
<p>Writing code is the easy part; getting it to compile and pass CI/CD is where the time goes. UnClaude features <strong>&quot;Ralph Mode,&quot;</strong> a self-correcting loop. When the agent writes code, it doesn&#39;t just stop. It runs your test suite, analyzes the exit codes and error logs, and iteratively fixes its own mistakes until the tests pass.</p>
<h3>3. Integrated Project Memory</h3>
<p>An assistant is only as good as its context. UnClaude uses a local vector database to index your project and conversation history. This means the agent &quot;remembers&quot; your architectural patterns and previous instructions, saving you from having to repeat yourself in every new session.</p>
<hr>
<h2>Why Open Source?</h2>
<p>I’ve released UnClaude under the <strong>Apache 2.0 license</strong>. Developer tools should be transparent. By making it open source, you can inspect the prompts, modify the agent&#39;s logic, and build custom tools that fit your specific workflow.</p>
<hr>
<h2>Try it Out</h2>
<p>UnClaude is available now on PyPI. You can get up and running in seconds, or you can visit: <a href="https://github.com/anzal1/unclaude">https://github.com/anzal1/unclaude</a></p>
<pre><code class="language-bash">pipx install unclaude
unclaude login
</code></pre>
]]></content:encoded>
    </item>
    <item>
      <title>Architecting an AI Frontend Engineer: A Deep Dive into Recursive Code Generation</title>
      <link>https://anzalabidi.dev/writing/architecting-an-ai-frontend-engineer-a-deep-dive-into-recursive-code-generation/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/architecting-an-ai-frontend-engineer-a-deep-dive-into-recursive-code-generation/</guid>
      <pubDate>Sat, 04 Oct 2025 11:57:45 GMT</pubDate>
      <description>The holy grail for many developers is to automate the mundane. We build CLIs, write scripts, and create boilerplate templates, all in service of spending more time on the creative, complex problems. But what if we could push that automation to its lo...</description>
      <category>React</category>
      <category>AI</category>
      <category>llm</category>
      <category>agentic AI</category>
      <category>Python</category>
      <content:encoded><![CDATA[<p>The holy grail for many developers is to automate the mundane. We build CLIs, write scripts, and create boilerplate templates, all in service of spending more time on the creative, complex problems. But what if we could push that automation to its logical extreme? What if we could describe a UI in plain English and have an AI agent build it, component by component, dependency by dependency?</p>
<p>This post is the technical deep dive into that very project. We&#39;ll walk through the creation of a context-aware, recursive AI agent designed to build a fully functional frontend. Its entire workflow is based on cloning a specific Vite + React starter template—in this case, the one found at <code>https://github.com/anzal1/junior-frontend-developer</code>—and then intelligently modifying it based on a user&#39;s prompt. This isn&#39;t just about generating code; it&#39;s about creating a system that understands a project&#39;s structure, manages its dependencies, and orchestrates a series of complex tasks—a true digital assistant.</p>
<p>We&#39;ll dissect the architecture, explore the critical (and often hilarious) bugs we encountered, and share the key principles that made the system actually work. This isn&#39;t just a story; it&#39;s a technical blueprint for building your own autonomous development agents.</p>
<h3>Part 1: The Core Architecture - A Society of Specialists</h3>
<p>A common first instinct when building with LLMs is to create a single, massive prompt that tells one AI to do everything. This is a trap. A monolithic prompt is brittle, impossible to debug, and prone to hallucinations. Asking a single agent to &quot;build a login page&quot; might result in it hallucinating file creation, forgetting to install dependencies, and writing buggy code with mixed conventions all at once. A far more robust approach is a <strong>multi-agent system</strong>, where each agent is a specialist with a single, well-defined responsibility, akin to a well-organized software team.</p>
<p>Our system consists of a team of four specialist agents, orchestrated by a central Coordinator.</p>
<ul>
<li><strong>The Coordinator 🧠:</strong> The project manager. Written in deterministic Python, it&#39;s the &quot;adult in the room.&quot; It maintains the task queue, delegates work to the appropriate agent, and ensures the workflow progresses logically. It never talks to the LLM directly, providing a crucial layer of reliable control over the creative but sometimes unpredictable agents.</li>
<li><strong>The Planner Agent 🏛️:</strong> The System Architect. Its only job is to translate the user&#39;s high-level request into a structured JSON plan. This is the most creative agent, responsible for the initial vision. It doesn&#39;t write a line of code; it thinks about structure, dependencies, and the components needed to bring the user&#39;s idea to life. Its output is the foundational blueprint for the entire operation.</li>
<li><strong>The Dependency Agent 📦:</strong> The DevOps Specialist. It&#39;s an expert in package managers, a supply chain manager for our code. Given a list of dependencies, its only task is to generate and execute the correct <code>pnpm</code> or <code>npx</code> commands. It understands the subtle but critical difference between adding a library from npm and scaffolding a component from the shadcn-ui CLI.</li>
<li><strong>The Component Agent 🧑‍💻:</strong> The Senior Developer. This is the workhorse, the focused craftsman. It receives a single, specific task—&quot;create this component with these features&quot;—and its only job is to write the corresponding production-ready TSX code. It doesn&#39;t need to know about the overall project plan; it just executes its current ticket with precision.</li>
</ul>
<p>This separation of concerns is the single most important architectural decision. It allows us to write highly-focused, simple prompts for each agent, making their behavior more predictable and their failures easier to diagnose and fix.</p>
<h3>Part 2: The Communication Layer - Tool Calling is Non-Negotiable</h3>
<p>For agents to affect the real world (i.e., our filesystem), they need tools. We can&#39;t rely on an agent to output raw code as a text string within a markdown block; this is unreliable and prone to formatting errors, conversational fluff, and incomplete snippets. We need it to reliably call a function that we&#39;ve defined.</p>
<p>This is where <strong>Tool Calling</strong> (or Function Calling) comes in. It establishes a formal API contract between our Python code and the LLM. We define our tools—<code>write_react_component</code> and <code>execute_shell_command</code>—as JSON schemas and provide them to the LLM in the API call.</p>
<p>Here’s a simplified look at the API payload sent to OpenRouter when asking the Component Agent to create a file:</p>
<pre><code class="language-python">{
  &quot;model&quot;: &quot;google/gemini-2.5-pro&quot;,
  &quot;messages&quot;: [
    {
      &quot;role&quot;: &quot;system&quot;,
      &quot;content&quot;: &quot;You are a senior React developer... Your ONLY output must be a call to the `write_react_component` tool.&quot;
    },
    {
      &quot;role&quot;: &quot;user&quot;,
      &quot;content&quot;: &quot;The project is at &#39;retro_feline&#39;. Create the component: File Path: src/App.tsx, Description: The root component...&quot;
    }
  ],
  &quot;tools&quot;: [
    {
      &quot;type&quot;: &quot;function&quot;,
      &quot;function&quot;: {
        &quot;name&quot;: &quot;write_react_component&quot;,
        &quot;description&quot;: &quot;Writes or overwrites a React component file...&quot;,
        &quot;parameters&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;properties&quot;: {
            &quot;file_path&quot;: { &quot;type&quot;: &quot;string&quot; },
            &quot;code&quot;: { &quot;type&quot;: &quot;string&quot; },
            &quot;project_path&quot;: { &quot;type&quot;: &quot;string&quot; }
          },
          &quot;required&quot;: [&quot;file_path&quot;, &quot;code&quot;, &quot;project_path&quot;]
        }
      }
    }
  ]
}
</code></pre>
<p>When the LLM responds, it won&#39;t just give us text. It will give us a structured <code>tool_calls</code> object, which our <code>BaseAgent</code> class can then parse and execute. This makes the agent&#39;s actions explicit, auditable, and far less prone to error.</p>
<pre><code class="language-python"># Simplified logic within our BaseAgent&#39;s execute method
response_message = response[&#39;choices&#39;][0][&#39;message&#39;]
tool_calls = response_message.get(&quot;tool_calls&quot;)

if tool_calls:
    for tool_call in tool_calls:
        tool_name = tool_call[&#39;function&#39;][&#39;name&#39;]
        tool_function = self.available_tools.get(tool_name)
        tool_args = json.loads(tool_call[&#39;function&#39;][&#39;arguments&#39;])

        # Execute the real Python function
        result = tool_function(**tool_args)
</code></pre>
<p>This request-execute loop is the fundamental heartbeat of any autonomous agent system, transforming the LLM from a passive text generator into an active participant in the software development process.</p>
<h3>Part 3: The Recursive Engine - A Humble Task Queue</h3>
<p>The term &quot;recursive&quot; sounds complex, but our implementation is beautifully simple: a <strong>First-In, First-Out (FIFO) task queue</strong>, managed by the Python <code>collections.deque</code>. This approach elegantly avoids asking the LLM to manage its own state or remember the next step in a complex sequence, which is notoriously unreliable.</p>
<p>The process is straightforward:</p>
<ol>
<li><strong>Plan:</strong> The <code>PlannerAgent</code> generates the master plan, a JSON object containing lists of dependencies and components to create.</li>
<li><strong>Enqueue:</strong> The <code>Coordinator</code> iterates through this plan and populates the <code>deque</code> with discrete task objects. The queue might look like this: <code>[npm_task, shadcn_task, component_task_1, component_task_2]</code>.</li>
<li><strong>Process:</strong> The <code>Coordinator</code> enters a <code>while self.task_queue:</code> loop. In each iteration, it pops the next task, determines its <code>type</code> (e.g., &quot;npm_dependencies&quot;, &quot;component&quot;), and delegates it to the appropriate specialist agent. The agent&#39;s world is simple: it receives one job, executes it, and is done.</li>
</ol>
<p>This architecture is powerful because it&#39;s <strong>deterministic</strong> and <strong>observable</strong>. The Python <code>Coordinator</code> is in full control of the workflow. We can inspect the task queue at any time to see the remaining work, and because each task is small and isolated, failures are contained and easier to debug.</p>
<h3>Part 4: A Journey of a Thousand Bugs - Lessons from the Trenches</h3>
<p>Building this system was a constant battle against the delightful unpredictability of LLMs. Here are the key technical challenges we faced and how we solved them.</p>
<h4>Lesson 1: The AI Lies. Trust, but Verify.</h4>
<p>The first agent confidently reported &quot;All files created!&quot; but the project folder was empty. We saw perfect logs but no results. It was hallucinating tool calls.</p>
<ul>
<li><strong>The Fix:</strong> We rewrote the prompts to be brutally direct (&quot;<strong>Your ONLY output must be a call to the tool</strong>&quot;) and, crucially, lowered the API <code>temperature</code> to <code>0.1</code>. The temperature setting controls randomness; a high value encourages creativity, while a low value promotes precision and determinism. This change turned our &quot;creative artist&quot; into a &quot;dutiful factory worker&quot; who would follow instructions to the letter.</li>
</ul>
<h4>Lesson 2: Context is Everything. A Blind Agent is a Useless Agent.</h4>
<p>Initially, the agent had no knowledge of the template it was using, leading to errors like trying to import a CSS file that didn&#39;t exist in that location. It was like giving a builder a hammer and telling them to build a house without showing them the plot of land.</p>
<ul>
<li><strong>The Fix:</strong> We implemented a &quot;context injection&quot; pipeline. A new <code>template_context.md</code> file was created, acting as a &quot;style guide&quot; or &quot;company handbook&quot; for the AI, explicitly documenting the template&#39;s file structure and import conventions. The <code>Coordinator</code> now loads this file and prepends it to the system prompt of the agents. The agent now has the &quot;manual&quot; for the project, making its output dramatically more accurate.</li>
</ul>
<h4>Lesson 3: JSON is Merely a Suggestion to an LLM.</h4>
<p>The AI would frequently return malformed JSON. Sometimes it would wrap it in <code>```json</code> fences. Other times, it would generate JavaScript-style objects with numbered keys instead of a proper JSON array. This is maddening when the only error is a single missing comma in a 200-line JSON object.</p>
<ul>
<li><strong>The Fix:</strong> We built a &quot;sanitizer&quot; in the <code>PlannerAgent</code> that runs before <code>json.loads()</code>. It strips markdown and, most importantly, checks if a value is a dictionary with numeric keys and converts it to a list: <code>list(plan[&quot;components&quot;].values())</code>. This simple defensive coding against the AI&#39;s quirks saved hours of debugging.</li>
</ul>
<h4>Lesson 4: Decompose, Decompose, Decompose.</h4>
<p>Our initial <code>DependencyAgent</code> was asked to &quot;install all these dependencies,&quot; a mix of npm and shadcn packages. It suffered from cognitive load, would reliably install the npm packages, and then stop, forgetting about the shadcn components.</p>
<ul>
<li><strong>The Fix:</strong> We re-architected. The <code>PlannerAgent</code> was updated to produce two distinct lists: <code>npm_dependencies</code> and <code>shadcn_dependencies</code>. The <code>Coordinator</code> then creates two separate tasks. The <code>DependencyAgent</code>&#39;s job became trivial: it receives a list and a specific command to use. This offloaded the complex sequencing logic from the unreliable LLM to our reliable Python code.</li>
</ul>
<h3>Part 5: The Grand Finale - <code>Open</code> and the Preview Link</h3>
<p>The final touch was to automate the preview. <code>subprocess.run(&quot;pnpm run dev&quot;)</code> would hang the script, as it&#39;s a blocking call that waits for the process to finish. We turned to its non-blocking sibling, <code>subprocess.Popen</code>, to launch the Vite dev server in the background.</p>
<p>To prevent &quot;zombie processes&quot; that would keep running after the app closes, we used Python&#39;s <code>atexit</code> module to register a cleanup function that ensures the server is terminated when the main script exits.</p>
<pre><code class="language-python"># In the Coordinator&#39;s __init__
import atexit
self.dev_server_process = None
atexit.register(self._cleanup_dev_server)

def _cleanup_dev_server(self):
    if self.dev_server_process:
        self.dev_server_process.terminate()
</code></pre>
]]></content:encoded>
    </item>
    <item>
      <title>Stop Applying for Jobs Manually: Build an AI Agent That Does It for You</title>
      <link>https://anzalabidi.dev/writing/stop-applying-for-jobs-manually-build-an-ai-agent-that-does-it-for-you/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/stop-applying-for-jobs-manually-build-an-ai-agent-that-does-it-for-you/</guid>
      <pubDate>Sat, 12 Jul 2025 12:34:16 GMT</pubDate>
      <description>Are you tired of the soul-crushing routine of job hunting? The endless cycle of finding a listing, filling out the same form fields, and uploading your resume for the hundredth time? It feels like a full-time job just to apply for a job. What if you ...</description>
      <category>software development</category>
      <category>AI</category>
      <category>automation</category>
      <category>Python</category>
      <category>jobs</category>
      <content:encoded><![CDATA[<p>Are you tired of the soul-crushing routine of job hunting? The endless cycle of finding a listing, filling out the <em>same</em> form fields, and uploading your resume for the hundredth time? It feels like a full-time job just to apply for a job.</p>
<p>What if you could hand off that entire process to a smart AI agent? An assistant that opens your browser, searches for jobs on LinkedIn, intelligently fills out each application, and works 24/7 on your behalf.</p>
<p>This isn&#39;t a futuristic dream. It’s possible right now with a powerful open-source tool called <a href="https://github.com/browser-use/web-ui"><strong>Browser Use</strong></a>. In this guide, I&#39;ll show you exactly how to build your own personal AI job-hunting assistant by teaching you how to write the perfect &quot;master prompt&quot; to command your agent.</p>
<p>Let&#39;s dive in.</p>
<h3>Part 1: Your Technical Toolkit &amp; Setup</h3>
<p>First, we need to get the <code>Browser Use</code> project set up on your computer. This part involves using the command line and requires that you have <a href="https://git-scm.com/"><strong>Git</strong></a> and <a href="https://www.python.org/downloads/"><strong>Python</strong></a> installed.</p>
<p><strong>Step 1: Clone the Project</strong></p>
<p>We need to download the project files from GitHub. Open your terminal and run these commands one by one:</p>
<p>Bash</p>
<pre><code class="language-powershell"># Clone the repository for the web interface
git clone https://github.com/browser-use/web-ui.git

# Move into the new project folder
cd browser-use-web-ui
</code></pre>
<p><strong>Step 2: Create and Activate a Python Environment</strong></p>
<p>A virtual environment is like a clean, isolated workspace for our project&#39;s code.</p>
<p>Bash</p>
<pre><code class="language-powershell"># Create the environment
python3 -m venv .venv

# Activate the environment (On Mac/Linux)
source .venv/bin/activate

# Or activate it on Windows
.venv\Scripts\activate
</code></pre>
<p>You&#39;ll know it&#39;s working when you see <code>(.venv)</code> at the start of your terminal prompt.</p>
<p><strong>Step 3: Install the Tools</strong></p>
<p>Now we install all the necessary packages and the browser automation framework, <a href="https://playwright.dev/"><strong>Playwright</strong></a>.</p>
<p>Bash</p>
<pre><code class="language-powershell"># Install all the required Python packages
pip install -r requirements.txt

# Install the browsers for the agent to control
playwright install
</code></pre>
<h3>Part 2: Giving Your Agent a Brain with AI</h3>
<p>Our agent needs an AI model to think and follow instructions. We&#39;ll use the free tier of a powerful model through a service called <a href="https://openrouter.ai/"><strong>OpenRouter</strong></a>.</p>
<p><strong>Step 4: Configure Your API Keys</strong></p>
<p>API keys are like secret passwords that let our script talk to the AI model.</p>
<ol>
<li>In the project folder, find the file named <code>.env.example</code> and make a copy of it. Rename the copy to just <code>.env</code>.</li>
<li>Go to <a href="https://openrouter.ai/models"><strong>OpenRouter.ai</strong></a> and sign up.</li>
<li>Find a capable free model (like <strong>DeepSeek Coder</strong> or <strong>Google&#39;s Gemma</strong>).</li>
<li>Go to your <strong>Keys</strong> page, create a new key, name it, and copy the key itself.</li>
<li>Open your new <code>.env</code> file and paste in your key and the OpenRouter Base URL. It should look like this:</li>
</ol>
<p>Code snippet</p>
<pre><code class="language-xml">OPENAI_API_KEY=&quot;paste_your_secret_api_key_here&quot;
OPENAI_BASE_URL=&quot;https://openrouter.ai/api/v1&quot;
</code></pre>
<h3>Part 3: Launch and Test Run</h3>
<p>Let&#39;s fire it up to make sure everything is connected correctly.</p>
<p><strong>Step 5: Launch the Web Interface</strong></p>
<p>In your terminal (with the <code>.venv</code> still active), run this command:</p>
<p>Bash</p>
<pre><code class="language-powershell">python -m uvicorn main:app --reload
</code></pre>
<p>Your terminal will give you a local URL like <code>http://127.0.0.1:8000</code>. Copy it and open it in your browser.</p>
<p><strong>Step 6: Run Your First Test</strong></p>
<ol>
<li>On the <code>Browser Use</code> page, click <strong>&quot;LM Settings&quot;</strong>.</li>
<li>For the <strong>Model Name</strong>, enter the name of the model you chose, like <code>deepseek/deepseek-coder</code>. Save it.</li>
<li>Go back to the <strong>&quot;Run Agent&quot;</strong> tab. There&#39;s a default test task already there.</li>
<li>Click <strong>&quot;Run Agent&quot;</strong>.</li>
</ol>
<p>A new browser window should pop up and perform a quick Google search automatically. Success! You have a working AI agent ready for your commands.</p>
<h3>Part 4: The Core - Crafting the Perfect Prompt for Your Agent</h3>
<p>This is where the magic happens. We will write a clear, step-by-step &quot;master prompt&quot; to command our agent. For complex prompts, using a powerful AI assistant like <a href="https://chatgpt.com/"><strong>ChatGPT</strong></a> can help you refine your logic and wording.</p>
<p>Here’s how to structure your prompt for the best results.</p>
<p>\1. Define the Goal and Starting Point</p>
<p>Start with a clear objective.</p>
<ul>
<li><strong>Goal:</strong> My goal is to apply for jobs on LinkedIn.</li>
<li><strong>Starting URL:</strong> Start at this page: <code>https://www.linkedin.com/jobs/search/?keywords=Product%20Manager&amp;location=Remote</code></li>
</ul>
<p>\2. Set the Rules of Engagement</p>
<p>Tell the agent exactly what to look for and what to avoid. This is crucial for getting relevant applications.</p>
<ul>
<li><strong>Inclusion Rules:</strong><ul>
<li>The job title must include &quot;Product Manager&quot; or &quot;Product Owner&quot;.</li>
<li>The location must be &quot;Remote&quot;.</li>
<li>Only apply to jobs posted in the &quot;Past week&quot;.</li>
</ul>
</li>
<li><strong>Exclusion Rules (Just as important!):</strong><ul>
<li>Do NOT apply if the title includes &quot;Senior&quot;, &quot;Lead&quot;, or &quot;Principal&quot;.</li>
<li>Do NOT apply to jobs from the companies &quot;Meta&quot; or &quot;Google&quot;.</li>
</ul>
</li>
</ul>
<p>\3. Write the Step-by-Step Action Sequence</p>
<p>This is the main algorithm. Write it like you&#39;re explaining it to a person.</p>
<ul>
<li><strong>Action Plan:</strong><ol>
<li>Navigate to the Starting URL.</li>
<li>Go through each job listing on the page one by one.</li>
<li>For each job, check if it matches my Inclusion and Exclusion rules.</li>
<li>If it is a match, click on the job listing.</li>
<li>Click the &quot;Easy Apply&quot; button.</li>
<li>The application form will now be open. Use the following information to fill it out:<ul>
<li>My full name is: Jane Doe</li>
<li>My email is: <a href="mailto:jane.doe@email.com">jane.doe@email.com</a></li>
<li>My phone number is: 123-456-7890</li>
<li>My resume is located at: <code>C:\Users\JaneDoe\Documents\resume_v2.pdf</code></li>
</ul>
</li>
<li>If you encounter a question like &quot;Years of experience with SaaS products?&quot;, answer &quot;5&quot;.</li>
<li>After filling all required fields, click the button to &quot;Review&quot; and then &quot;Submit application&quot;.</li>
<li>Close the job tab and move to the next listing on the search results page.</li>
</ol>
</li>
</ul>
<p><strong>Putting It All Together</strong></p>
<p>Combine these sections into one big prompt inside the &quot;Task Description&quot; box in <code>Browser Use</code>. The more detailed you are, the better your agent will perform.</p>
<h3>Part 5: Unleash Your AI Job Hunter!</h3>
<ol>
<li><strong>Copy and paste your complete, detailed prompt</strong> into the <code>Browser Use</code> interface.</li>
<li>Click <strong>&quot;Run Agent&quot;</strong>.</li>
</ol>
<p>Now, sit back and watch. The browser window will spring to life, navigating, analyzing, and applying on your behalf, all based on the precise instructions you wrote. You&#39;ve successfully delegated one of the most tedious tasks in modern life to your own personal AI agent.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Building a High-Performance Graph: From SVG Hell to Canvas Heaven</title>
      <link>https://anzalabidi.dev/writing/building-a-high-performance-graph-from-svg-hell-to-canvas-heaven/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/building-a-high-performance-graph-from-svg-hell-to-canvas-heaven/</guid>
      <pubDate>Tue, 08 Jul 2025 08:03:53 GMT</pubDate>
      <description>A Deep Dive into Rendering Large Networks with React and D3 At its core, our work often revolves around data. But raw data in tables and spreadsheets can only tell us so much. The real magic happens when we can see the relationships hidden within tha...</description>
      <category>React</category>
      <category>Browsers</category>
      <category>Rendering</category>
      <category>optimization</category>
      <category>canvas</category>
      <category>JavaScript</category>
      <content:encoded><![CDATA[<h3>A Deep Dive into Rendering Large Networks with React and D3</h3>
<p>At its core, our work often revolves around data. But raw data in tables and spreadsheets can only tell us so much. The real magic happens when we can <em>see</em> the relationships hidden within that data. This is especially true for network data, where the connections between points are often more important than the points themselves.</p>
<p>Visualizing these networks allows our analysts to spot fraud rings, understand complex system dependencies, and uncover insights that would be impossible to find in a spreadsheet. The tool for this job? A force-directed graph.</p>
<p>However, as we quickly discovered, building a graph that looks good with a handful of test nodes is one thing. Building one that stays fast and usable with real-world, large-scale data is another challenge entirely.</p>
<p>This document chronicles our journey of transforming a sluggish, proof-of-concept graph into a highly performant, feature-rich analysis tool. We&#39;ll explore the technical bottlenecks we hit, the architectural decisions we made, and the clever algorithms that saved the day.</p>
<h2>The Tool for the Job: What is D3.js?</h2>
<p>Before we dive into the problems, let&#39;s talk about the main tool we used: <strong>D3.js (Data-Driven Documents)</strong>.</p>
<p>D3 is not a &quot;charting library&quot; in the traditional sense. It doesn&#39;t give you pre-built bar charts or pie charts. Instead, it gives you a powerful set of tools to bind arbitrary data to the Document Object Model (DOM) and then apply data-driven transformations to the document.</p>
<p>In simple terms, you can give D3 an array of numbers and use it to create and style a <code>&lt;div&gt;</code> for each number. For graph visualization, we give it an array of nodes and links and use it to create and position SVG elements. Its most powerful feature for our use case is its <code>forceSimulation</code> module—a physics engine that can automatically position nodes in a way that is both aesthetically pleasing and analytically insightful.</p>
<h2>The First Attempt: The Simplicity and Deception of SVG</h2>
<p>When you start a D3 project, SVG (Scalable Vector Graphics) is the natural choice. It&#39;s a web standard, and it integrates perfectly with D3&#39;s data-binding paradigm. The logic feels wonderfully direct: for every node in our data, we create a <code>&lt;circle&gt;</code> element, and for every link, we create a <code>&lt;line&gt;</code> element.</p>
<pre><code class="language-javascript">// This looks so simple, right?
const svg = d3.select(&quot;#graph-container&quot;).append(&quot;svg&quot;);

// Make a line for every link
svg.selectAll(&quot;line&quot;).data(links).enter().append(&quot;line&quot;);

// And a circle for every node
svg.selectAll(&quot;circle&quot;).data(nodes).enter().append(&quot;circle&quot;);
</code></pre>
<p>This creates a direct, one-to-one relationship between our data and the DOM.</p>
<p>For a few hundred nodes, this works like a charm! It&#39;s crisp, it&#39;s interactive (you can attach <code>onClick</code> listeners directly to the circles), and you feel like you&#39;ve built something amazing in just a few lines of code.</p>
<p>The problem is, this simple approach has a hidden, dark side that only reveals itself when you start throwing real, complex data at it.</p>
<h3>The SVG Bottleneck: Why Our Graph Ground to a Halt</h3>
<p>Here&#39;s the catch: SVG is what&#39;s called a <strong>&quot;retained-mode&quot;</strong> system. In simple terms, for every single shape you draw, the browser has to create and keep track of a separate object in the DOM.</p>
<p>Think about it. A graph with 5,000 nodes and 10,000 links means you&#39;re creating over <strong>15,000 DOM elements!</strong> This is what our graph looked like—a classic &quot;hairball.&quot;</p>
<p>The real trouble starts when the D3 force simulation kicks in. To create that nice, organic layout, the simulation is constantly adjusting the positions of all the nodes. For our SVG graph, that meant:</p>
<ol>
<li><strong>The Reflow Nightmare:</strong> On every single &quot;tick&quot; of the simulation, we were telling the browser to update the <code>cx</code> and <code>cy</code> attributes of thousands of circle elements. Every time an element moves, the browser has to do a &quot;reflow&quot;—a super expensive calculation to figure out how that move affects the layout of everything else on the page.</li>
<li><strong>Painting Over and Over:</strong> After the reflow, the browser has to repaint all the changed elements.</li>
<li><strong>Putting it all Together:</strong> Finally, it composites all these freshly painted layers back onto the screen.</li>
</ol>
<p>Doing all of that, for thousands of elements, hundreds of times per second? The browser&#39;s main thread just couldn&#39;t keep up. The result was a jumpy, laggy mess that was frustrating to use and made analysis impossible.</p>
<h2>The Fix: Breaking Free with Canvas</h2>
<p>To get the performance we needed, we had to break free from the DOM. The HTML5 <code>&lt;canvas&gt;</code> element was our escape hatch.</p>
<h3>A Different Way of Thinking: &quot;Immediate-Mode&quot;</h3>
<p>Canvas works in <strong>&quot;immediate-mode&quot;</strong>. Think of it like this:</p>
<ul>
<li><strong>SVG is like building with Legos.</strong> Each brick is a distinct object. You can move a brick, change its color, or attach an event listener to it. The model retains the state of every single brick.</li>
<li><strong>Canvas is like... well, a canvas!</strong> You&#39;re a painter with a brush. You tell the canvas &quot;draw a circle here,&quot; and it puts pixels on the screen. The moment it&#39;s drawn, the canvas forgets it was a circle. It&#39;s just a collection of pixels. It doesn&#39;t retain anything.</li>
</ul>
<p>This &quot;fire-and-forget&quot; approach is the key to its speed.</p>
<h3>The Performance Win</h3>
<ol>
<li><strong>One Element to Rule Them All:</strong> No matter if we have 10 nodes or 10,000, we only ever have <em>one</em> <code>&lt;canvas&gt;</code> element in the DOM. The browser&#39;s layout work is basically zero.</li>
<li><strong>We&#39;re in Control of the Rendering:</strong> We let the D3 physics simulation run in the background, constantly updating the <code>x</code> and <code>y</code> coordinates of our nodes in a simple JavaScript array. Then, in a separate, highly optimized loop using <code>requestAnimationFrame</code>, we tell the canvas to redraw the entire scene based on that data.</li>
</ol>
<pre><code class="language-cpp">function renderLoop() {
  // 1. Wipe the canvas clean.
  context.clearRect(0, 0, width, height);

  // 2. Loop through our data and paint everything.
  nodes.forEach(node =&gt; {
    context.beginPath();
    context.arc(node.x, node.y, 5, 0, 2 * Math.PI);
    context.fill();
  });

  // 3. Tell the browser we&#39;re ready for the next paint frame.
  requestAnimationFrame(renderLoop);
}
</code></pre>
<p>This decouples the physics from the painting and syncs our drawing with the screen&#39;s refresh rate. The result? A buttery-smooth 60fps animation, even with a massive number of nodes!</p>
<h2>The Interaction Challenge: How Do You Click on Pixels?</h2>
<p>We solved the rendering bottleneck, but created a new problem: <strong>interaction</strong>. The canvas is a dumb pixel buffer. It has no concept of the nodes or edges drawn on it. If a user clicks on the canvas, how do we know <em>what</em> they clicked on?</p>
<p>The naive approach is a brute-force search: loop through every node and check if the click coordinates are within its radius. This is an <strong>O(n)</strong> operation, meaning it scales linearly with the number of nodes. For 10,000 nodes, this is far too slow.</p>
<h3>The Hero of Our Story: The Mighty Quadtree</h3>
<p>This is where the <strong>Quadtree</strong> becomes our most important tool. A quadtree is a data structure that recursively subdivides a 2D space into four quadrants, allowing for incredibly efficient spatial lookups.</p>
<p>Instead of checking every node, we can find the node under the cursor with <strong>O(log n)</strong> complexity. For 10,000 nodes, this reduces the number of checks from 10,000 to roughly 14.</p>
<p>In our implementation:</p>
<ol>
<li><strong>Build the Tree:</strong> On every render frame, we build a new quadtree from the latest node positions: <code>quadtree = d3.quadtree().addAll(nodes)</code>.</li>
<li><strong>Find the Node:</strong> On a mouse event, we query the tree: <code>quadtree.find(mouseX, mouseY, searchRadius)</code>.</li>
</ol>
<p>This is fast enough to run on every mouse move, enabling smooth tooltips, clicks, and dragging on a canvas with tens of thousands of elements.</p>
<h2>Putting It All Together: A Stable React Architecture</h2>
<p>The final piece of the puzzle is ensuring our component is stable within the React ecosystem. A common pitfall is to place the D3 simulation setup inside a standard <code>useEffect</code> hook. This causes the entire simulation to be destroyed and recreated whenever a prop changes, leading to the dreaded &quot;jumping&quot; graph.</p>
<p>Our solution uses a two-hook architecture:</p>
<ol>
<li><strong>One-Time Setup</strong> <code>useEffect</code>: This hook runs only once (<code>useEffect(..., [])</code>). It is responsible for all the expensive, one-time setup: creating the simulation, appending UI elements, attaching event listeners, and starting the render loop.</li>
<li><strong>Data Update</strong> <code>useEffect</code>: This hook runs only when the <code>dataset</code> prop changes. It does <em>not</em> destroy the simulation. It simply updates the existing simulation with the new data and &quot;reheats&quot; it with <code>simulation.alpha(1).restart()</code>.</li>
</ol>
<p>This separation is the key to preventing the &quot;jumping&quot; and &quot;twitching&quot; issues, as UI interactions and prop changes no longer trigger a full teardown and recreation of the graph visualization.</p>
<h2>Conclusion</h2>
<p>By migrating from SVG to Canvas, we traded the convenience of the DOM for raw rendering performance. We then regained interactivity by implementing a Quadtree for efficient spatial lookups. Finally, by carefully structuring our React component, we created a stable, non-rerendering architecture. The result is a feature-rich, highly performant graph visualization tool capable of handling the scale and complexity our data demands.</p>
<h2>Quadtree Implementation from Scratch</h2>
<p>While we use D3&#39;s built-in Quadtree for its robustness and integration with the D3 ecosystem, understanding how one works from scratch is enlightening. Below is a simplified JavaScript implementation that demonstrates the core principles of insertion and querying.</p>
<pre><code class="language-javascript">class Point {
    constructor(x, y, data) {
        this.x = x;
        this.y = y;
        this.data = data; // Arbitrary data associated with the point
    }
}

class Rectangle {
    constructor(x, y, w, h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
    }

    contains(point) {
        return (
            point.x &gt;= this.x - this.w &amp;&amp;
            point.x &lt; this.x + this.w &amp;&amp;
            point.y &gt;= this.y - this.h &amp;&amp;
            point.y &lt; this.y + this.h
        );
    }

    intersects(range) {
        return !(
            range.x - range.w &gt; this.x + this.w ||
            range.x + range.w &lt; this.x - this.w ||
            range.y - range.h &gt; this.y + this.h ||
            range.y + range.h &lt; this.y - this.h
        );
    }
}

class QuadTree {
    constructor(boundary, capacity) {
        this.boundary = boundary; // A Rectangle object
        this.capacity = capacity; // Max number of points before subdividing
        this.points = [];
        this.divided = false;
    }

    subdivide() {
        const { x, y, w, h } = this.boundary;
        const nw = new Rectangle(x - w / 2, y - h / 2, w / 2, h / 2);
        const ne = new Rectangle(x + w / 2, y - h / 2, w / 2, h / 2);
        const sw = new Rectangle(x - w / 2, y + h / 2, w / 2, h / 2);
        const se = new Rectangle(x + w / 2, y + h / 2, w / 2, h / 2);

        this.northwest = new QuadTree(nw, this.capacity);
        this.northeast = new QuadTree(ne, this.capacity);
        this.southwest = new QuadTree(sw, this.capacity);
        this.southeast = new QuadTree(se, this.capacity);

        this.divided = true;
    }

    insert(point) {
        if (!this.boundary.contains(point)) {
            return false;
        }

        if (this.points.length &lt; this.capacity) {
            this.points.push(point);
            return true;
        } else {
            if (!this.divided) {
                this.subdivide();
            }

            if (this.northeast.insert(point)) return true;
            if (this.northwest.insert(point)) return true;
            if (this.southeast.insert(point)) return true;
            if (this.southwest.insert(point)) return true;
        }
    }

    query(range, found = []) {
        if (!this.boundary.intersects(range)) {
            return found;
        }

        for (let p of this.points) {
            if (range.contains(p)) {
                found.push(p);
            }
        }

        if (this.divided) {
            this.northwest.query(range, found);
            this.northeast.query(range, found);
            this.southwest.query(range, found);
            this.southeast.query(range, found);
        }

        return found;
    }
}
</code></pre>
<h2>Live Performance Demo</h2>
<p>To see the performance difference for yourself, save the code below as a single <code>.html</code> file and open it in your browser. It renders the same force-directed graph in a single panel.</p>
<p>Use the controls at the top to switch between &quot;SVG Mode&quot; and &quot;Canvas Mode&quot; and to increase the number of nodes and links. You will quickly see the SVG version&#39;s FPS drop dramatically, while the Canvas version remains smooth and interactive</p>
<p>Use the controls at the top to switch between &quot;SVG Mode&quot; and &quot;Canvas Mode&quot; and to increase the number of nodes and links. You will quickly see the SVG version&#39;s FPS drop dramatically, while the Canvas version remains smooth and interactive.</p>
<pre><code class="language-xml">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;SVG vs. Canvas Performance Demo&lt;/title&gt;
    &lt;script src=&quot;https://d3js.org/d3.v7.min.js&quot;&gt;&lt;/script&gt;
    &lt;style&gt;
        body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, Roboto, &#39;Helvetica Neue&#39;, Arial, sans-serif; background-color: #f0f2f5; }
        .controls { padding: 15px; background-color: #fff; border-bottom: 1px solid #ddd; display: flex; align-items: center; gap: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .controls label { font-weight: bold; }
        .controls input[type=&quot;number&quot;] { width: 80px; padding: 5px; border: 1px solid #ccc; border-radius: 4px; }
        .controls button { padding: 5px 15px; border: 1px solid #ccc; border-radius: 4px; background-color: #e9e9e9; cursor: pointer; }
        .controls .mode-toggle button.active { background-color: #007bff; color: white; border-color: #007bff; }
        .container { display: flex; width: 100%; height: calc(100vh - 70px); }
        .panel { width: 100%; height: 100%; position: relative; background-color: #fff; }
        .fps-container { position: absolute; top: 10px; right: 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
        .fps { background: rgba(0,0,0,0.5); color: white; padding: 5px 8px; border-radius: 3px; font-family: monospace; }
        .perf-graph { border: 1px solid #ccc; background-color: rgba(255,255,255,0.8); }
        #graph-container { width: 100%; height: 100%; }
        #graph-container &gt; * { width: 100%; height: 100%; display: block; }
        .tooltip { position: absolute; visibility: hidden; background: rgba(0,0,0,0.7); color: white; padding: 4px 8px; border-radius: 3px; pointer-events: none; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;controls&quot;&gt;
    &lt;div class=&quot;mode-toggle&quot;&gt;
        &lt;label&gt;Mode:&lt;/label&gt;
        &lt;button id=&quot;svg-btn&quot; class=&quot;active&quot;&gt;SVG&lt;/button&gt;
        &lt;button id=&quot;canvas-btn&quot;&gt;Canvas&lt;/button&gt;
    &lt;/div&gt;
    &lt;label for=&quot;nodes&quot;&gt;Nodes:&lt;/label&gt;
    &lt;input type=&quot;number&quot; id=&quot;nodes&quot; value=&quot;500&quot; min=&quot;10&quot; max=&quot;20000&quot; step=&quot;100&quot;&gt;
    &lt;label for=&quot;links&quot;&gt;Links:&lt;/label&gt;
    &lt;input type=&quot;number&quot; id=&quot;links&quot; value=&quot;400&quot; min=&quot;10&quot; max=&quot;20000&quot; step=&quot;100&quot;&gt;
    &lt;button id=&quot;update&quot;&gt;Update Graph&lt;/button&gt;
&lt;/div&gt;

&lt;div class=&quot;container&quot;&gt;
    &lt;div class=&quot;panel&quot;&gt;
        &lt;div id=&quot;graph-container&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;fps-container&quot;&gt;
            &lt;div id=&quot;fps-display&quot; class=&quot;fps&quot;&gt;-- FPS&lt;/div&gt;
            &lt;canvas id=&quot;perf-graph&quot; class=&quot;perf-graph&quot; width=&quot;200&quot; height=&quot;50&quot;&gt;&lt;/canvas&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
    const graphContainer = d3.select(&quot;#graph-container&quot;);
    const perfCanvas = document.getElementById(&quot;perf-graph&quot;);
    const perfContext = perfCanvas.getContext(&quot;2d&quot;);

    let activeSimulation;
    let activeRenderLoopId;
    let currentMode = &#39;svg&#39;;

    const fpsCounter = {
        history: [],
        lastTime: performance.now(),
        frames: 0
    };

    function createData(numNodes, numLinks) {
        const nodes = Array.from({length: numNodes}, (_, i) =&gt; ({id: i}));
        const links = Array.from({length: numLinks}, () =&gt; ({
            source: Math.floor(Math.random() * numNodes),
            target: Math.floor(Math.random() * numNodes)
        }));
        return { nodes, links };
    }

    function updateFPS() {
        fpsCounter.frames++;
        const time = performance.now();
        if (time &gt;= fpsCounter.lastTime + 1000) {
            const fps = fpsCounter.frames;
            fpsCounter.frames = 0;
            fpsCounter.lastTime = time;
            document.getElementById(&#39;fps-display&#39;).textContent = `${fps} FPS`;
            fpsCounter.history.push(fps);
            if (fpsCounter.history.length &gt; 100) fpsCounter.history.shift();
        }
        drawPerformanceGraph();
    }

    function drawPerformanceGraph() {
        perfContext.clearRect(0, 0, perfCanvas.width, perfCanvas.height);
        perfContext.fillStyle = &quot;rgba(240, 240, 240, 0.8)&quot;;
        perfContext.fillRect(0, 0, perfCanvas.width, perfCanvas.height);

        perfContext.beginPath();
        perfContext.moveTo(0, perfCanvas.height - (60 / 70 * perfCanvas.height));
        perfContext.lineTo(perfCanvas.width, perfCanvas.height - (60 / 70 * perfCanvas.height));
        perfContext.strokeStyle = &quot;rgba(0, 255, 0, 0.5)&quot;;
        perfContext.stroke();

        perfContext.beginPath();
        perfContext.moveTo(0, perfCanvas.height);
        fpsCounter.history.forEach((fps, i) =&gt; {
            const x = (i / 99) * perfCanvas.width;
            const y = perfCanvas.height - (Math.min(fps, 70) / 70 * perfCanvas.height);
            perfContext.lineTo(x, y);
        });
        perfContext.strokeStyle = &quot;#333&quot;;
        perfContext.stroke();
    }

    function cleanup() {
        if (activeSimulation) activeSimulation.stop();
        if (activeRenderLoopId) cancelAnimationFrame(activeRenderLoopId);
        graphContainer.html(&quot;&quot;);
        fpsCounter.history = [];
        fpsCounter.frames = 0;
        fpsCounter.lastTime = performance.now();
    }

    function runSVG(data, width, height) {
        cleanup();
        const svg = graphContainer.append(&quot;svg&quot;).attr(&quot;width&quot;, width).attr(&quot;height&quot;, height);
        const tooltip = d3.select(&quot;body&quot;).append(&quot;div&quot;).attr(&quot;class&quot;, &quot;tooltip&quot;);

        activeSimulation = d3.forceSimulation(data.nodes)
            .force(&quot;link&quot;, d3.forceLink(data.links).id(d =&gt; d.id))
            .force(&quot;charge&quot;, d3.forceManyBody().strength(-30))
            .force(&quot;center&quot;, d3.forceCenter(width / 2, height / 2));

        const link = svg.append(&quot;g&quot;).selectAll(&quot;line&quot;).data(data.links).join(&quot;line&quot;).attr(&quot;stroke&quot;, &quot;#999&quot;).attr(&quot;stroke-opacity&quot;, 0.6);
        const node = svg.append(&quot;g&quot;).selectAll(&quot;circle&quot;).data(data.nodes).join(&quot;circle&quot;).attr(&quot;r&quot;, 5).attr(&quot;fill&quot;, &quot;#333&quot;)
            .on(&quot;mouseover&quot;, (event, d) =&gt; {
                tooltip.style(&quot;visibility&quot;, &quot;visible&quot;).text(`Node ${d.id}`);
            })
            .on(&quot;mousemove&quot;, (event) =&gt; {
                tooltip.style(&quot;top&quot;, (event.pageY - 10) + &quot;px&quot;).style(&quot;left&quot;, (event.pageX + 10) + &quot;px&quot;);
            })
            .on(&quot;mouseout&quot;, () =&gt; {
                tooltip.style(&quot;visibility&quot;, &quot;hidden&quot;);
            })
            .call(d3.drag()
                .on(&quot;start&quot;, (event, d) =&gt; {
                    if (!event.active) activeSimulation.alphaTarget(0.3).restart();
                    d.fx = d.x;
                    d.fy = d.y;
                })
                .on(&quot;drag&quot;, (event, d) =&gt; {
                    d.fx = event.x;
                    d.fy = event.y;
                })
                .on(&quot;end&quot;, (event, d) =&gt; {
                    if (!event.active) activeSimulation.alphaTarget(0);
                    d.fx = null;
                    d.fy = null;
                }));

        activeSimulation.on(&quot;tick&quot;, () =&gt; {
            link.attr(&quot;x1&quot;, d =&gt; d.source.x).attr(&quot;y1&quot;, d =&gt; d.source.y).attr(&quot;x2&quot;, d =&gt; d.target.x).attr(&quot;y2&quot;, d =&gt; d.target.y);
            node.attr(&quot;cx&quot;, d =&gt; d.x).attr(&quot;cy&quot;, d =&gt; d.y);
        });

        function renderLoop() {
            updateFPS();
            activeRenderLoopId = requestAnimationFrame(renderLoop);
        }
        activeRenderLoopId = requestAnimationFrame(renderLoop);
    }

    function runCanvas(data, width, height) {
        cleanup();
        const canvas = graphContainer.append(&quot;canvas&quot;).attr(&quot;width&quot;, width).attr(&quot;height&quot;, height).node();
        const context = canvas.getContext(&quot;2d&quot;);
        const tooltip = d3.select(&quot;body&quot;).append(&quot;div&quot;).attr(&quot;class&quot;, &quot;tooltip&quot;);

        activeSimulation = d3.forceSimulation(data.nodes)
            .force(&quot;link&quot;, d3.forceLink(data.links).id(d =&gt; d.id))
            .force(&quot;charge&quot;, d3.forceManyBody().strength(-30))
            .force(&quot;center&quot;, d3.forceCenter(width / 2, height / 2));

        let quadtree = d3.quadtree().x(d =&gt; d.x).y(d =&gt; d.y);

        activeSimulation.on(&quot;tick&quot;, () =&gt; {
            quadtree = d3.quadtree().x(d =&gt; d.x).y(d =&gt; d.y).addAll(data.nodes);
            render();
        });

        function render() {
            context.clearRect(0, 0, width, height);
            context.beginPath();
            data.links.forEach(d =&gt; {
                context.moveTo(d.source.x, d.source.y);
                context.lineTo(d.target.x, d.target.y);
            });
            context.strokeStyle = &quot;#999&quot;;
            context.stroke();
            context.beginPath();
            data.nodes.forEach(d =&gt; {
                context.moveTo(d.x + 5, d.y);
                context.arc(d.x, d.y, 5, 0, 2 * Math.PI);
            });
            context.fillStyle = &quot;#333&quot;;
            context.fill();
        }

        d3.select(canvas)
            .on(&quot;mousemove&quot;, (event) =&gt; {
                const [mx, my] = d3.pointer(event);
                const found = quadtree.find(mx, my, 10);
                if (found) {
                    tooltip.style(&quot;visibility&quot;, &quot;visible&quot;).text(`Node ${found.id}`)
                        .style(&quot;top&quot;, (event.pageY - 10) + &quot;px&quot;).style(&quot;left&quot;, (event.pageX + 10) + &quot;px&quot;);
                } else {
                    tooltip.style(&quot;visibility&quot;, &quot;hidden&quot;);
                }
            })
            .call(d3.drag()
                .subject((event) =&gt; {
                    const [mx, my] = d3.pointer(event, canvas);
                    return quadtree.find(mx, my, 10);
                })
                .on(&quot;start&quot;, (event) =&gt; {
                    if (!event.active) activeSimulation.alphaTarget(0.3).restart();
                    event.subject.fx = event.subject.x;
                    event.subject.fy = event.subject.y;
                })
                .on(&quot;drag&quot;, (event) =&gt; {
                    event.subject.fx = event.x;
                    event.subject.fy = event.y;
                })
                .on(&quot;end&quot;, (event) =&gt; {
                    if (!event.active) activeSimulation.alphaTarget(0);
                    event.subject.fx = null;
                    event.subject.fy = null;
                }));

        function animationLoop() {
            updateFPS();
            activeRenderLoopId = requestAnimationFrame(animationLoop);
        }
        activeRenderLoopId = requestAnimationFrame(animationLoop);
    }

    function updateAll() {
        const numNodes = +document.getElementById(&#39;nodes&#39;).value;
        const numLinks = +document.getElementById(&#39;links&#39;).value;
        const data = createData(numNodes, numLinks);

        const panelWidth = document.querySelector(&#39;.panel&#39;).clientWidth;
        const panelHeight = document.querySelector(&#39;.panel&#39;).clientHeight;

        if (currentMode === &#39;svg&#39;) {
            runSVG(data, panelWidth, panelHeight);
        } else {
            runCanvas(data, panelWidth, panelHeight);
        }
    }

    document.getElementById(&#39;svg-btn&#39;).addEventListener(&#39;click&#39;, () =&gt; {
        currentMode = &#39;svg&#39;;
        document.getElementById(&#39;svg-btn&#39;).classList.add(&#39;active&#39;);
        document.getElementById(&#39;canvas-btn&#39;).classList.remove(&#39;active&#39;);
        updateAll();
    });

    document.getElementById(&#39;canvas-btn&#39;).addEventListener(&#39;click&#39;, () =&gt; {
        currentMode = &#39;canvas&#39;;
        document.getElementById(&#39;canvas-btn&#39;).classList.add(&#39;active&#39;);
        document.getElementById(&#39;svg-btn&#39;).classList.remove(&#39;active&#39;);
        updateAll();
    });

    document.getElementById(&#39;update&#39;).addEventListener(&#39;click&#39;, updateAll);

    // Initial load
    updateAll();
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre>
]]></content:encoded>
    </item>
    <item>
      <title>Lynx vs. React Native: A Comprehensive Comparison</title>
      <link>https://anzalabidi.dev/writing/lynx-vs-react-native-a-comprehensive-comparison/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/lynx-vs-react-native-a-comprehensive-comparison/</guid>
      <pubDate>Thu, 13 Mar 2025 22:29:01 GMT</pubDate>
      <description>Introduction The cross-platform mobile development landscape is evolving rapidly with new contenders challenging established solutions. Two notable technologies in this space are React Native, a mature framework developed by Meta (formerly Facebook),...</description>
      <category>React</category>
      <category>React Native</category>
      <category>Android</category>
      <category>iOS</category>
      <category>Web Development</category>
      <content:encoded><![CDATA[<h2>Introduction</h2>
<p>The cross-platform mobile development landscape is evolving rapidly with new contenders challenging established solutions. Two notable technologies in this space are React Native, a mature framework developed by Meta (formerly Facebook), and Lynx, a newly open-sourced technology from ByteDance used extensively within TikTok. This blog post explores both technologies in detail, highlighting their architectural approaches, performance characteristics, developer experiences, and ideal use cases.</p>
<h2>Background and Evolution</h2>
<h3>React Native&#39;s Journey</h3>
<p>React Native emerged in 2015 as an extension of React&#39;s &quot;learn once, write anywhere&quot; philosophy. Over its nearly decade-long journey, it has undergone significant evolution:</p>
<ul>
<li>Initially introduced the concept of using JavaScript to control native UI components</li>
<li>Completed a multi-year &quot;New Architecture&quot; initiative with the recent 0.76 release</li>
<li>Moved from a bridge-based architecture to a more direct &quot;bridgeless&quot; approach</li>
<li>Established a vast ecosystem of libraries, tools, and community support</li>
<li>Recently integrated React 19 with concurrent rendering capabilities</li>
</ul>
<h3>Lynx&#39;s Emergence</h3>
<p>Lynx represents a newer approach, having been developed internally at ByteDance before its recent open-source release:</p>
<ul>
<li>Already powers significant parts of TikTok&#39;s interface at scale</li>
<li>Released as version 3.x, indicating its production-ready status</li>
<li>Designed specifically to address performance challenges in large-scale apps</li>
<li>Built with a focus on native-feeling experiences across platforms</li>
<li>Incorporates lessons learned from earlier cross-platform solutions</li>
</ul>
<h2>Architectural Deep Dive</h2>
<h3>React Native Architecture</h3>
<p>React Native&#39;s architecture has evolved substantially over time:</p>
<p><strong>Old Architecture:</strong></p>
<ul>
<li>JavaScript code communicated with native platforms via a JSON-based bridge</li>
<li>UI updates required serialization/deserialization, creating performance bottlenecks</li>
<li>Component trees managed separately in JS and native realms</li>
</ul>
<p><strong>New Architecture (current):</strong></p>
<ul>
<li><strong>JavaScript Interface (JSI)</strong>: Direct C++ interface between JavaScript and native code</li>
<li><strong>Fabric</strong>: C++ rendering system that improves UI updates and animations</li>
<li><strong>TurboModules</strong>: On-demand loading of native modules</li>
<li><strong>Codegen</strong>: Automatic generation of type-safe native interfaces</li>
<li><strong>Bridgeless Mode</strong>: Eliminates the legacy bridge for improved performance</li>
</ul>
<p><strong>Metro Bundler:</strong></p>
<ul>
<li>Custom JavaScript bundler optimized for React Native</li>
<li>Recent improvements include symlink support and faster resolution</li>
</ul>
<h3>Lynx Architecture</h3>
<p>Lynx takes a fundamentally different approach with its dual-threaded architecture:</p>
<p><strong>PrimJS Engine:</strong></p>
<ul>
<li>Custom JavaScript engine specifically optimized for UI workloads</li>
<li>Runs on the main UI thread for critical rendering and event handling</li>
</ul>
<p><strong>Background Thread:</strong></p>
<ul>
<li>Handles most application logic</li>
<li>Keeps the main thread free for responsive UI interaction</li>
</ul>
<p><strong>Static Thread Scheduling:</strong></p>
<ul>
<li>Clear division between main and background thread code</li>
<li>Enforced at build time for predictable performance</li>
</ul>
<p><strong>Custom Rendering Engine:</strong></p>
<ul>
<li>Platform-agnostic rendering approach</li>
<li>Consistent visual appearance across different platforms</li>
</ul>
<p><strong>Rspeedy Toolchain:</strong></p>
<ul>
<li>Rust-based bundler built on Rspack</li>
<li>Designed for fast builds and micro-frontend capabilities</li>
</ul>
<h2>Performance Characteristics</h2>
<h3>React Native Performance</h3>
<p>React Native has made significant performance strides:</p>
<ul>
<li><strong>Bridgeless Mode</strong>: Reduces overhead of JS-to-native communication</li>
<li><strong>Hermes Engine</strong>: Custom JavaScript engine with faster startup and lower memory usage</li>
<li><strong>Concurrent Rendering</strong>: React 19 integration enables time-sliced rendering</li>
<li><strong>Incremental Improvements</strong>: Each release brings optimization in specific areas</li>
<li><strong>Metro Optimizations</strong>: Faster build and reload times</li>
</ul>
<p>Despite these improvements, React Native still faces some challenges:</p>
<ul>
<li>Complex animations can sometimes drop frames</li>
<li>Initial load times can be noticeable on lower-end devices</li>
<li>Performance tuning often requires specialized knowledge</li>
</ul>
<h3>Lynx Performance</h3>
<p>Lynx was architected from the ground up with performance as a primary goal:</p>
<ul>
<li><strong>Instant First-Frame Rendering (IFR)</strong>: Eliminates blank screens during app launch</li>
<li><strong>Main-Thread Scripting (MTS)</strong>: Ensures responsive handling of critical UI interactions</li>
<li><strong>Reduced Launch Times</strong>: Claims 2-4x faster launches compared to web implementations</li>
<li><strong>Specialized Threading Model</strong>: Prevents UI thread blocking</li>
<li><strong>Optimized Asset Loading</strong>: Reduces time-to-interactive for complex UIs</li>
</ul>
<p>Benchmark claims from the Lynx team suggest particularly strong performance on Android devices, where React Native has historically faced more challenges.</p>
<h2>Developer Experience</h2>
<h3>React Native Developer Experience</h3>
<p>React Native offers a mature and refined developer experience:</p>
<ul>
<li><strong>Familiar React Paradigms</strong>: Component-based architecture with props and state</li>
<li><strong>Hot Reloading</strong>: Quick iteration during development</li>
<li><strong>React Native DevTools</strong>: New official debugging tools</li>
<li><strong>Rich Typings</strong>: Comprehensive TypeScript support</li>
<li><strong>Framework Integration</strong>: Works well with React ecosystem (Redux, React Query, etc.)</li>
<li><strong>Expo Framework</strong>: Optional toolchain for easier development</li>
</ul>
<p>Recent improvements include:</p>
<ul>
<li>Better error messages</li>
<li>Improved debugging with Hermes</li>
<li>More streamlined native module creation</li>
</ul>
<h3>Lynx Developer Experience</h3>
<p>Lynx emphasizes a web-like development approach:</p>
<ul>
<li><strong>Web-Standard CSS</strong>: Full support for animations, transitions, gradients, and effects</li>
<li><strong>Familiar Markup</strong>: HTML-like syntax for UI construction</li>
<li><strong>Static Thread Analysis</strong>: Clear boundaries between UI and logic code</li>
<li><strong>Hot Module Replacement</strong>: Quick feedback during development</li>
<li><strong>Multi-Framework Support</strong>: Not limited to React (ReactLynx is just one implementation)</li>
</ul>
<p>The main difference is Lynx&#39;s explicit focus on bringing web development paradigms to native app development, including CSS features that are sometimes challenging in React Native.</p>
<h2>Styling and UI Capabilities</h2>
<h3>React Native Styling</h3>
<p>React Native uses a JavaScript object-based styling approach:</p>
<pre><code class="language-javascript">const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: &#39;#fff&#39;,
    alignItems: &#39;center&#39;,
    justifyContent: &#39;center&#39;,
  },
});
</code></pre>
<p>Features include:</p>
<ul>
<li>Flexbox-based layouts</li>
<li>Platform-specific styling with <a href="http://Platform.select">Platform.select</a></li>
<li>Limited subset of CSS properties</li>
<li>Recent additions in 0.73-0.77 including percentage values in layout and improved box shadow support</li>
</ul>
<h3>Lynx Styling</h3>
<p>Lynx embraces web CSS more comprehensively:</p>
<pre><code class="language-javascript">&lt;view
  style={{
    background: &quot;radial-gradient(circle at top left, rgb(255,53,26), rgb(0,235,235))&quot;,
    maskImage: &quot;radial-gradient(circle 75px, black 75%, transparent)&quot;,
  }}
&gt;
  &lt;text&gt;LYNX&lt;/text&gt;
&lt;/view&gt;
</code></pre>
<p>Features include:</p>
<ul>
<li>Full CSS animations and transitions</li>
<li>Advanced visual effects (gradients, clipping, masking)</li>
<li>CSS variables for theming</li>
<li>More complete implementation of web styling capabilities</li>
</ul>
<h2>Ecosystem and Community</h2>
<h3>React Native Ecosystem</h3>
<p>As the more established platform, React Native boasts:</p>
<ul>
<li>Thousands of third-party libraries</li>
<li>Strong integration with native SDKs</li>
<li>Multiple framework options (Expo, Solito, etc.)</li>
<li>Community-maintained platform extensions (Windows, macOS, visionOS)</li>
<li>Regular contributors&#39; summits and well-defined governance</li>
<li>Extensive documentation and learning resources</li>
</ul>
<p>React Native also benefits from Meta&#39;s continued investment and the fact that many major companies have built significant applications with it.</p>
<h3>Lynx Ecosystem</h3>
<p>As a newly open-sourced technology, Lynx is just beginning its community journey:</p>
<ul>
<li>Strong backing from TikTok and ByteDance</li>
<li>Production-proven in high-scale applications</li>
<li>Commitment to open development on GitHub</li>
<li>Module Federation support for micro-frontends</li>
<li>Rust-based tooling aligning with industry trends</li>
</ul>
<p>While the ecosystem is nascent, the project starts with the advantage of being thoroughly tested in production at significant scale.</p>
<h2>Best Use Cases</h2>
<h3>When React Native Shines</h3>
<p>React Native is particularly well-suited for:</p>
<ol>
<li><strong>Teams with React Experience</strong>: Leverages existing web developer skills</li>
<li><strong>Startups and MVPs</strong>: Rapid development with a single team</li>
<li><strong>Apps Needing Wide Library Support</strong>: Access to thousands of ready-made solutions</li>
<li><strong>Cross-Platform Requirements</strong>: Supports iOS, Android, and optional desktop/web</li>
<li><strong>Brownfield Integration</strong>: Adding features to existing native apps</li>
<li><strong>Community-Driven Projects</strong>: Benefits from extensive documentation and resources</li>
</ol>
<h3>When Lynx May Be Preferable</h3>
<p>Lynx could be the better choice for:</p>
<ol>
<li><strong>Performance-Critical Applications</strong>: When every millisecond of launch time matters</li>
<li><strong>High-Interactivity UIs</strong>: Applications requiring extremely responsive touch handling</li>
<li><strong>Scale-Focused Organizations</strong>: Teams dealing with large codebases across platforms</li>
<li><strong>Advanced Visual Design Requirements</strong>: Projects needing rich CSS capabilities</li>
<li><strong>Non-React Framework Preferences</strong>: Teams wanting to use alternative frameworks</li>
<li><strong>Micro-Frontend Architectures</strong>: Organizations adopting modular application structures</li>
</ol>
<h2>Technical Comparison Table</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>React Native</th>
<th>Lynx</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Architecture</strong></td>
<td>Bridgeless with Fabric &amp; TurboModules</td>
<td>Dual-threaded with PrimJS</td>
</tr>
<tr>
<td><strong>JavaScript Engine</strong></td>
<td>Hermes (default)</td>
<td>PrimJS (custom)</td>
</tr>
<tr>
<td><strong>Rendering Approach</strong></td>
<td>Native UI components with Fabric</td>
<td>Custom rendering engine</td>
</tr>
<tr>
<td><strong>Thread Model</strong></td>
<td>Single JS thread with worklets</td>
<td>Strictly divided main/background threads</td>
</tr>
<tr>
<td><strong>CSS Support</strong></td>
<td>Subset of CSS</td>
<td>Comprehensive web-like CSS</td>
</tr>
<tr>
<td><strong>Animation System</strong></td>
<td>Animated API, Reanimated</td>
<td>Native CSS animations &amp; transitions</td>
</tr>
<tr>
<td><strong>Framework Support</strong></td>
<td>React-centric</td>
<td>Framework-agnostic (ReactLynx initial)</td>
</tr>
<tr>
<td><strong>Community Size</strong></td>
<td>Very large, established</td>
<td>New, but backed by TikTok</td>
</tr>
<tr>
<td><strong>Production Maturity</strong></td>
<td>Proven across thousands of apps</td>
<td>Proven in TikTok at scale</td>
</tr>
<tr>
<td><strong>Native Integration</strong></td>
<td>Strong, with JSI for direct access</td>
<td>Designed for performance-critical APIs</td>
</tr>
</tbody></table>
<h2>Conclusion</h2>
<p>Both React Native and Lynx represent compelling approaches to cross-platform mobile development, each with distinct advantages.</p>
<p><strong>React Native</strong> excels through its maturity, vast ecosystem, and proven track record across countless applications. Its recent architectural improvements address many historical performance concerns, and the community continues to innovate. For teams already using React and wanting the most straightforward path to cross-platform development, React Native remains an excellent choice.</p>
<p><strong>Lynx</strong> introduces fresh ideas with its dual-threaded architecture and performance-first approach. Its web-like development model and focus on scale make it particularly appealing for large applications where performance is paramount. While its ecosystem is still developing, the fact that it powers parts of one of the world&#39;s most popular apps gives it immediate credibility.</p>
<p>Rather than viewing these technologies as strict competitors, developers should appreciate having multiple options that address different needs and priorities. As both continue to evolve, the cross-platform development landscape will only become richer and more capable.</p>
<p>The best approach may be to evaluate your specific project requirements, team expertise, and performance needs rather than making a choice based solely on popularity or novelty. Both React Native and Lynx represent significant achievements in bringing native performance and web development together—the challenge is selecting the right tool for your particular journey.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A Beginner’s Guide to RTSP Streaming with WebSockets Using Node.js and FFmpeg</title>
      <link>https://anzalabidi.dev/writing/a-beginners-guide-to-rtsp-streaming-with-websockets-using-nodejs-and-ffmpeg/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/a-beginners-guide-to-rtsp-streaming-with-websockets-using-nodejs-and-ffmpeg/</guid>
      <pubDate>Sun, 15 Sep 2024 10:05:35 GMT</pubDate>
      <description>Real-Time Streaming Protocol (RTSP) is widely used for controlling media streams in surveillance systems, IP cameras, and more. However, interacting with RTSP streams directly in web applications can be challenging since browsers don’t natively suppo...</description>
      <category>Node.js</category>
      <category>streaming</category>
      <category>video</category>
      <category>FFmpeg</category>
      <category>Programming Blogs</category>
      <category>React</category>
      <category>HTML5</category>
      <category>npm</category>
      <category>JavaScript</category>
      <content:encoded><![CDATA[<p><strong>Real-Time Streaming Protocol</strong> (RTSP) is widely used for controlling media streams in surveillance systems, IP cameras, and more. However, interacting with RTSP streams directly in web applications can be challenging since browsers don’t natively support this protocol. The good news is that by leveraging <strong>FFmpeg</strong> and <strong>WebSockets</strong>, you can relay RTSP streams to a browser.</p>
<p>In this blog, I’ll walk you through the process of streaming RTSP feeds using Node.js and FFmpeg, as well as packaging this into a Docker container. We’ll also go over how to create an npm package that developers can use to set up their own RTSP-to-WebSocket relay server.</p>
<h2>What is RTSP?</h2>
<p>RTSP (Real-Time Streaming Protocol) is a network control protocol designed for use in entertainment and communications systems to control streaming media servers. It establishes and controls media sessions between endpoints and is often used to deliver live feeds, such as from IP cameras.</p>
<p>Unfortunately, modern browsers don’t directly support RTSP, so we need to find a way to relay the RTSP stream to a more browser-friendly format, such as WebSockets or HTTP.</p>
<h3>Why Use FFmpeg?</h3>
<p>FFmpeg is a powerful open-source tool that can handle multimedia streams like RTSP. It can transcode, decode, and relay streams in various formats. In this tutorial, FFmpeg will convert the RTSP stream into a format suitable for sending over WebSockets to a browser.</p>
<h3>The Role of WebSockets</h3>
<p>WebSockets enable two-way communication between a server and a client over a single, persistent connection. By relaying RTSP streams through WebSockets, we can push the stream data directly to the browser in real time.</p>
<hr>
<h2>Setting Up the Node.js RTSP Stream Relay</h2>
<h3>Step 1: Create a Basic Node.js Server</h3>
<p>We’ll start by creating a simple Node.js server that will listen for WebSocket connections and relay RTSP streams.</p>
<ol>
<li><p><strong>Initialize the Node.js Project</strong></p>
<p>First, create a project directory and initialize a new Node.js project:</p>
<pre><code class="language-bash"> mkdir rtsp-stream-relay
 cd rtsp-stream-relay
 npm init -y
</code></pre>
</li>
<li><p><strong>Install Required Dependencies</strong></p>
<p>We’ll need to install the following packages:</p>
<ul>
<li><code>express</code>: For creating the server.</li>
<li><code>cors</code>: For enabling Cross-Origin Resource Sharing.</li>
<li><code>rtsp-relay</code>: A package that simplifies relaying RTSP streams over WebSockets.</li>
</ul>
</li>
</ol>
<p>Install the required packages:</p>
<pre><code class="language-bash">    npm install express cors rtsp-relay
</code></pre>
<ol start="3">
<li><p><strong>Set Up the Express Server</strong></p>
<p>Create an <code>index.js</code> file and add the following code:</p>
<pre><code class="language-javascript"> const cors = require(&#39;cors&#39;);
 const express = require(&#39;express&#39;);
 const { proxy } = require(&#39;rtsp-relay&#39;);

 const app = express();
 app.use(cors());

 const handler = (url) =&gt; {
   return proxy({
     additionalFlags: [&#39;-q&#39;, &#39;1&#39;],  // Reduce quality for lower bandwidth
     url: url,
     transport: &#39;tcp&#39;,             // Use TCP for stream transport
     verbose: true,                // Print FFmpeg logs
   });
 };

 app.ws(&#39;/api/stream&#39;, (ws, req) =&gt; {
   const url = req.query.url;      // Get RTSP URL from query parameter
   handler(url)(ws, req);          // Proxy RTSP stream via WebSocket
 });

 app.listen(3000, () =&gt; {
   console.log(&#39;RTSP Stream relay running on port 3000&#39;);
 });
</code></pre>
</li>
</ol>
<p>This basic Express server listens for WebSocket connections on <code>/api/stream</code>, accepts an RTSP URL as a query parameter, and relays the stream via WebSocket.</p>
<h3>Step 2: Add FFmpeg to Handle RTSP</h3>
<p>FFmpeg is responsible for handling the actual RTSP stream. The <code>rtsp-relay</code> package internally uses FFmpeg to convert the RTSP stream into a format that can be sent via WebSocket.</p>
<p>The <code>proxy</code> function used in the <code>index.js</code> file relays the RTSP stream from the specified <code>url</code> and transmits it over WebSocket. This is where the stream is processed and relayed efficiently.</p>
<hr>
<h2>Step 3: Packaging the Server with Docker</h2>
<p>Next, we’ll containerize the entire application using Docker. This makes it easy to deploy on any platform without worrying about dependencies.</p>
<ol>
<li><p><strong>Create a Dockerfile</strong></p>
<p>Create a <code>Dockerfile</code> to define the container environment:</p>
<pre><code class="language-dockerfile"> FROM ubuntu:22.04

 RUN apt-get update &amp;&amp; apt-get install -y ffmpeg

 RUN apt-get install -y curl
 RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
 RUN apt-get install -y nodejs

 WORKDIR /app
 COPY package.json yarn.lock ./
 RUN npm install

 COPY . .

 EXPOSE 3000

 CMD [&quot;node&quot;, &quot;index.js&quot;]
</code></pre>
</li>
</ol>
<p>This Dockerfile uses an Ubuntu base image, installs FFmpeg and Node.js, and runs the Node.js server on port <code>3000</code>.</p>
<ol start="2">
<li><p><strong>Build and Run the Docker Image</strong></p>
<p>Build the Docker image and run the container:</p>
<pre><code class="language-bash"> docker build -t rtsp-relay-app .
 docker run -p 3000:3000 rtsp-relay-app
</code></pre>
</li>
</ol>
<p>Your RTSP relay server is now running inside the Docker container!</p>
<hr>
<h2>Step 4: Viewing the Stream in a Browser</h2>
<p>To consume the WebSocket stream in a browser, you’ll need to use the <code>MediaSource</code> API or a video player that supports WebSocket.</p>
<h3>React Example</h3>
<p>You can use React to display the video stream:</p>
<pre><code class="language-jsx">import React, { useEffect, useRef } from &quot;react&quot;;

const RTSPStream = ({ streamUrl }) =&gt; {
  const videoRef = useRef(null);

  useEffect(() =&gt; {
    const ws = new WebSocket(`ws://localhost:3000/api/stream?url=${streamUrl}`);
    ws.onmessage = (event) =&gt; {
      const video = videoRef.current;
      const mediaSource = new MediaSource();
      video.src = URL.createObjectURL(mediaSource);
      mediaSource.addEventListener(&quot;sourceopen&quot;, () =&gt; {
        const sourceBuffer = mediaSource.addSourceBuffer(&#39;video/mp4; codecs=&quot;avc1.42E01E&quot;&#39;);
        sourceBuffer.appendBuffer(event.data);
      });
    };
  }, [streamUrl]);

  return &lt;video ref={videoRef} controls autoPlay /&gt;;
};

export default RTSPStream;
</code></pre>
<p>This React component establishes a WebSocket connection and renders the stream in a video element.</p>
<h2>Conclusion</h2>
<p>Streaming RTSP feeds to the browser isn’t natively supported, but by using FFmpeg and WebSockets with a Node.js server, you can create a real-time, two-way relay that efficiently delivers RTSP streams to web clients.</p>
<p>With a Dockerized environment and an npm package, this solution becomes even more accessible and portable for any development workflow.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Coinbase Interview Experience [SDE-1 Remote]</title>
      <link>https://anzalabidi.dev/writing/coinbase-interview-experience-sde-1-remote/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/coinbase-interview-experience-sde-1-remote/</guid>
      <pubDate>Wed, 01 May 2024 17:43:07 GMT</pubDate>
      <description>Initial Contact In mid-February, I approached the recruiter via a cold email. After a few days, they reached out to me and sent an online assessment, which consisted of four LeetCode-style problems: one easy, two medium, and one hard. I solved three ...</description>
      <category>software development</category>
      <category>software architecture</category>
      <category>Web Development</category>
      <category>DSA</category>
      <category>remote</category>
      <category>interview</category>
      <content:encoded><![CDATA[<h2>Initial Contact</h2>
<p>In mid-February, I approached the recruiter via a cold email. After a few days, they reached out to me and sent an online assessment, which consisted of four LeetCode-style problems: one easy, two medium, and one hard. I solved three and a half problems successfully.</p>
<h2>Phone Screening</h2>
<p>Following the online assessment, the recruiter emailed me to schedule a phone screening round. During this 30-minute call, we discussed my previous work experience and resume. The recruiter also provided me with details about the hiring process.</p>
<h2>Technical Interviews</h2>
<p>After the phone screening, the recruiter sent me an email to book slots for two technical interviews. Each round had a single hard question with follow-ups spanning three levels. The main focus for these rounds was on optimization, factory patterns, and code readability.</p>
<h3>Round 1</h3>
<p>In the first round, the question was related to replicating a bank system, where I had to keep records of users and list out updates after given transactions, i solved all the levels in this round and the interviewer was pretty satisfied.</p>
<h3>Round 2</h3>
<p>The second round had a question on log parsing, where a log file for a multi-threaded operating system was provided, and I had to parse it based on given conditions, along with optimizing some given functions. I was able to solve 2 levels here but I got stuck on the last level and it took me a while to get the actual idea for the optimization and I ran out of time due to this.</p>
<h2>Outcome</h2>
<p>Unfortunately, I couldn&#39;t clear the last round. Nevertheless, it was a great discussion, and the preparation for these interviews significantly improved my code-writing abilities.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Zomato SDE Interview Experience</title>
      <link>https://anzalabidi.dev/writing/zomato-sde-interview-experience/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/zomato-sde-interview-experience/</guid>
      <pubDate>Tue, 16 Apr 2024 08:24:33 GMT</pubDate>
      <description>Introduction A few months ago, I decided to apply for the SDE position at Zomato, one of the leading food delivery platforms in India. I was really excited about the opportunity, as Zomato is known for its innovative technology and impressive enginee...</description>
      <category>interview</category>
      <category>software development</category>
      <category>technology</category>
      <category>Software Engineering</category>
      <category>Web Development</category>
      <category>Devops</category>
      <category>Developer</category>
      <content:encoded><![CDATA[<h3>Introduction</h3>
<p>A few months ago, I decided to apply for the SDE position at Zomato, one of the leading food delivery platforms in India. I was really excited about the opportunity, as Zomato is known for its innovative technology and impressive engineering team.</p>
<p>To get my foot in the door, I took an unconventional approach - I directly emailed Zomato&#39;s CEO, Deepinder Goyal, expressing my interest in the role and highlighting my relevant skills and experience. To my surprise, this strategy worked, and I soon received a follow-up email from one of Zomato&#39;s team leads to schedule an interview.</p>
<h3>The Interview Process</h3>
<p>The interview process consisted of three rounds, each serving as an elimination round.</p>
<h4>Round 1</h4>
<p>The first round was with an SDE2, who grilled me on my knowledge of React, server-side rendering, and the internal workings of front-end frameworks. I also had to tackle a challenging LeetCode-style coding problem at the end of this round.</p>
<h4>Round 2</h4>
<p>The second round was with an Engineering Manager, and the focus shifted more towards hands-on coding. He asked me probing questions about React, such as the diffing algorithm, the reconciliation process, and the rules around custom hooks. I also had to implement basic versions of useState and useEffect, and explain concepts like closures, the differences between let and var, and the advantages of using Tailwind CSS over CSS-in-JS. We also discussed my experience with Docker and its internal implementation.</p>
<h4>Round 3</h4>
<p>The final round was with the VP of Engineering. This was more of a conversational interview, where I was given an overview of Zomato&#39;s culture and what to expect as an SDE-1. The VP also asked me about what I could bring to the table and how I would contribute to the team.</p>
<h3>Conclusion</h3>
<p>After successfully navigating these three rounds, I was thrilled to receive a job offer from Zomato. The interview process was undoubtedly challenging, but it also gave me a glimpse into the company&#39;s high standards and commitment to building a strong engineering team.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A Deep Dive into Retryable Jobs with BullMQ</title>
      <link>https://anzalabidi.dev/writing/a-deep-dive-into-retryable-jobs-with-bullmq/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/a-deep-dive-into-retryable-jobs-with-bullmq/</guid>
      <pubDate>Mon, 16 Oct 2023 15:07:06 GMT</pubDate>
      <description>Messaging queues are a fundamental part of modern software architecture. They enable the decoupling of services, improving scalability, and resilience. In this blog, we&#39;ll explore messaging queues, why they are essential, and provide a simple TypeScr...</description>
      <category>Web Development</category>
      <category>Node.js</category>
      <category>server</category>
      <category>JavaScript</category>
      <category>TypeScript</category>
      <content:encoded><![CDATA[<p>Messaging queues are a fundamental part of modern software architecture. They enable the decoupling of services, improving scalability, and resilience. In this blog, we&#39;ll explore messaging queues, why they are essential, and provide a simple TypeScript code example.</p>
<h3><strong>What Are Messaging Queues?</strong></h3>
<p>Messaging queues are a communication mechanism that allows different parts of a software system to exchange information asynchronously. They provide a way for various components or services to interact without knowing anything about each other. This decoupling is crucial in distributed systems and microservices architectures, where independence and scalability are vital.</p>
<h3><strong>Why Use Messaging Queues?</strong></h3>
<ol>
<li><strong>Decoupling:</strong> Components can work independently without direct dependencies on each other.</li>
<li><strong>Scalability:</strong> New consumers or producers can be added without impacting existing services.</li>
<li><strong>Reliability:</strong> Messages are stored until successfully processed, reducing data loss.</li>
<li><strong>Load Balancing:</strong> Distributes work evenly among consumers.</li>
<li><strong>Asynchronous Communication:</strong> Allows for non-blocking, event-driven architectures.</li>
</ol>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/0*r2scSeajH28VEbQC" alt=""></p>
<h2>A Real world example :</h2>
<p><a href="https://docs.bullmq.io/">BullMQ</a> is a powerful job and task queue library for Node.js. It&#39;s excellent for managing background jobs and tasks, and it offers a wide range of features, including retryable jobs. Retryable jobs are essential for handling tasks that might fail temporarily, such as sending emails, making API requests, or other I/O operations.</p>
<p><strong>Use Case for Retryable Jobs:</strong></p>
<p>Imagine you&#39;re building an e-commerce platform, and you need to send order confirmation emails to customers. While sending these emails, there could be occasional network issues or problems with the email service provider. In such cases, you don&#39;t want to lose these emails; you want to retry sending them a few times before considering them failed.</p>
<p>Here&#39;s a demo of how to use BullMQ for handling retryable jobs in TypeScript:</p>
<p><strong>Install Dependencies:</strong></p>
<pre><code class="language-powershell">npm install bullmq ioredis
</code></pre>
<p><strong>Producer Code (sending order confirmation emails):</strong></p>
<pre><code class="language-typescript">import { Queue, Worker } from &#39;bullmq&#39;;

const emailQueue = new Queue(&#39;emailQueue&#39;);

async function sendOrderConfirmation(orderId: number, email: string) {
  // Simulate sending the email (replace with actual email sending logic).
  // You can deliberately introduce failures to demonstrate retries.
  if (Math.random() &lt; 0.5) {
    throw new Error(&#39;Failed to send email&#39;);
  }

  // Email sent successfully.
  console.log(`Email sent for order ${orderId} to ${email}`);
}

async function sendEmailJob(orderId: number, email: string) {
  try {
    await sendOrderConfirmation(orderId, email);
  } catch (error) {
    // The job failed; BullMQ will handle retries.
    throw error;
  }
}

emailQueue.add(&#39;send-email&#39;, { orderId: 1, email: &#39;example@example.com&#39; });
</code></pre>
<p><strong>Consumer Code (retrying failed jobs):</strong></p>
<pre><code class="language-typescript">import { Worker } from &#39;bullmq&#39;;

const emailQueue = new Worker(&#39;emailQueue&#39;, async (job) =&gt; {
  console.log(`Processing job for order ${job.data.orderId} to ${job.data.email}`);
  await sendEmailJob(job.data.orderId, job.data.email);
});

emailQueue.on(&#39;completed&#39;, (job) =&gt; {
  console.log(`Job completed for order ${job.data.orderId}`);
});

emailQueue.on(&#39;failed&#39;, (job, err) =&gt; {
  console.error(`Job failed for order ${job.data.orderId}: ${err.message}`);
});
</code></pre>
<p>In this example:</p>
<ol>
<li>The producer code sends email jobs to the <code>emailQueue</code>. It simulates sending emails and occasionally throws an error to mimic a failure.</li>
<li>The consumer code processes jobs from the <code>emailQueue</code>. If a job fails (due to the deliberate error thrown), BullMQ will automatically retry it according to its configured retry settings. You can configure these settings, such as the number of retries and the retry delay, when creating the queue.</li>
</ol>
<p>Retryable jobs are crucial for handling transient failures, ensuring that critical tasks like sending emails are eventually delivered. BullMQ makes it easier to manage these scenarios, providing a reliable way to process tasks even in the face of temporary issues.</p>
<h3>Some popularly used Queues :</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697468554818/1e08b312-429c-4758-a949-a5b5dcf4376b.gif" alt=""></p>
]]></content:encoded>
    </item>
    <item>
      <title>Monerepo Architecture with Nx and Next.js</title>
      <link>https://anzalabidi.dev/writing/monerepo-architecture-with-nx-and-nextjs/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/monerepo-architecture-with-nx-and-nextjs/</guid>
      <pubDate>Wed, 07 Jun 2023 19:10:28 GMT</pubDate>
      <description>Introduction to monorepo architecture What is a monorepo ? Monorepo architecture, short for \&quot;monolithic repository architecture,\&quot; is a software development approach where multiple projects or components are stored within a single repository. Instead ...</description>
      <category>newbie</category>
      <category>Web Development</category>
      <category>Next.js</category>
      <category>Developer</category>
      <category>webdev</category>
      <content:encoded><![CDATA[<h2>Introduction to monorepo architecture</h2>
<h3>What is a monorepo ?</h3>
<p>Monorepo architecture, short for &quot;monolithic repository architecture,&quot; is a software development approach where multiple projects or components are stored within a single repository. Instead of maintaining separate repositories for each project or component, all the code, assets, and related resources are consolidated into a single repository.</p>
<p>In a monorepo, you would typically find multiple directories or folders, each representing a different project or component. These projects or components might be related to each other, such as different services of a larger application or different libraries used across multiple projects. By organizing them together, it becomes easier to manage and coordinate changes, dependencies, and version control.</p>
<p>There are a few advantages to using a monorepo architecture:</p>
<ol>
<li><strong>Code sharing and reuse</strong>: With all the projects in one repository, it&#39;s easier to share and reuse code between different components. Developers can extract shared libraries, utilities, or modules that can be utilized across the entire codebase.</li>
<li><strong>Simplified dependency management</strong>: In a monorepo, managing dependencies becomes more straightforward. Instead of dealing with separate dependencies for each project, you can have a centralized dependency management system. This can reduce conflicts, ensure consistent versions, and simplify the overall build process.</li>
<li><strong>Consistent versioning</strong>: Since all projects are within the same repository, it&#39;s easier to ensure consistent versioning across different components. You can tag releases, manage changelogs, and track version history more efficiently.</li>
<li><strong>Easier code refactoring and collaboration</strong>: Having a monorepo can facilitate collaboration among developers. It&#39;s easier to refactor code across different projects, perform cross-project refactorings, and make sweeping changes if required. Developers can also work on multiple projects simultaneously, making it simpler to coordinate changes and releases.</li>
</ol>
<p>However, there are also some challenges and considerations with monorepo architecture:</p>
<ol>
<li><strong>Increased repository size</strong>: Since all projects are stored in a single repository, the overall size of the repository can grow significantly. This can impact clone times, disk space requirements, and the performance of certain operations.</li>
<li><strong>Build and test complexity</strong>: As the number of projects or components increases, the build and test processes can become more complex. Building and testing the entire monorepo can be time-consuming and resource-intensive. It requires a robust build system and efficient test suites to manage these complexities effectively.</li>
<li><strong>Organization and access control</strong>: With multiple projects in a monorepo, it&#39;s important to have a clear organization and access control mechanisms in place. Developers need to understand the repository structure and have proper permissions to work on specific projects or components.</li>
</ol>
<p>Overall, monorepo architecture can be a powerful approach for managing large-scale software projects or interconnected components. It provides advantages such as code sharing, simplified dependency management, and easier collaboration. However, it also requires careful planning, tooling, and consideration of potential challenges to ensure successful implementation.</p>
<h2>How to set a monorepo with Nx and Next.js</h2>
<h3>Project Setup</h3>
<p>We&#39;ll begin by creating a default Next.js application with a Typescript template.</p>
<pre><code class="language-powershell">npx create-next-app --ts nextjs-fullstack-app-template

cd nextjs-fullstack-app-template
</code></pre>
<p>First we will test to make sure the app is working. We&#39;re going to be using <code>yarn</code> for this example, but you could just as easily use NPM if you choose.</p>
<pre><code class="language-powershell">yarn install

yarn dev
</code></pre>
<p>Also recommended to run</p>
<pre><code class="language-powershell">yarn build
</code></pre>
<p>To ensure you can successfully do a production build of the project. It&#39;s recommended (but not required) to close your dev server when running a Next.js build. Most of the time there is no issue but occasionally the build can put your dev server in a weird state that requires a restart.</p>
<p>You should get a nice little report on the command line of all the pages built with green coloured text implying they are small and efficient. We&#39;ll try to keep them that way as we develop the project.</p>
<h3>Engine Locking</h3>
<p>We would like for all developers working on this project to use the same Node engine and package manager we are using. To do that we create two new files:</p>
<ul>
<li><code>.nvmrc</code> - Will tell other uses of the project which version of Node is used</li>
<li><code>.npmrc</code> - Will tell other users of the project which package manager is used</li>
</ul>
<p>We are using <code>Node v14 Fermium</code> and <code>yarn</code> for this project so we set those values like so:</p>
<p><code>.nvmrc</code></p>
<pre><code class="language-powershell">lts/fermium
</code></pre>
<p><code>.npmrc</code></p>
<pre><code class="language-json">engine-strict=true
</code></pre>
<p>You can check your version of Node with <code>node --version</code> and make sure you are setting the correct one. A list of Node version codenames can be found <a href="https://github.com/nodejs/Release/blob/main/CODENAMES.md">here</a></p>
<p>Note that the use of <code>engine-strict</code> didn&#39;t specifically say anything about <code>yarn</code>, we do that in <code>package.json</code>:</p>
<p><code>package.json</code></p>
<pre><code class="language-json">  &quot;name&quot;: &quot;nextjs-fullstack-app-template&quot;,
  &quot;author&quot;: &quot;YOUR_NAME&quot;,
  &quot;description&quot;: &quot;A tutorial and template for creating a production-ready fullstack Next.js application&quot;,
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;private&quot;: true,
  &quot;license&quot; : &quot;MIT&quot;
  &quot;homepage&quot;: &quot;YOUR_GIT_REPO_URL&quot;
  &quot;engines&quot;: {
    &quot;node&quot;: &quot;&gt;=14.0.0&quot;,
    &quot;yarn&quot;: &quot;&gt;=1.22.0&quot;,
    &quot;npm&quot;: &quot;please-use-yarn&quot;
  },
  ...
</code></pre>
<p>The <code>engines</code> field is where you specify the specific versions of the tools you are using. You can also fill in your personal details if you choose.</p>
<h3>Git Setup</h3>
<p>This would be a good time to make our first commit to our remote repo, to make sure our changes are backed up, and to follow best practices for keeping related changes grouped within a single commit before moving to something new.</p>
<p>By default your Next.js project will already have a repo initialized. You can check what branch you are on with <code>git status</code>. It should say something like:</p>
<pre><code class="language-powershell">On branch main
Changes not staged for commit:
  (use &quot;git add &lt;file&gt;...&quot; to update what will be committed)
  (use &quot;git restore &lt;file&gt;...&quot; to discard changes in working directory)
        modified:   README.md

Untracked files:
  (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)
        .npmrc
        .nvmrc
</code></pre>
<p>This tells us we are on the <code>main</code> branch and we have not staged or made any commits yet.</p>
<p>Let&#39;s commit our changes so far.</p>
<pre><code class="language-powershell">git add .

git commit -m &#39;project initialization&#39;
</code></pre>
<p>The first command will add and stage all files in your project directory that aren&#39;t ignored in <code>.gitignore</code>. The second will make a commit of the state of your current project with the message we wrote after the <code>-m</code> flag.</p>
<p>Hop over to your preferred git hosting provider (<a href="https://github.com/">Github</a> for example) and create a new repository to host this project. Make sure the default branch is se tto the same name as the branch on your local machine to avoid any confusion.</p>
<p>On Github you can change your global default branch name to whatever you like by going to:</p>
<pre><code class="language-powershell">Settings -&gt; Repositories -&gt; Repository default branch
</code></pre>
<p>Now you are ready to add the remote origin of your repository and push. Github will give you the exact instructions when you create it. Your syntax may be a little different than mine depending on if you are using HTTPS rather than SSH.</p>
<pre><code class="language-powershell">git remote add origin git@github.com:{YOUR_GITHUB_USERNAME}/{YOUR_REPOSITORY_NAME}.git

git push -u origin {YOUR_BRANCH_NAME}
</code></pre>
<p>Note that from this point on we will be using the <a href="https://www.conventionalcommits.org/en/v1.0.0/#summary">Conventional Commits</a> standard and specifically the Angular convention <a href="https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#type">described here</a></p>
<p>The reason being like many other features in this project to simply set a <strong>consistent</strong> standard for all developers to use to minimize train-up time when contributing to the project. I personally have very little concern as to what standard is chosen, as long as everyone agrees to follow it that is the most important thing.</p>
<p>Consistency is everything!</p>
<h3>Code Formatting and Quality Tools</h3>
<p>In order to set a standard that will be used by all contributors to the project to keep the code style consistent and basic best practices followed we will be implementing two tools:</p>
<ul>
<li><a href="https://eslint.org/">eslint</a> - For best practices on coding standards</li>
<li><a href="https://prettier.io/">prettier</a> - For automatic formatting of code files</li>
</ul>
<h3>ESLint</h3>
<p>We&#39;ll begin with ESLint, which is easy because it automatically comes installed and pre-configured with Next.js projects.</p>
<p>We are just going to add a little bit of extra configuration and make it a bit stricter than it is by default. If you disagree with any of the rules it sets, no need to worry, it&#39;s very easy to disable any of them manually. We configure everything in <code>.eslintrc.json</code> which should already exist in your root directory:</p>
<p><code>.eslintrc.json</code></p>
<pre><code class="language-json">{
  &quot;extends&quot;: [&quot;next&quot;, &quot;next/core-web-vitals&quot;, &quot;eslint:recommended&quot;],
  &quot;globals&quot;: {
    &quot;React&quot;: &quot;readonly&quot;
  },
  &quot;rules&quot;: {
    &quot;no-unused-vars&quot;: [1, { &quot;args&quot;: &quot;after-used&quot;, &quot;argsIgnorePattern&quot;: &quot;^_&quot; }]
  }
}
</code></pre>
<p>In the above small code example we have added a few additional defaults, we have said that <code>React</code> will always be defined even if we don&#39;t specifically import it, and I have added a personal custom rule that I like which allows you to prefix variables with an underscore _ if you have declared them but not used them in the code.</p>
<p>I find that scenario comes up often when you are working on a feature and want to prepare variables for use later, but have not yet reached the point of implementing them.</p>
<p>You can test out your config by running:</p>
<pre><code class="language-powershell">yarn lint
</code></pre>
<p>You should get a message like:</p>
<pre><code class="language-powershell">✔ No ESLint warnings or errors
Done in 1.47s.
</code></pre>
<p>If you get any errors then ESLint is quite good at explaining clearly what they are. If you encounter a rule you don&#39;t like you can disable it in &quot;rules&quot; by simply setting it to 1 (warning) or 0 (ignore) like so:</p>
<pre><code class="language-json">  &quot;rules&quot;: {
    &quot;no-unused-vars&quot;: 0, // As example: Will never bug you about unused variables again
  }
</code></pre>
<p>Let&#39;s make a commit at this point with the message <code>build: configure eslint</code></p>
<h3>Prettier</h3>
<p>Prettier will take care of automatically formatting our files for us. Let&#39;s add it to the project now.</p>
<p>It&#39;s only needed during development, so I&#39;ll add it as a <code>devDependency</code> with <code>-D</code></p>
<pre><code class="language-powershell">yarn add -D prettier
</code></pre>
<p>I also recommend you get the <a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode">Prettier VS Code extension</a> so that VS Code can handle the formatting of the files for you and you don&#39;t need to rely on the command line tool. Having it installed and configured in your project means that VSCode will use your project&#39;s settings, so it&#39;s still necessary to add it here.</p>
<p>We&#39;ll create two files in the root:</p>
<p><code>.prettierrc</code></p>
<pre><code class="language-json">{
  &quot;trailingComma&quot;: &quot;es5&quot;,
  &quot;tabWidth&quot;: 2,
  &quot;semi&quot;: true,
  &quot;singleQuote&quot;: true
}
</code></pre>
<p>Those values are entirely at your discretion as to what is best for your team and project.</p>
<p><code>.prettierignore</code></p>
<pre><code class="language-plaintext">.yarn
.next
dist
node_modules
</code></pre>
<p>In that file I&#39;ve placed a list of directories that I don&#39;t want Prettier to waste any resources working on. You can also use patterns like *.html to ignore groups of types of files if you choose.</p>
<p>Now we add a new script to <code>package.json</code> so we can run Prettier:</p>
<p><code>package.json</code></p>
<pre><code class="language-json">  ...
  &quot;scripts: {
    ...
    &quot;prettier&quot;: &quot;prettier --write .&quot;
  }
</code></pre>
<p>You can now run</p>
<pre><code class="language-powershell">yarn prettier
</code></pre>
<p>to automatically format, fix and save all files in your project you haven&#39;t ignored. By default my formatter updated about 5 files. You can see them in your list of changed files in the source control tab on the left of VS Code.</p>
<p>Let&#39;s make another commit with <code>build: implement prettier</code>.</p>
<h2>Git Hooks</h2>
<p>One more section on configuration before we start getting into component development. Remember you&#39;re going to want this project to be as rock solid as possible if you&#39;re going to be building on it in the long term, particularly with a team of other developers. It&#39;s worth the time to get it right at the start.</p>
<p>We are going to implement a tool called <a href="https://typicode.github.io/husky/#/">Husky</a></p>
<p>Husky is a tool for running scripts at different stages of the git process, for example add, commit, push, etc. We would like to be able to set certain conditions, and only allow things like commit and push to succeed if our code meets those conditions, presuming that it indicates our project is of acceptable quality.</p>
<p>To install Husky run</p>
<pre><code class="language-powershell">yarn add -D husky

npx husky install
</code></pre>
<p>The second command will create a <code>.husky</code> directory in your project. This is where your hooks will live. Make sure this directory is included in your code repo as it&#39;s intended for other developers as well, not just yourself.</p>
<p>Add the following script to your <code>package.json</code> file:</p>
<p><code>package.json</code></p>
<pre><code class="language-json">  ...
  &quot;scripts: {
    ...
    &quot;prepare&quot;: &quot;husky install&quot;
  }
</code></pre>
<p>This will ensure Husky gets installed automatically when other developers run the project.</p>
<p>To create a hook run</p>
<pre><code class="language-powershell">npx husky add .husky/pre-commit &quot;yarn lint&quot;
</code></pre>
<p>The above says that in order for our commit to succeed, the <code>yarn lint</code> script must first run and succeed. &quot;Succeed&quot; in this context means no errors. It will allow you to have warnings (remember in the ESLint config a setting of 1 is a warning and 2 is an error in case you want to adjust settings).</p>
<p>Let&#39;s create a new commit with the message <code>ci: implement husky</code>. If all has been setup properly your lint script should run before the commit is allowed to occur.</p>
<p>We&#39;re going to add another one:</p>
<pre><code class="language-powershell">npx husky add .husky/pre-push &quot;yarn build&quot;
</code></pre>
<p>The above ensures that we are not allowed to push to the remote repository unless our code can successfully build. That seems like a pretty reasonable condition doesn&#39;t it? Feel free to test it by committing this change and trying to push.</p>
<hr>
<p>Lastly we are going to add one more tool. We have been following a standard convention for all our commit messages so far, let&#39;s ensure that everyone on the team is following them as well (including ourselves!). We can add a linter for our commit messages:</p>
<pre><code class="language-powershell">yarn add -D @commitlint/config-conventional @commitlint/cli
</code></pre>
<p>To configure it we will be using a set of standard defaults, but I like to include that list explicitly in a <code>commitlint.config.js</code> file since I sometimes forget what prefixes are available:</p>
<p><code>commitlint.config.js</code></p>
<pre><code class="language-js">// build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
// ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
// docs: Documentation only changes
// feat: A new feature
// fix: A bug fix
// perf: A code change that improves performance
// refactor: A code change that neither fixes a bug nor adds a feature
// style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
// test: Adding missing tests or correcting existing tests

module.exports = {
  extends: [&#39;@commitlint/config-conventional&#39;],
  rules: {
    &#39;body-leading-blank&#39;: [1, &#39;always&#39;],
    &#39;body-max-line-length&#39;: [2, &#39;always&#39;, 100],
    &#39;footer-leading-blank&#39;: [1, &#39;always&#39;],
    &#39;footer-max-line-length&#39;: [2, &#39;always&#39;, 100],
    &#39;header-max-length&#39;: [2, &#39;always&#39;, 100],
    &#39;scope-case&#39;: [2, &#39;always&#39;, &#39;lower-case&#39;],
    &#39;subject-case&#39;: [
      2,
      &#39;never&#39;,
      [&#39;sentence-case&#39;, &#39;start-case&#39;, &#39;pascal-case&#39;, &#39;upper-case&#39;],
    ],
    &#39;subject-empty&#39;: [2, &#39;never&#39;],
    &#39;subject-full-stop&#39;: [2, &#39;never&#39;, &#39;.&#39;],
    &#39;type-case&#39;: [2, &#39;always&#39;, &#39;lower-case&#39;],
    &#39;type-empty&#39;: [2, &#39;never&#39;],
    &#39;type-enum&#39;: [
      2,
      &#39;always&#39;,
      [
        &#39;build&#39;,
        &#39;chore&#39;,
        &#39;ci&#39;,
        &#39;docs&#39;,
        &#39;feat&#39;,
        &#39;fix&#39;,
        &#39;perf&#39;,
        &#39;refactor&#39;,
        &#39;revert&#39;,
        &#39;style&#39;,
        &#39;test&#39;,
        &#39;translation&#39;,
        &#39;security&#39;,
        &#39;changeset&#39;,
      ],
    ],
  },
};
</code></pre>
<p>Then enable commitlint with Husky by using:</p>
<pre><code class="language-powershell">npx husky add .husky/commit-msg &#39;npx --no -- commitlint --edit &quot;$1&quot;&#39;
# Sometimes above command doesn&#39;t work in some command interpreters
# You can try other commands below to write npx --no -- commitlint --edit $1
# in the commit-msg file.
npx husky add .husky/commit-msg \&quot;npx --no -- commitlint --edit &#39;$1&#39;\&quot;
# or
npx husky add .husky/commit-msg &quot;npx --no -- commitlint --edit $1&quot;
</code></pre>
<p>Feel free to try some commits that <em>don&#39;t</em> follow the rules and see how they are not accepted, and you receive feedback that is designed to help you correct them.</p>
<h3>VS Code Configuration</h3>
<p>Now that we have implemented ESLint and Prettier we can take advantage of some convenient VS Code functionality to have them be run automatically.</p>
<p>Create a directory in the root of your project called <code>.vscode</code> and inside a file called <code>settings.json</code>. This will be a list of values that override the default settings of your installed VS Code.</p>
<p>The reason we want to place them in a folder for the project is that we can set specific settings that only apply to this project, and we can share them with the rest of our team by including them in the code repository.</p>
<p>Within <code>settings.json</code> we will add the following values:</p>
<p><code>.vscode/settings.json</code></p>
<pre><code class="language-json">{
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;,
  &quot;editor.formatOnSave&quot;: true,
  &quot;editor.codeActionsOnSave&quot;: {
    &quot;source.fixAll&quot;: true,
    &quot;source.organizeImports&quot;: true
  }
}
</code></pre>
<p>The above will tell VS Code to use your Prettier extension as the default formatter (you can override manually if you wish with another one) and to automatically format your files and organize your import statements every time you save.</p>
<p>Very handy stuff and just another thing you no longer need to think about so you can focus on the important things like solving business problems.</p>
<p>I&#39;ll now make a commit with message <code>build: implement vscode project settings</code>.</p>
<h3>Debugging</h3>
<p>Let&#39;s set up a convenient environment for debugging our application in case we run into any issues during development.</p>
<p>Inside of your <code>.vscode</code> directory create a <code>launch.json</code> file:</p>
<p><code>launch.json</code></p>
<pre><code class="language-json">{
  &quot;version&quot;: &quot;0.1.0&quot;,
  &quot;configurations&quot;: [
    {
      &quot;name&quot;: &quot;Next.js: debug server-side&quot;,
      &quot;type&quot;: &quot;node-terminal&quot;,
      &quot;request&quot;: &quot;launch&quot;,
      &quot;command&quot;: &quot;npm run dev&quot;
    },
    {
      &quot;name&quot;: &quot;Next.js: debug client-side&quot;,
      &quot;type&quot;: &quot;pwa-chrome&quot;,
      &quot;request&quot;: &quot;launch&quot;,
      &quot;url&quot;: &quot;http://localhost:3000&quot;
    },
    {
      &quot;name&quot;: &quot;Next.js: debug full stack&quot;,
      &quot;type&quot;: &quot;node-terminal&quot;,
      &quot;request&quot;: &quot;launch&quot;,
      &quot;command&quot;: &quot;npm run dev&quot;,
      &quot;console&quot;: &quot;integratedTerminal&quot;,
      &quot;serverReadyAction&quot;: {
        &quot;pattern&quot;: &quot;started server on .+, url: (https?://.+)&quot;,
        &quot;uriFormat&quot;: &quot;%s&quot;,
        &quot;action&quot;: &quot;debugWithChrome&quot;
      }
    }
  ]
}
</code></pre>
<p>With that script in place you have three choices for debugging. CLick the little &quot;bug &amp; play icon&quot; on the left of VS Code or press <code>Ctrl + Shift + D</code> to access the debugging menu. You can select which script you want to run and start/stop it with the start/stop buttons.</p>
<p>In addition to this, or if you are not using VS Code, we can also set up some helpful debugging scripts in your project.</p>
<p>First we will install the <a href="https://www.npmjs.com/package/cross-env">cross-env</a> which will; be necessary to set environment variables if you have teammates working on different environments (Windows, Linux, Mac, etc).</p>
<pre><code class="language-powershell">yarn add -D cross-env
</code></pre>
<p>With that package installed we can update our <code>package.json</code> <code>dev</code> script to look like the following:</p>
<p><code>package.json</code></p>
<pre><code class="language-json">{
  ...
  &quot;scripts&quot;: {
    ...
    &quot;dev&quot;: &quot;cross-env NODE_OPTIONS=&#39;--inspect&#39; next dev&quot;,
  },
}
</code></pre>
<p>This will allow you to log server data in the browser while working in dev mode, making it easier to debug issues.</p>
<p>At this stage I&#39;ll be making a new commit with message <code>build: add debugging configuration</code></p>
<h3>Directory Structure</h3>
<p>This section is now going to cover setting up the folder structure in our project. This is one of those topics that many people will have <em>extremely strong opinions about</em>, and for good reason! Directory structure can really make or break a project in the long term when it gets out of control, especially when fellow team members have to spend unnecessary time trying to guess where to put things (or find things).</p>
<p>I personally like to take a fairly simplistic approach, keep things separated basically in a class model/view style. We will be using three primary folders:</p>
<pre><code class="language-plaintext">/components
/lib
/pages
</code></pre>
<ul>
<li><code>component</code> - The individual UI components that make up the app will live in here</li>
<li><code>lib</code> - Business/app/domain logic will live in here.</li>
<li><code>pages</code> - Will be the actual routes/pages as per the required Next.js structure.</li>
</ul>
<p>We will have other folders in addition to this to support the project, but the core of almost everything that makes up the unique app that we are building will be housed in these three directories.</p>
<p>Within <code>components</code> we will have subdirectories that kind of group similar types of components together. You can use any method you prefer to do this. I have used the MUI library quite a bit in my time, so I tend to follow the same organization they use for components in <a href="https://mui.com/getting-started/installation/">their documentation</a></p>
<p>For example inputs, surfaces, navigation, utils, layout etc.</p>
<p>You don&#39;t need to create these directories in advance and leave them empty. I would just create them as you go while building your components.</p>
<h2>Next.js meets Nx</h2>
<p>In order to create a new Next.js application, we have two options mainly:</p>
<ul>
<li>use the <a href="https://nextjs.org/docs/getting-started">Next.js CLI</a></li>
<li>use a <a href="https://nx.dev/latest/react/guides/nextjs">Nx workspace</a></li>
</ul>
<p>We’re going to use Nx for this setup because it provides a series of advantages:</p>
<ul>
<li>support for multiple apps (we can easily add more apps to our workspace and share common logic)</li>
<li>structure our code as <a href="https://nx.dev/latest/react/structure/creating-libraries">workspace libraries</a>, thus facilitating a cleaner architecture, code reuse and responsibility segregation</li>
<li>improved build and test speed via Nx <a href="https://nx.dev/latest/react/core-concepts/affected">affected commands</a> and <a href="https://nx.dev/latest/react/core-concepts/computation-caching">computation caching</a></li>
<li>out of the box support for code generation, <a href="https://nx.dev/latest/react/storybook/overview">Storybook</a> and <a href="https://nx.dev/latest/react/cypress/overview">Cypress integration</a></li>
</ul>
<p>These parts will be covered in more detail in the upcoming articles that are part of this series.</p>
<p>To create a new Nx workspace, use the following command.</p>
<pre><code class="language-powershell">npx create-nx-workspace juridev --packageManager=yarn
</code></pre>
<p><code>juridev</code> here is the name of my organization and will be your namespace when you import libraries which we’ll see later.</p>
<p>When asked, use Next.js as the preset</p>
<p><img src="https://juristr.com/blog/assets/imgs/nextjs-nx-series/create-nx-workspace.png" alt=""></p>
<p>During the setup, you’ll be asked to give the generated application a name. I use “site” for now as this is going to be my main Next.js website. Make sure to <strong>choose CSS as the styling framework</strong>. Because we’ll be using Tailwind later, we need pure CSS and PostCSS processing.</p>
<p>Once the installation and setup completes, run <code>yarn start</code> (or <code>npm start</code>) to launch the Next.js dev server and navigate to <a href="http://localhost:4200">http://localhost:4200</a>. You should see the running application.</p>
<h2>Nx Workspace structure</h2>
<p>Let’s quickly explore the Nx workspace structure to learn some of the fundamentals.</p>
<h3>Apps and Libs</h3>
<p>An Nx workspace is structured into <strong>apps</strong> and <strong>libs</strong>. Instead of having all the different features of our app just within folders of our application folder, we rather split them up into “workspace libraries”. Most of our business and domain logic should reside in those libraries. The apps can be seen as our “deployables”. They import the functionality in the libs as the building blocks to create a deployable app.</p>
<p>Although the libraries can be built and published (see <a href="https://nx.dev/latest/react/structure/buildable-and-publishable-libraries/">Publishable and Buildable Libraries</a>), they don’t have to. They are referenced via TypeScript path mappings in the <code>tsconfig.base.json</code> configuration at the root of the Nx workspace. When we build the application, all referenced libraries are built into the app via the used bundler (e.g. Webpack or Rollup etc).</p>
<h3>Config files: workspace.json and nx.json</h3>
<p>Let’s give a fast overview of the main configuration files. All the details can be found on the official docs page: <a href="https://nx.dev/latest/react/core-concepts/configuration">https://nx.dev/latest/react/core-concepts/configuration</a></p>
<p>The <code>workspace.json</code> is the main configuration file of an Nx workspace. It defines</p>
<ul>
<li>the projects in the workspace (e.g. apps and libs)</li>
<li>the <a href="https://nx.dev/latest/react/executors/using-builders">Nx executor</a> used to run operations on the projects (e.g. serve the app, build it, run Jest tests, Storybook etc..)</li>
</ul>
<p>The <code>nx.json</code> defines mostly additional configuration properties used for the <a href="https://nx.dev/latest/react/structure/dependency-graph">Nx dependency graph</a>. Additionally, you can define the base branch (e.g. <code>master</code> or <code>main</code> or whatever you are using) and the <a href="https://nx.dev/latest/react/core-concepts/configuration#tasks-runner-options">task runner</a> to be used.</p>
<h3>Serving, building and testing</h3>
<p>The Nx workspace.json config defines what you can actually serve, build, test etc. Here’s a quick example of such a configuration for a project called <code>cart</code>.</p>
<pre><code class="language-json">{
  &quot;projects&quot;: {
    &quot;cart&quot;: {
      &quot;root&quot;: &quot;apps/cart&quot;,
      &quot;sourceRoot&quot;: &quot;apps/cart/src&quot;,
      &quot;projectType&quot;: &quot;application&quot;,
      &quot;targets&quot;: {
        &quot;build&quot;: {
          &quot;executor&quot;: &quot;@nrwl/web:build&quot;,
          &quot;options&quot;: {
            &quot;outputPath&quot;: &quot;dist/apps/cart&quot;,
            ...
          },
          ...
        },
        &quot;serve&quot;: {...},
        &quot;test&quot;: {
          &quot;executor&quot;: &quot;@nrwl/jest:jest&quot;,
          &quot;options&quot;: {
            ...
          }
        }
      }
    }
  }
}
</code></pre>
<p>It defines targets for <code>build</code>, <code>serve</code> and <code>test</code>. These can be invoked using the following syntax:</p>
<pre><code class="language-bash">npx nx run &lt;proj-name&gt;:&lt;target&gt; &lt;options&gt;
</code></pre>
<blockquote>
<p>Note, we use <code>npx</code> in front because we don’t have Nx installed globally. Thus npx will fallback and execute the installed binary in our node_modules folder. You can obviously also install Nx globally and get rid of having to prefix commands with <code>npx</code></p>
</blockquote>
<p>So to serve our app we run <code>nx run cart:serve</code>, to build it <code>nx run cart:build</code> and so on. There are also shortcuts, meaning we can alternatively invoke these commands like <code>nx serve cart</code> or <code>nx build cart</code>.</p>
<blockquote>
<p>In Nx “targets” are invocable commands. There are predefined commands such as build, serve, test that get set up when you generate a new application. You can also define your custom ones, either by building your own <a href="https://nx.dev/latest/react/executors/using-builders">Nx Executor</a> or use the <a href="https://nx.dev/latest/react/workspace/run-commands-executor">Nx Run-Commands</a>.</p>
</blockquote>
<h2>Working on our Next App</h2>
<h3>Understanding Page Structures: Generating the About Page</h3>
<p>When looking at the setup you’ll see a “pages” folder. Every file returning a React component in there, instructs Next.js to generate a new page. As you can see there is an <code>index.tsx</code> page, which you see when navigating to the root of the Next website <a href="http://localhost:4200"><code>http://localhost:4200</code></a>. To better understand this, let’s create an About page that responds at <a href="http://localhost:4200/about"><code>http://localhost:4200/about</code></a>.</p>
<p>Nx has some nice generators for that already. Hence, typing..</p>
<pre><code class="language-bash">npx nx generate @nrwl/next:page --name=about --style=css
</code></pre>
<p>..generates a new <code>about.tsx</code> (with its according styling file).</p>
<pre><code class="language-tsx">import &#39;./about.module.scss&#39;;

/* eslint-disable-next-line */
export interface AboutProps {}

export function About(props: AboutProps) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Welcome to about!&lt;/h1&gt;
    &lt;/div&gt;
  );
}

export default About;
</code></pre>
<blockquote>
<p>Btw, if you’re not the terminal kind of person, you can also use the <a href="https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console">Nx Console VSCode</a> plugin.</p>
</blockquote>
<p>If we now serve our app with <code>npx nx serve site</code> and navigate to <code>/about</code>, we should see something like the following:</p>
<p><img src="https://juristr.com/blog/assets/imgs/nextjs-nx-series/next-webapp-running.png" alt=""></p>
<h3>Understanding <code>getStaticProps</code></h3>
<p><a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation">Next.js Docs</a></p>
<p><code>getStaticProps</code> allow us to return props to our React component that’s going to be pre-rendered by Next.js. It gets the <code>context</code> object as a parameter and should return an object of the form.</p>
<pre><code class="language-tsx">return {
  props: { /* your own properties */ }
}
</code></pre>
<p>We can write our <code>getStaticProps</code> as follows:</p>
<pre><code class="language-tsx">// apps/site/pages/about.tsx
import { GetStaticProps } from &#39;next&#39;;
...

export interface AboutProps {
  name: string;
}
...

export const getStaticProps: GetStaticProps&lt;AboutProps&gt; = async (context) =&gt; {
  return {
    props: {
      name: &#39;Juri&#39;
    },
  };
};
</code></pre>
<p>Note how we use TypeScript to type the return value of our function to match our <code>AboutProps</code> from the <code>about.tsx</code> component. You can find more info about how to use the <code>getStaticProps</code> and others <a href="https://nextjs.org/docs/basic-features/data-fetching#typescript-use-getstaticprops">with TypeScript on the official Next.js docs</a>.</p>
<p>We can now use the props in our React component:</p>
<pre><code class="language-tsx">export function About(props: AboutProps) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Welcome, {props.name}!&lt;/h1&gt;
    &lt;/div&gt;
  );
}

export const getStaticProps: GetStaticProps&lt;AboutProps&gt; = async (context) =&gt; {
  ...
}
</code></pre>
<p><img src="https://juristr.com/blog/assets/imgs/nextjs-nx-series/getstaticprops-page.png" alt=""></p>
<h3>Understanding <code>getStaticPaths</code></h3>
<p><a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation">Next.js Docs</a></p>
<p>If we want to create a blog, we’ll want to load pages dynamically. So we cannot really give them a static name as we did with our About page (<code>about.tsx</code>).</p>
<pre><code class="language-bash">nx generate @nrwl/next:page --name=[slug] --style=none --directory=articles
</code></pre>
<p>This generates a new <code>articles</code> folder with a new <code>[slug].tsx</code> file. The <code>[slug]</code> part is where Next.js understands it is dynamic and needs to be filled accordingly. Let’s also clean up the generated part a bit, changing the React component name to <code>Article</code> as well as the corresponding TS interface.</p>
<p>So first of all let’s focus on the <code>getStaticPaths</code> function which we define as follows:</p>
<pre><code class="language-tsx">// apps/site/pages/articles/[slug].tsx
import { ParsedUrlQuery } from &#39;querystring&#39;;

interface ArticleProps extends ParsedUrlQuery {
  slug: string;
}

export const getStaticPaths: GetStaticPaths&lt;ArticleProps&gt; = async () =&gt; {
  ...
}
</code></pre>
<p><a href="https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation">According to the docs</a> the function needs to return an object, having a <code>paths</code> as well as <code>fallback</code> property:</p>
<pre><code class="language-tsx">return {
  paths: [
    { params: { ... } }
  ],
  fallback: true or false
};
</code></pre>
<p>The <code>paths</code> section contains the number of pages that should be pre-rendered. So we could have something like</p>
<pre><code class="language-tsx">return {
  paths: [
    {
      slug: &#39;page1&#39;
    },
    {
      slug: &#39;page2&#39;
    }
  ],
  ...
}
</code></pre>
<p>From a mental model, this would instruct Next.js to “generate” (obviously it doesn’t) at the place of our <code>[slug].tsx</code> a <code>page1.tsx</code> and <code>page2.tsx</code> which are then converted to pages accessible at <code>/articles/page1</code> and <code>/articles/page2</code>.</p>
<p>This would be the place where you would go and read your file system or query the API for all the pages you wanna render. But more about that later. To simplify things, let us just generate a set of “pages”:</p>
<pre><code class="language-tsx">export const getStaticPaths: GetStaticPaths&lt;ArticleProps&gt; = async () =&gt; {
  return {
    paths: [1, 2, 3].map((idx) =&gt; {
      return {
        params: {
          slug: `page${idx}`,
        },
      };
    }),
    fallback: false,
  };
};
</code></pre>
<p>The returned <code>params</code> object can be accessed from within the <code>getStaticProps</code> which we’ve seen before and potentially remapped to something else. Here’s the place where you could further elaborate the content, say we get the content in markdown, we could process and convert it to HTML here.</p>
<p>In this simple scenario we just pass it along:</p>
<pre><code class="language-tsx">export const getStaticProps: GetStaticProps&lt;ArticleProps&gt; = async ({
  params,
}: {
  params: ArticleProps;
}) =&gt; {
  return {
    props: {
      slug: params.slug,
    },
  };
};
</code></pre>
<p>And finally we can access it from within the page React component:</p>
<pre><code class="language-tsx">export function Article(props: ArticleProps) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Visiting {props.slug}&lt;/h1&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p><img src="https://juristr.com/blog/assets/imgs/nextjs-nx-series/getstaticpaths-page.png" alt=""></p>
<h3>What about <code>fallback</code>?</h3>
<p>There’s another property returned by the <code>getStaticPaths</code> function: <code>fallback</code>. The Next.js docs are pretty clear about it, so make sure to <a href="https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required">check them out</a>.</p>
<p>In short, <code>fallback: false</code> renders only the set of pages returned by the <code>paths</code> property. If a given page doesn’t find a match, a 404 page (that comes with Next.js) is being rendered.</p>
<blockquote>
<p>It’s also useful when the new pages are not added often. If you add more items to the data source and need to render the new pages, you’d need to run the build again.</p>
</blockquote>
<p>If <code>fallback: true</code> the difference is that pages that have not been rendered during build time (e.g. that are not in the <code>paths</code> property) will not result in a 404 page. Rather, Next.js returns a <a href="https://nextjs.org/docs/basic-features/data-fetching#fallback-pages">Fallback page</a> (e.g. a page where you could display a loading indicator) and then statically generates the page and the corresponding HTML and sends it back to the client, where the fallback page is swapped with the real one. Furthermore, it will be added to the sets of pre-rendered pages, s.t. any subsequent call will be immediate.</p>
<h2>Building and Exporting our Next.js application with Nx</h2>
<p>Next.js defines two main options when it comes to generating your deployable:</p>
<ul>
<li><strong>build -</strong> allows to generate an optimized bundle that can be served by the <code>next</code> CLI, e.g. when deploying to some <a href="https://vercel.com/">Vercel</a> infrastructure. It requires a Node environment that can run the application. We will talk more about deployment of Next.js apps in an upcoming article</li>
<li><strong>export -</strong> allows to generate a static site out of your Next.js application. This is ideal if you don’t have a Node environment and you just want to serve the app from some static CDN.</li>
</ul>
<p>Hence, also the Nx configuration (in <code>workspace.json</code>) has matching Nx targets (see the section about “Nx Workspace structure” to learn more).</p>
<p>We can invoke the “build” with</p>
<pre><code class="language-plaintext">nx run site:build --configuration=production
</code></pre>
<p>or alternatively with <code>nx build site</code>.</p>
<p>Similarly, the <code>export</code> can be invoked with</p>
<pre><code class="language-plaintext">nx run site:export --configuration=production
</code></pre>
<p>or <code>nx export site</code>. Using the <code>export</code> command will automatically build the Next.js app first.</p>
<p>By passing <code>--configuration=production</code> (or <code>--prod</code>) the production configuration is being used which is defined in the <code>workspace.json</code> and which can set additional production environment only properties:</p>
<pre><code class="language-json">&quot;build&quot;: {
    &quot;executor&quot;: &quot;@nrwl/next:build&quot;,
    &quot;outputs&quot;: [&quot;{options.outputPath}&quot;],
    &quot;options&quot;: {
        &quot;root&quot;: &quot;apps/site&quot;,
        &quot;outputPath&quot;: &quot;dist/apps/site&quot;
    },
    &quot;configurations&quot;: {
        &quot;production&quot;: {}
    }
},
</code></pre>
<h3>For reference visit : <a href="https://github.com/anzal1/Nx-monorepo-template">https://github.com/anzal1/Nx-monorepo-template</a></h3>
]]></content:encoded>
    </item>
    <item>
      <title>Embracing Failure: A Journey of Growth and Resilience</title>
      <link>https://anzalabidi.dev/writing/embracing-failure-a-journey-of-growth-and-resilience/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/embracing-failure-a-journey-of-growth-and-resilience/</guid>
      <pubDate>Sun, 28 May 2023 09:22:41 GMT</pubDate>
      <description>The reason behind the blog People tend to share their achievements all the time but what matters is how they dealt with their failures, cause often a failure can break someone&#39;s confidence to such an extent that he/she may quit the most wanted dream ...</description>
      <category>software development</category>
      <category>Web Development</category>
      <category>newbie</category>
      <category>#codenewbies</category>
      <category>Stress,</category>
      <content:encoded><![CDATA[<h2>The reason behind the blog</h2>
<p>People tend to share their achievements all the time but what matters is how they dealt with their failures, cause often a failure can break someone&#39;s confidence to such an extent that he/she may quit the most wanted dream in their life.</p>
<h3>Failure, the end of everything?</h3>
<p>Failure is an inevitable part of life. Whether we like it or not, we all encounter setbacks and disappointments along our journey. However, it&#39;s important to remember that failure does not define us but rather shapes us into who we become. In this blog, we will explore the concept of failure, delve into the reasons behind our fear of failure, and ultimately discover the valuable lessons that can be learned from our missteps. So, let&#39;s dive into the world of failures and uncover the hidden gems of growth and resilience that lie within.</p>
<h4>1. Understanding Failure:</h4>
<p>Failure is not a reflection of our worth or abilities. It is simply a temporary stumbling block that challenges us to reassess our approach and learn from our mistakes. By shifting our perspective and reframing failure as an opportunity for growth, we can unlock its transformative potential.</p>
<h4>2. The Fear of Failure:</h4>
<p>Fear of failure often holds us back from taking risks or pursuing our dreams. We worry about the judgment of others, the impact on our self-esteem, or the potential loss of time and resources. However, understanding that failure is a stepping stone to success can help us overcome this fear and embrace the unknown with courage and resilience.</p>
<h4>3. Learning from Failure:</h4>
<p>Every failure provides a valuable lesson if we are willing to look for it. By analyzing our mistakes, identifying the factors that led to our setbacks, and making adjustments, we can turn failure into a catalyst for improvement. Sharing some personal anecdotes of failure and subsequent growth can inspire readers to view their own failures as stepping stones rather than roadblocks.</p>
<h4>4. Failure in Various Areas of Life:</h4>
<p>Failure is not limited to a specific domain; it can manifest itself in various aspects of our lives, such as relationships, careers, education, and personal development. Exploring the different contexts in which failure occurs and providing practical insights on how to bounce back can help readers gain a comprehensive understanding of failure and its impact.</p>
<h4>5. Famous Examples of Failure:</h4>
<p>Even the most successful individuals have faced failure at some point in their lives. Highlighting the stories of renowned personalities who experienced significant setbacks but ultimately triumphed can serve as a source of inspiration and motivation for readers.</p>
<h4>6. Building Resilience:</h4>
<p>Resilience is the key to bouncing back from failure and facing challenges head-on. Sharing strategies and practical tips to develop resilience can empower readers to navigate the ups and downs of life with a renewed sense of strength and determination.</p>
<h4>My personal encounter with failures</h4>
<p>Might not be surprised I have encountered numerous failures since my childhood, at first they were just accompanied by a feeling of a bit of sadness, but it was after my 11th standard that started feeling the pain of failing or understanding the somewhat egoistic approach towards a failure, like, how can i lose in something that i think i am good at, below is a list of stuff at what i failed and i think it is very important to derive a lesson from each and every failure that a person suffers.</p>
<ol>
<li>Lost a district-level football match: It was my 11th standard when our team reached the semi-finals of the district cup, we lost 1-0 and were knocked out.</li>
<li>Failed to get into the IITs: This was one of the major setbacks that I faced to date, I performed well in the mains but lack of preparation cost me the JEE Advanced and the result was not good enough for me to get into the IITs with preferable branches.</li>
<li>Lost the college basketball and football match: This was a bit of pain in the heart as a person nobody likes to lose but nevertheless we as a team did lose and it wasn&#39;t a pleasant experience either.</li>
<li>Rejected by FAANG &amp; MAANG: From the first year itself I applied to numerous tech biggies in search of internships but almost all of them ended up in rejections till date it has been 50+ applications and I&#39;ve reached the last round of in many of them but still the same result<ol>
<li>Microsoft Engage: rejected in the second round of the quiz</li>
<li>Flipkart: rejected in the second round</li>
<li>Amazon: Luxemburg office, rejected in the last round</li>
<li>Google: not shortlisted</li>
<li>Netflix: rejected in the second round</li>
<li>Atlassian: not shortlisted</li>
<li>Microsoft: rejected in the second round</li>
<li>Morgan Stanley: rejected in the second round</li>
<li>Goldman Sachs: didn&#39;t hear from them after two rounds</li>
<li>JP Morgan: not shortlisted</li>
<li>Bloomberg: rejected in the third round</li>
</ol>
</li>
</ol>
<p>and the list goes on but what remains constant is an urge not to give up because there is no losing, there only learning at every stage.</p>
<h4>Conclusion:</h4>
<p>Failure is not the end, it is a stepping stone to growth, resilience, and success. By embracing failure, learning from our mistakes, and viewing setbacks as opportunities, we can cultivate a mindset that fuels personal and professional growth. So, let us not be defined by our failures but instead be empowered by them, for it is through failure that we truly find our strength and discover our greatest achievements. I failed a lot but every time I fail I feel I am one step closer to something big, something worthy of failing so many times. I hope this little blog is something for the readers to feel that they aren&#39;t alone in failing cause though we fall, we fail, we break but then we rise, we heal and we overcome.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Freelancing, a deception, or a magic wand.</title>
      <link>https://anzalabidi.dev/writing/freelancing-a-deception-or-a-magic-wand/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/freelancing-a-deception-or-a-magic-wand/</guid>
      <pubDate>Tue, 18 Apr 2023 16:41:42 GMT</pubDate>
      <description>Freelancing has become a popular and flexible way of working for many people across the world. As a freelancer, you are essentially self-employed, and you have the freedom to work on projects for multiple clients, without being tied to a single emplo...</description>
      <category>Freelancing</category>
      <category>coding</category>
      <category>Web Development</category>
      <category>news</category>
      <category>Developer</category>
      <content:encoded><![CDATA[<p>Freelancing has become a popular and flexible way of working for many people across the world. As a freelancer, you are essentially self-employed, and you have the freedom to work on projects for multiple clients, without being tied to a single employer. In this blog, we will explore freelancing in more detail, including the benefits and challenges of this type of work, how to get started as a freelancer, and tips for succeeding in this competitive field.</p>
<p><img src="https://img.freepik.com/free-vector/freelancer-flexible-remote-work-locations-isometric-flowchart-with-shared-office-writing-home-outdoor-with-laptop-vector-illustration_1284-30324.jpg?w=2000" alt=""></p>
<h3>What is Freelancing?</h3>
<p>Freelancing is a form of self-employment where you work on projects for multiple clients on a short-term or long-term basis, instead of working for a single employer. As a freelancer, you may work from home or in a co-working space, and you are responsible for managing your own time, finding clients, negotiating rates, and delivering work on time.</p>
<h4>Benefits of Freelancing</h4>
<ol>
<li>Flexibility: One of the biggest benefits of freelancing is the flexibility it provides. You have the ability to choose the projects you work on, the clients you work with, and the hours you work. This can be especially beneficial for those who have other commitments such as caring for children or pursuing further education.</li>
<li>Control: As a freelancer, you have full control over your workload and can set your own rates for your services. This can lead to higher earnings compared to working for an employer.</li>
<li>Variety: Freelancing allows you to work on a wide range of projects with different clients, which can provide a greater variety of work and challenges. This can be an excellent way to develop new skills and gain experience in different industries.</li>
</ol>
<h4>Challenges of Freelancing</h4>
<ol>
<li>Inconsistent Income: Freelancing can be unpredictable, and your income may fluctuate depending on the availability of projects and clients. It is important to manage your finances carefully and plan for periods when work may be slower.</li>
<li>No Benefits: Unlike traditional employment, freelancers do not receive benefits such as paid time off, health insurance, or retirement benefits. It is important to factor in these costs when setting your rates.</li>
<li>Isolation: Freelancing can be a lonely profession, as you may not have colleagues to interact with on a daily basis. It is important to make an effort to connect with other freelancers or professionals in your field to avoid feeling isolated.</li>
</ol>
<h4>How to Get Started as a Freelancer</h4>
<ol>
<li>Define Your Skills: The first step in becoming a successful freelancer is to define your skills and identify the services you can offer. Consider your experience, education, and strengths when determining what services you can provide.</li>
<li>Build a Portfolio: A portfolio is a collection of your best work that showcases your skills and expertise to potential clients. It is important to create a professional-looking portfolio that highlights your strengths and experience.</li>
<li>Find Clients: Finding clients can be one of the most challenging aspects of freelancing. Consider reaching out to your network, advertising your services online, or using freelancer platforms such as Upwork or Fiverr to find clients.</li>
<li>Set Your Rates: Setting your rates can be tricky as you need to find a balance between earning a fair wage and being competitive in the market. Consider the time it takes to complete a project, your level of experience, and the rates of other freelancers in your field when setting your rates.</li>
</ol>
<h4>Tips for Succeeding as a Freelancer</h4>
<ol>
<li>Manage Your Time: As a freelancer, time management is crucial. Create a schedule and stick to it, set deadlines for yourself, and prioritize your work to ensure you meet your client&#39;s needs.</li>
<li>Communicate Effectively: Good communication is essential for building strong relationships with clients. Be responsive to emails and messages, set clear expectations, and be open to feedback.</li>
<li>Focus on Quality: Delivering high-quality work is essential for building a strong reputation as a freelancer. Take the time to ensure your work is accurate, meets the client&#39;s expectations, and is delivered on time.</li>
<li>Keep Learning: The world of freelancing is constantly evolving, and it is important to keep up with the latest trends and technologies in your field. Attend workshops, conferences, and training sessions to improve your skills and stay up-to-date.</li>
<li>Build Relationships: Building strong relationships with clients is essential for long-term success as a freelancer. Be reliable, and communicative, and go above and beyond to exceed their expectations. Happy clients are more likely to recommend you to others and provide you with repeat business.</li>
<li>Manage Your Finances: Managing your finances is important as a freelancer. Keep track of your income and expenses, set aside money for taxes and other expenses, and consider using accounting software to simplify the process.</li>
</ol>
<h4>My journey as a Freelancer</h4>
<p>Freelancing came to me as an attractive option to make money and being honest it did prove it&#39;s metal. I&#39;ll say <code>we</code> rather than <code>I</code> cause we flatmates mutually decided that we would vigorously search for clients and try to grab as many projects as we can in a month, we approximately made more than 50k, paid our rent, filled up the monthly asset stock and donated a generous amount. Wait how did we do that? The answer is simple and the amusing fact is we did all this in a span of a week of work, cause it was not the coding that took time, it was the payment that extended the waiting time to a month. Taking up projects at this pace may seem very ambitious but it is also mentally and physically tiring yet I cannot deny the fact that the adrenaline rush to meet the deadlines was good.</p>
<h4>Conclusion</h4>
<p>Freelancing can be a rewarding and flexible way of working for those who have the skills, determination, and discipline to succeed. While there are challenges to overcome, the benefits of freelancing, including flexibility, control, and variety, make it a popular choice for many professionals. By following these tips, freelancers can build a successful and sustainable business, and enjoy the many rewards that come with working for themselves. Additionally, it is worth noting that freelancing offers opportunities to work with clients and companies from around the world, regardless of geographic location. This can provide exposure to different cultures, industries, and perspectives, leading to greater personal and professional growth.</p>
<p>However, it is important to remember that freelancing is not for everyone. It requires self-motivation, discipline, and a willingness to take risks. Freelancers must be comfortable with the uncertainty and variability that comes with this type of work, and be willing to continuously adapt to changing market conditions.</p>
<p>Overall, freelancing can be a rewarding and fulfilling way of working for those who are willing to put in the effort to build a successful business. By defining your skills, building a strong portfolio, finding clients, setting your rates, and following these tips for success, you can enjoy the many benefits that come with being a freelancer.</p>
<p>There are many freelancing websites available that offer a platform for freelancers to connect with clients and find work opportunities. Here are some of the most popular freelancing websites:</p>
<ol>
<li>Upwork</li>
<li>Fiverr</li>
<li>Freelancer</li>
<li>Guru</li>
<li>PeoplePerHour</li>
<li>Toptal</li>
<li>SimplyHired</li>
<li>99designs</li>
<li>Behance</li>
<li>Dribbble</li>
</ol>
<p>Each of these platforms has its own unique features, pricing structures, and user communities. It is important to research and compares these websites to determine which one best meets your needs as a freelancer.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Let&#39;s Get Rusty</title>
      <link>https://anzalabidi.dev/writing/lets-get-rusty/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/lets-get-rusty/</guid>
      <pubDate>Wed, 08 Mar 2023 15:48:36 GMT</pubDate>
      <description>What the heck is rust ? Rust is a programming language that was initially developed by Mozilla and released to the public in 2010. It was designed to be a fast, efficient, and safe alternative to other system programming languages like C++ and C. Rus...</description>
      <category>Rust</category>
      <category>Programming Blogs</category>
      <category>coding</category>
      <category>technology</category>
      <category>Web Development</category>
      <content:encoded><![CDATA[<h3>What the heck is rust ?</h3>
<p>Rust is a programming language that was initially developed by Mozilla and released to the public in 2010. It was designed to be a fast, efficient, and safe alternative to other system programming languages like C++ and C. Rust&#39;s popularity has been increasing rapidly in recent years, and for good reason. In this blog, we&#39;ll dive deep into Rust and explore its advantages over other languages.</p>
<ol>
<li>Memory safety and thread safety One of the most significant advantages of Rust is its strong emphasis on memory safety and thread safety. Rust&#39;s ownership and borrowing system ensures that memory is managed safely and efficiently, which can help prevent common bugs like null pointers, buffer overflows, and use-after-free errors. The language&#39;s type system also helps ensure that code is thread-safe, meaning that it can be run concurrently without data races.</li>
<li>High performance Rust is designed to be a high-performance language, which makes it an excellent choice for system-level programming. Its syntax and semantics are designed to optimize code, and it provides direct access to hardware resources, making it faster than many other languages. Rust is also designed to work well with multi-core processors, making it ideal for high-performance computing and parallel processing.</li>
<li>Easy to learn Despite its advanced features, Rust is surprisingly easy to learn. Its syntax is clean and easy to understand, and its compiler provides helpful error messages that can make it easier to fix issues in code. Rust also has an active community of developers who are eager to help new users, making it a welcoming language for beginners.</li>
<li>Cross-platform support Rust is a cross-platform language, meaning that it can be used to develop software for a wide range of platforms, including Windows, macOS, Linux, and even embedded systems. This makes it an ideal choice for developers who need to build applications that can run on multiple platforms.</li>
<li>Large and growing community Rust has a large and growing community of developers who are working on a wide range of projects. This community provides a wealth of resources, including libraries, frameworks, and tools, making it easier for developers to get started with Rust and build complex applications.</li>
</ol>
<p>In conclusion, Rust is a powerful programming language that offers a range of benefits over other languages. Its emphasis on memory and thread safety, high performance, ease of use, cross-platform support, and growing community make it an excellent choice for system-level programming, high-performance computing, and more. If you&#39;re looking for a modern, efficient, and safe programming language, Rust is definitely worth considering.</p>
<p><img src="https://doc.rust-lang.org/book/img/ferris/does_not_compile.svg" alt=""></p>
<h3>Too much theory show me some code :</h3>
<ol>
<li>Memory safety and thread safety Rust&#39;s ownership and borrowing system allows for safe memory management, which can prevent common bugs like null pointers, buffer overflows, and use-after-free errors. Here&#39;s an example of how Rust&#39;s ownership system works:</li>
</ol>
<pre><code class="language-rust">fn main() {
    let mut s = String::from(&quot;hello&quot;);

    let len = calculate_length(&amp;s);

    println!(&quot;The length of &#39;{}&#39; is {}.&quot;, s, len);

    change(&amp;mut s);

    let len = calculate_length(&amp;s);

    println!(&quot;The length of &#39;{}&#39; is {}.&quot;, s, len);
}

fn calculate_length(s: &amp;String) -&gt; usize {
    s.len()
}

fn change(some_string: &amp;mut String) {
    some_string.push_str(&quot;, world&quot;);
}
</code></pre>
<p>In this example, we create a string <code>s</code> and pass a reference to it to the <code>calculate_length</code> function, which returns the length of the string. We then pass a mutable reference to the <code>change</code> function, which appends <code>&quot;, world&quot;</code> to the string. Finally, we call <code>calculate_length</code> again to get the new length of the string. Because Rust&#39;s ownership system ensures that there is only one mutable reference to the string at a time, this code is safe and will not cause any memory or thread-related issues.</p>
<ol>
<li>High performance Rust is designed to be a high-performance language, which makes it an excellent choice for system-level programming. Here&#39;s an example of how Rust&#39;s performance compares to that of Python:</li>
</ol>
<pre><code class="language-rust">rust:
fn main() {
    let mut sum = 0;

    for i in 0..1000000000 {
        sum += i;
    }

    println!(&quot;{}&quot;, sum);
}
</code></pre>
<pre><code class="language-python">python
sum = 0
for i in range(1000000000):
    sum += i
print(sum)
</code></pre>
<p>In this example, we calculate the sum of the first billion integers in both Rust and Python. When we run the Rust code, it completes in just a few seconds, whereas the Python code takes several minutes to complete. This illustrates Rust&#39;s performance advantage over interpreted languages like Python.</p>
<ol>
<li>Easy to learn Despite its advanced features, Rust is surprisingly easy to learn. Here&#39;s an example of how Rust&#39;s syntax is clean and easy to understand:</li>
</ol>
<pre><code class="language-rust">fn main() {
    let x = 5;
    let y = {
        let x = 3;
        x + 1
    };
    println!(&quot;The value of x is {}.&quot;, x);
    println!(&quot;The value of y is {}.&quot;, y);
}
</code></pre>
<p>In this example, we create a variable <code>x</code> and set it to <code>5</code>. We then create another variable <code>y</code> and set it to the result of a block of code that adds 1 to <code>x</code>. Because Rust uses a block expression for the calculation of <code>y</code>, we don&#39;t need to use the <code>return</code> keyword, which makes the code more concise and easier to read.</p>
<ol>
<li>Cross-platform support Rust is a cross-platform language, meaning that it can be used to develop software for a wide range of platforms, including Windows, macOS, Linux, and even embedded systems. Here&#39;s an example of how Rust can be used to develop an application that runs on multiple platforms:</li>
</ol>
<pre><code class="language-rust">fn main() {
    println!(&quot;Hello, world!&quot;);
}
</code></pre>
<p>This simple &quot;Hello, world!&quot; program can be compiled and run on any platform that supports Rust, without any modifications to the code. This illustrates Rust&#39;s cross-platform compatibility, which can save developers time and effort when developing software for multiple platforms.</p>
<ol>
<li>Large and growing community:</li>
</ol>
<pre><code class="language-rust">use std::thread;

fn main() {
    let mut handles = vec![];

    for i in 0..10 {
        handles.push(thread::spawn(move || {
            println!(&quot;Thread {} started.&quot;, i);
        }));
    }

    for handle in handles {
        handle.join().unwrap();
    }
}
</code></pre>
<p>In this example, we create 10 threads that print a message to the console. We use Rust&#39;s standard library to create and manage the threads, which makes the code more concise and easier to understand. If we have any questions or issues with this code, we can turn to Rust&#39;s community for help, either through forums, chat rooms, or online resources.</p>
<p>In comparison to other languages like C++, Rust provides advantages in terms of safety, performance, ease of learning, cross-platform support, and community. These features make Rust an excellent choice for system-level programming, game development, web development, and more.</p>
<h3>Rust as a server side language , are you serious ?</h3>
<p>There are several reasons why Rust is a good choice for server-side programming:</p>
<ol>
<li>Memory safety: Rust&#39;s ownership and borrowing system prevents common memory errors like null pointers, buffer overflows, and use-after-free errors, which can lead to security vulnerabilities and crashes. This makes Rust a safe choice for server-side programming, where security and reliability are critical.</li>
<li>High performance: Rust is designed to be a high-performance language, which makes it a good choice for server-side programming where performance is important. Rust&#39;s performance is comparable to that of C and C++, but with safer memory management.</li>
<li>Asynchronous programming: Rust has excellent support for asynchronous programming, which is essential for server-side programming. Rust&#39;s async/await syntax and futures library make it easy to write efficient and scalable asynchronous code.</li>
<li>Web frameworks: Rust has several excellent web frameworks, including Actix, Rocket, and Warp. These frameworks make it easy to write efficient and secure web applications in Rust, with features like middleware, routing, and authentication.</li>
<li>Cross-platform support: Rust is a cross-platform language, meaning that it can be used to develop server-side applications for a wide range of platforms, including Windows, Linux, and macOS.</li>
<li>Community: Rust has a large and growing community of developers.</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>NEO4j , A Modern day ninja.</title>
      <link>https://anzalabidi.dev/writing/neo4j-a-modern-day-ninja/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/neo4j-a-modern-day-ninja/</guid>
      <pubDate>Sat, 28 Jan 2023 18:33:25 GMT</pubDate>
      <description>INTRODUCTION Neo4j is a highly popular, open-source graph database management system. It is built on the principles of graph theory and allows users to model and query complex relationships between data in a highly intuitive and efficient manner. One...</description>
      <category>Databases</category>
      <category>Beginner Developers</category>
      <category>technology</category>
      <category>Web Development</category>
      <category>webdev</category>
      <content:encoded><![CDATA[<h2>INTRODUCTION</h2>
<p>Neo4j is a highly popular, open-source graph database management system. It is built on the principles of graph theory and allows users to model and query complex relationships between data in a highly intuitive and efficient manner.</p>
<p>One of the key advantages of Neo4j is its ability to handle large amounts of data and relationships with ease. The graph data model allows for flexible and efficient querying of data, making it a great choice for applications that involve data with many connections and dependencies. Additionally, Neo4j&#39;s Cypher query language is designed to be highly readable and easy to use, making it accessible to developers of all skill levels.</p>
<p>Another major advantage of Neo4j is its scalability. The database can handle millions of nodes and relationships, and can be easily scaled up or down to meet the needs of any application. Additionally, Neo4j&#39;s built-in cluster support allows for easy horizontal scaling, making it a great option for organizations that need to handle large amounts of data.</p>
<p>Neo4j also has a rich ecosystem of tools and libraries to support developers. These include libraries for popular programming languages like Java, Python, and JavaScript, as well as visualization tools and other plugins to help developers work with the data stored in Neo4j.</p>
<p>One use case of Neo4j is its use in recommendation systems. It can be used to store and query data on users, items, and their interactions, and then use that data to make personalized recommendations to users. Additionally, Neo4j can be used in fraud detection and network analysis, as it can easily store and query data on connections between entities.</p>
<p>Overall, Neo4j is a powerful and versatile graph database management system that is well-suited to a wide range of use cases. Its ability to handle large amounts of data and relationships, along with its intuitive and easy-to-use query language, make it a great choice for developers looking to build applications that involve complex data. Additionally, its scalability and rich ecosystem of tools and libraries make it a great option for organizations that need to handle large amounts of data.</p>
<h2>ARCHITECTURE</h2>
<p>Neo4j&#39;s architecture is based on a master-slave model, where one server acts as the master and the other servers act as slaves. The master server is responsible for handling all write operations, while the slaves handle all read operations. This allows for highly efficient and scalable operation, as the read and write operations can be handled by different servers, allowing for better utilization of resources.</p>
<p>The data in Neo4j is stored in a format called Property Graph. A property graph is a mathematical graph, where the nodes represent entities and the edges represent the relationships between them. Each node and edge has a set of properties, which are key-value pairs that provide additional information about the nodes and edges.</p>
<p>The nodes and edges in Neo4j are stored in a highly optimized data structure called a native store. This allows for fast and efficient storage and retrieval of data, and also enables Cypher, Neo4j&#39;s query language, to perform complex queries on the data with high performance. Additionally, Neo4j also support indexing and querying of the data to optimize the performance of the querying.</p>
<p>In summary, Neo4j&#39;s architecture is based on a master-slave model, which allows for highly efficient and scalable operation. The data is stored in the property graph format, which consists of nodes, edges and properties, and it is optimized for fast and efficient storage and retrieval of data. Additionally, the native store and querying capabilities allow for complex queries on the data with high performance.</p>
<p><img src="https://dist.neo4j.com/wp-content/uploads/20220208132007/1_o9P8rcl2BPMwnjrg8lQSJQ.jpeg" alt="enter image description here"></p>
<h2>SOME USECASES AND EXAMPLES</h2>
<p>Cypher is the query language used in Neo4j to query and manipulate the data stored in the graph. Here are some examples of Cypher syntax and code:</p>
<ol>
<li><p>Creating nodes and relationships:</p>
<pre><code>CREATE (:Person { name: &quot;John&quot;, age: 30 })
CREATE (:Person { name: &quot;Jane&quot;, age: 25 })
CREATE (:Person { name: &quot;Bob&quot;, age: 35 })
CREATE (j:Person { name: &quot;John&quot;, age: 30 })-[:KNOWS]-&gt;(b:Person { name: &quot;Bob&quot;, age: 35 })
</code></pre>
<blockquote>
<p>In this example, we&#39;re creating three nodes with the label &quot;Person&quot; and properties &quot;name&quot; and &quot;age&quot;. Then we&#39;re creating a relationship of type &quot;KNOWS&quot; between the nodes &quot;John&quot; and &quot;Bob&quot;.</p>
</blockquote>
</li>
<li><p>Retrieving data:</p>
<pre><code> MATCH (p:Person) RETURN p
</code></pre>
<blockquote>
<p>This query retrieves all the nodes with the label &quot;Person&quot; and returns the nodes.</p>
</blockquote>
</li>
<li><p>Updating data:</p>
<pre><code> MATCH (p:Person { name: &quot;John&quot; }) SET p.age = 32
</code></pre>
<blockquote>
<p>This query matches the node with the label &quot;Person&quot; and the property &quot;name&quot; equal to &quot;John&quot; and sets the &quot;age&quot; property to 32</p>
</blockquote>
</li>
<li><p>Deleting data:</p>
<pre><code>MATCH (p:Person { name: &quot;John&quot; }) DELETE p
</code></pre>
<blockquote>
<p>This query matches the node with the label &quot;Person&quot; and the property &quot;name&quot; equal to &quot;John&quot; and deletes the node.</p>
</blockquote>
</li>
<li><p>Filtering data:</p>
<pre><code>MATCH (p:Person) WHERE p.age &gt; 30 RETURN p
</code></pre>
<blockquote>
<p>This query matches all the nodes with the label &quot;Person&quot; and filters the results to only return nodes where the &quot;age&quot; property is greater than 30.</p>
</blockquote>
</li>
</ol>
<p>These are just a few examples of Cypher syntax and code. Cypher is a very powerful and flexible language, and it can be used to express a wide range of queries and manipulations on the data stored in Neo4j. Additionally, Cypher supports indexing and querying, which can be used to optimize the performance of queries.</p>
<p><img src="https://dist.neo4j.com/wp-content/uploads/20160415155725/graph-database-rules-engine.png" alt="enter image description here"></p>
<h2>THE DEEPER THE BETTER</h2>
<p>One of the key components of Neo4j&#39;s architecture is the storage layer. The storage layer is responsible for persisting the graph data and managing the relationships between nodes and edges. Neo4j uses a native storage format, called the native store, which is optimized for fast and efficient storage and retrieval of graph data. The native store uses a memory-mapped file system to store the data on disk, which allows for fast access to the data, even when working with very large datasets.</p>
<p>Another important component of Neo4j&#39;s architecture is the query layer. The query layer is responsible for processing Cypher queries, Neo4j&#39;s query language, and providing the results to the application. Cypher is designed to be highly readable and easy to use, and it allows developers to express complex queries in a natural and intuitive way. Cypher also supports indexing and querying, to optimize the performance of the querying.</p>
<p>The Neo4j&#39;s architecture also has a caching layer, which is responsible for caching frequently accessed data in memory to improve query performance. The caching layer uses a Least Recently Used (LRU) algorithm to determine which data to cache and when to evict data from the cache. This caching layer can significantly improve query performance, particularly when working with large datasets.</p>
<p>In addition to the above, Neo4j also has a robust security model that allows for granular control over access to data. It has built-in support for authentication and authorization, and it allows for the creation of custom roles and permissions. This makes it suitable for use in a wide range of applications, including those with sensitive data.</p>
<p>Another important aspect of Neo4j is its scalability. Neo4j&#39;s architecture is designed to scale horizontally, which means that it can easily be scaled out by adding more servers to the cluster. This allows Neo4j to handle very large datasets and high query loads, making it suitable for use in high-traffic applications and big data scenarios.</p>
<p>In summary, Neo4j&#39;s architecture is designed to provide fast and efficient storage and retrieval of graph data, while also providing a robust and easy-to-use query language. The native storage format, caching layer, and query layer work together to provide high performance, even when working with very large datasets. Additionally, the architecture is designed to scale horizontally, making it suitable for use in high-traffic applications and big data scenarios, and the security model provides granular control over access to data.</p>
<p><img src="https://dist.neo4j.com/wp-content/uploads/20160317110028/fitness-program-nutrition-recommendations.png" alt="enter image description here"></p>
]]></content:encoded>
    </item>
    <item>
      <title>Why you need to learn PHP</title>
      <link>https://anzalabidi.dev/writing/why-you-need-to-learn-php/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/why-you-need-to-learn-php/</guid>
      <pubDate>Thu, 26 Jan 2023 18:25:36 GMT</pubDate>
      <description>PHP is a popular programming language which is utilized to build dynamic web applications with MySQL database connections. For a programming language to be successful, it must be comfortable and widely accepted by a large number of web developers. PH...</description>
      <category>PHP</category>
      <category>Beginner Developers</category>
      <category>Web Development</category>
      <category>Developer</category>
      <category>languages</category>
      <content:encoded><![CDATA[<p>PHP is a popular programming language which is utilized to build dynamic web applications with MySQL database connections. For a programming language to be successful, it must be comfortable and widely accepted by a large number of web developers. PHP is outfitted with many open sources integrated development environments. Moreover, there are a lot of benefits of learning PHP language.</p>
<blockquote>
<p>“Ruby is rubbish! PHP is phpantastic!” – Nikita Popov</p>
</blockquote>
<h3>Advantages of learning PHP</h3>
<p>PHP offers a plenty of benefits that will surely deliver your limits of developing something outstanding. Not only is it open-source but also feature-rich and has all the functionality that a proprietary or paid scripting language would offer. PHP is easy to install and set-up. It is the prominent reason of why PHP is the best language to learn. In the software industry, there are many IT companies were looking for PHP developers. There are various benefits of using PHP which attracts people towards it. In this way, let us discuss the most important reasons to utilize PHP in web development</p>
<p><img src="https://kinsta.com/wp-content/uploads/2020/03/php-tutorials.png" alt="enter image description here"></p>
<h4>1. Easy to Learn</h4>
<p>PHP is easy to learn, even if you have no more skills of programming. It is one of the essential benefits of learning PHP. Compared with other programming languages, PHP does not need one to spend a lot of time studying a manual. A complete web page will develop just a single PHP file.</p>
<h4>2. Familiarity with Syntax</h4>
<p>PHP has a compelling and easily understandable syntax. So, it is very familiar, and programmers are really comfortable coding with it. If you have any programming knowledge in both C and Perl, then learning PHP will be very easy, as its syntax is very similar to these programming languages.</p>
<h4>3. Free of Cost</h4>
<p>Since PHP is an open source web development language, it’s completely free of cost. PHP is available for free to every user, and the community of PHP developers gives excellent technical support. Therefore, all its components are free to use and distribute.</p>
<h4>4. User-Friendly</h4>
<p>PHP is one of the best user-friendly programming languages in the industry. It also gives more flexibility than C, C++, and ASP and overall helps in improving traffic to the website. To develop complex, dynamic and user-friendly web applications, PHP is only the first preference for all web developers. So, this feature is one of the main benefits of learning PHP</p>
<h4>5. Supports All of the Leading Databases</h4>
<p>Besides, PHP supports all of the leading databases, including MySQL, ODBC, SQLite and more. It is the main advantage of using PHP for web development.</p>
<h4>6. Efficiency in Performance</h4>
<p>Depending on your coding ability, PHP can turn out to be an effective programming language to use. PHP is known to be versatile when writing code and also in making web applications. Furthermore, it is extremely reliable when you have to serve a few web pages.</p>
<h4>7. A Helpful PHP Community</h4>
<p>PHP has a large community of developers who regularly updates tutorials, documentation, online help, and FAQs. It is one of the significant benefits of learning PHP to learn from the communities. If you have any trouble when using PHP, it is the best place you can find all information about the PHP language. Apart from this, you will get tips and tricks from PHP pros through several websites and forums. Additionally, PHP has a great community and resources to learn PHP online.</p>
<h4>8. Control</h4>
<p>While different programming languages require long scripts, PHP can do that same work in a few lines of code. It has the maximum control over the websites. Likewise, whenever you want to make changes, you can edit easily.</p>
<h4>9. Platform Independent</h4>
<p>PHP runs on just about each platform available allowing it to operate across different operating systems. Whether it is a Linux, UNIX, Mac OS, and Windows; it also supports all the major operating systems. It is one of the vital benefits of learning PHP to develop your skills in web development.</p>
<h4>10. Supports All Major Web Servers</h4>
<p>Apart from the operating systems, it also supports all major web servers like Apache, Microsoft IIS, Netscape, personal web server, iPlanet server, etc. As the programming language works with many operating systems, it will deploy on different platforms.</p>
<h4>11. Speedy</h4>
<p>PHP uses its own memory space, so the workload of the server and loading time will reduce automatically, which results into the faster processing speed. The processing speed is fast, and web applications like eCommerce, CRM, CMS, and Forums are also developed faster by it. It is the main importance of using PHP language in web development.</p>
<h4>12. Secured</h4>
<p>PHP is one of the most secure ways of developing websites and dynamic web applications. PHP has multiple layers of security to prevent threats and malicious attacks. It is the major importance of using PHP to develop a hybrid web application.</p>
<h4>13. Trusted</h4>
<p>PHP is being utilized for two decades now since its beginning in 1995. It is one of the major benefits of learning PHP. It is trusted by a large number of websites, and web developers and the list is expanding day to day. Besides, PHP has demonstrated its ability and versatility by developing and maintaining some of the most highly visited and popular sites.</p>
<h3>Conclusion:</h3>
<p>Hence, these are the benefits of using PHP in the web development. It is advisable for you to use it in your next web development services project. Therefore beginners should take up a proper training for learning PHP programming language to get a good head-start in their career. Interested aspirants can enroll our PHP training course that will assist you to become a successful PHP developer.</p>
]]></content:encoded>
    </item>
    <item>
      <title>My work from home workstation</title>
      <link>https://anzalabidi.dev/writing/my-work-from-home-workstation/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/my-work-from-home-workstation/</guid>
      <pubDate>Thu, 26 Jan 2023 18:16:22 GMT</pubDate>
      <description>The Pros and Cons of Working from Home as a Web Developer The US Occupational Outlook Handbook estimates that by 2024, there will be a 27% increase in the job prospects for this kind of expertise, due to the increasing use of mobile devices and e-com...</description>
      <category>workathome</category>
      <category>Beginner Developers</category>
      <category>layoff</category>
      <category>HTML5</category>
      <category>news</category>
      <content:encoded><![CDATA[<p>The Pros and Cons of Working from Home as a Web Developer The US Occupational Outlook Handbook estimates that by 2024, there will be a 27% increase in the job prospects for this kind of expertise, due to the increasing use of mobile devices and e-commerce.</p>
<p>Many web developers are also able to work from home, which makes it an attractive career option for some.</p>
<p>Some Web developers have a degree (2 or 4 year-programs) and certifications in web development. But above all, successful developers have a deep desire to learn constantly, whether its graphic design, programming, scripting and markup languages (HTML 5, CSS, Javascript or XML), or other areas.</p>
<p>Becoming a freelance web developer or telecommuting has several advantages. Let&#39;s discuss some of them.</p>
<blockquote>
<p>“ Code is like humor. When you have to explain it, it’s bad.” – Cory House</p>
</blockquote>
<h4>Advantages and Disadvantages of working from home.</h4>
<h5>Advantage #1. Freedom to Set your Own Hours</h5>
<p>The main advantage of working from home is the flexibility to work when and where you want. If you are already established web developer, you can decide how many hours you would typically spend on a project each day and then pace it based on your schedule.</p>
<p>Note that if you are just starting a career as a freelancer, you might have clients calling on you at odd hours of the day or night. In this case, you need to be flexible to accommodate their needs especially if you are still building your portfolio and reputation in the freelancing world.</p>
<h5>Advantage #2. Increased Productivity</h5>
<p>Website building requires long hours and working without the distraction of an office or co-workers can increase the time you devote to creating, improving, or tweaking the site. In effect, telecommuters are more productive as they put in extra hours and are less likely to take extended breaks or days off even when ill.</p>
<h5>Advantage #3. Ability to Balance Work and Home Life</h5>
<p>Part of the attraction of teleworking is that you can juggle your career and personal life at the same time. Since you set your own hours, you can devote time to spend with loved ones, friends, family and even pets. You are likely to feel happier and less stressed out knowing that you still manage to spend quality time with them while getting work done. You can even save on childcare and pet sitting costs since you are at home. People who work from home are also twice as likely to love their jobs than on-site workers (Leadership IQ Survey, 2016).</p>
<h5>Advantage #4. No Dress Codes and Stressful Commutes</h5>
<p>Working at home does not require a dress code which can save you a bundle in shopping and dry-cleaning costs. In addition, there are no nerve-wracking commutes that can affect you physically and mentally. You might have the occasional face-to-face meeting with a client, but these days, with the reliability of tele and videoconferences, there is hardly a need to meet in person unless you must do on-site work.</p>
<p><img src="https://cdn.dribbble.com/users/2005626/screenshots/13950416/media/6492fd3c15dcdf9433763e7af8ed9aa6.png?compress=1&resize=400x300&vertical=top" alt="enter image description here"></p>
<h5>Disadvantage #1. Discipline</h5>
<p>Having no set schedule might make you slack off in many ways such as putting off that web design project you have planned in favor of playing outdoors with the kids. Hence, telecommuting requires sheer discipline to ensure you follow the schedule you make and don&#39;t succumb to distractions.</p>
<h5>Disadvantage #2. Absence of External Pressures</h5>
<p>It is too easy to do anything you want when you are alone and no one is watching you which can make productivity levels plummet drastically. To avoid this, make a daily or weekly plan and stick to it.</p>
<h5>Disadvantage #3. Limited Social Life and Contacts</h5>
<p>You might feel isolated and left out when you are in the company of Fido all day long. Social contact and relationships are harder to form when you are home all day long. To remedy this, join networking clubs, get in touch with colleagues or volunteer some free time in community projects.</p>
<h5>Disadvantage #4. Overworking and Work Burnout</h5>
<p>Perhaps most importantly, is the danger of becoming overworked at home. It is all too easy to work at odd hours due to client demands or sales deadlines you have to meet.</p>
<h3>Conclusion</h3>
<p>Web development instinctively lends itself to quiet and focused environments, so working at home is a natural choice. It would be wrong to say there are not many things to consider but in most instances, web developers will reap many rewards when they make the decision to work from home. Or at least work remotely for some of the business week. It is not for everyone but there is definitely money to be made in developing from home.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Github Repository Controls</title>
      <link>https://anzalabidi.dev/writing/github-repository-controls/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/github-repository-controls/</guid>
      <pubDate>Thu, 26 Jan 2023 18:00:05 GMT</pubDate>
      <description>Github Tutorial: How to Make Your First GitHub Repository A critical skill for developers of all experience levels is proficiency in GitHub. Github is a hosting platform for Git repositories that acts as a central location to store and manage code. G...</description>
      <category>GitHub</category>
      <category>Beginner Developers</category>
      <category>start</category>
      <category>news</category>
      <category>github-actions</category>
      <content:encoded><![CDATA[<p>Github Tutorial: How to Make Your First GitHub Repository</p>
<p>A critical skill for developers of all experience levels is proficiency in GitHub. Github is a hosting platform for Git repositories that acts as a central location to store and manage code. GitHub is a popular choice for developers and their teams because it offers version control, collaboration capabilities, and a community of peers sharing their trials and successes in software engineering.</p>
<p>In this article, we’ll complete a tutorial on creating your first GitHub repository. First, let’s start with a closer look at the GitHub ecosystem and why I recommend students of my Web Developer Bootcamp course and all software developers take the time to understand this valuable tool.</p>
<h3>GitHub vs. Git</h3>
<p>They may have similar names, but GitHub is not synonymous with Git. Some developers work with Git and never use GitHub.</p>
<p>What’s Git? It’s an open-source version control management system that tracks changes to projects. Version control software records and manages every change made to source code and files. Git is a type of version control system for developers and teams to manage and collaborate on versions of code, which are stored in project repositories as it moves through the development life cycle.</p>
<p>Git can be used on its own without GitHub or other similar platforms, but it’s difficult to collaborate and share code with coworkers or the developer community without a platform like GitHub.</p>
<p>How does GitHub compare to Git? GitHub is a web platform that hosts Git repositories. Think of GitHub as a project viewer to share different code versions and access remote repositories. Each repository contains all project files and the code history. Repositories contain all project files, code history, and can have multiple collaborators.</p>
<p>Developers clone (download) a repository to their computer and work on a local version of the project. After working on code or developing new features on a local computer, developers push the changes to the same GitHub repository. Then, other developers or team members can download the version to their computer and stay synced with the project’s development.</p>
<p><img src="https://blogthinkbig.com/wp-content/uploads/sites/4/2020/04/GitHub-Mascot.jpg?fit=1500,1000" alt="enter image description here"></p>
<h2>5 GitHub benefits for developers</h2>
<p>We know how GitHub differs from Git, but why should developers take the time to learn and use it? There are several benefits that I share with students on why they should use GitHub:</p>
<p>Collaboration — Collaboration with the developer community is one of GitHub’s most common uses, and it’s also one of its biggest benefits. It’s a way for teammates to work together and provide feedback. GitHub is also an ideal way for open-source projects to see continued collaboration from individual developers. In fact, GitHub is the largest open-source code repository on the internet! Version control and backup — Git is the version control software, while GitHub is the platform where projects using Git are stored and accessed. Essentially, GitHub acts as the cloud backup to a software project. Project management — GitHub can be used as a technical project management tool to track issues and bugs. This helps projects stay on schedule throughout the software development life cycle. Developer portfolio — GitHub offers a free web hosting service called GitHub Pages. It’s a straightforward way to turn a GitHub repository into an easy-to-review portfolio website. Networking — GitHub is a bit like a social networking website for developers. Users can follow each other, give project ratings, collaborate, communicate, and meet other developers from around the world. How to create a GitHub repository Now that you know the why of GitHub, I’ll get you started on the platform with this tutorial on creating your first repository. We’ll start by creating a local project to demonstrate how to upload it to GitHub.</p>
<h4>Step 1: Create a new local Git repository</h4>
<p>Open up your terminal and navigate to your projects folder, then run the following command to create a new project folder and navigate into it:</p>
<pre><code>mkdir hello-world

cd hello-world
</code></pre>
<p>To initialize a new local Git repository we need to run the <code>git init</code> command:</p>
<h4>git init</h4>
<p>After you run that command, you should get feedback that an empty Git repository was initialized for your project.</p>
<h4>Step 2: Adding a new file to our Git repository</h4>
<p>Create a new file in your project folder, we will call our sample file <code>hello.js</code></p>
<p>You can use the graphical interface of your operating system to create the file, or use the following terminal commands:</p>
<p>Windows Powershell: ni hello.js Bash (Mac/Linux) terminal: touch hello.js</p>
<p>You can open the hello.js file with your text editor, and write the following JavaScript code which prints Hello World! to the console:</p>
<pre><code>console.log(&quot;Hello World!&quot;);
</code></pre>
<p>Save the file changes and switch back to your terminal window. Note: Make sure to use the <code>git status</code> command frequently when working with Git. It’s a great way to check the status of your project files and the whole repository.</p>
<p>Step 3: Making our initial commit to the local repository Run the following commands to track your files and make the initial commit in the local repository:</p>
<h4>git add .</h4>
<h4>git commit -m &quot;Initial commit&quot;</h4>
<p>When that’s done, it means that we successfully prepared our new local repository to be pushed to GitHub!</p>
<h4>Step 4: Creating a new GitHub repository</h4>
<p>To create a new GitHub repository, navigate to github.com and press the plus symbol in the top right corner, then select the ‘New repository‘ option, as shown in the screenshot here:</p>
<p>You can also navigate to the GitHub page for creating new repositories by visiting this link: <a href="https://github.com/new">https://github.com/new</a></p>
<p>On that page, we first need to specify a Repository name and an optional Description.</p>
<p>For the Repository name, we can specify the same project name (hello-world) as the local repository that we are using in our example. If you want, you can also write a Description of your repository, but you can also skip that field as we did in the screenshot above.</p>
<p>You can set your repository to be Public or Private. When uploading your code to a public directory, make sure it doesn’t contain any sensitive data not intended to share with others. When creating a Private repository, you’ll manually choose who can access the new repository.</p>
<h4>Step 5: Pushing our code to the GitHub repository</h4>
<p>After the last step, you’ll be sent to the starting page of your new GitHub repository, which looks like this:</p>
<p>Since we’ve already created our Git repo locally, we’ll focus on the “…or push an existing repository from the command line” section of the page.</p>
<p>(Note: If we didn’t already have a local repository created, then we would follow the first set of commands to create a local repository from the remote GitHub one that was just created.)</p>
<p>The git remote add origin command will associate our local repository with the remote GitHub repository that we just created. We’re essentially telling your Git repo that we have a URL we want it to know about, and we give it the name “origin.” You do not have to name the remote “origin” but it is standard if you only have a single remote.</p>
<p>The git push command then pushes our local Git repository code to the remote GitHub repository.</p>
<p>Now, switch back to your local terminal and run the specified commands from your project folder:</p>
<pre><code>git remote add origin &lt;https://github.com/&gt;&lt;your-username&gt;/&lt;your-repo-name&gt;.gitgit push -u origin master
</code></pre>
<p>When you run the git push command you’ll be prompted to enter your GitHub username and password, to log in to your GitHub account from the terminal.</p>
<p>After the repository is pushed, navigate back to your GitHub account page or the repository link and refresh it: <a href="https://github.com/%60">https://github.com/`</a><your-username><code>/</code><your-repo-name>`</p>
<p>Now, you can use that link to share your project repository with other people!</p>
<p>Anyone can click on the hello.js file to see the contents of our project files. Also, other developers can clone or download the remote repository to their local computer by clicking on the green button highlighted in the screenshot. Other data, including past commits, existing branches, etc. will be visible from the repository.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Virtual Assistant , What ,When and how.</title>
      <link>https://anzalabidi.dev/writing/virtual-assistant-what-when-and-how/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/virtual-assistant-what-when-and-how/</guid>
      <pubDate>Thu, 26 Jan 2023 14:22:46 GMT</pubDate>
      <description>What is a virtual assistant? A virtual assistant is a virtual employee hired as an executive or administrative assistant for your business who works remotely. In other words, a virtual assistant takes on recurring, repetitive, and administrative work...</description>
      <category>virtual assistant</category>
      <category>newbie</category>
      <category>technology</category>
      <category>Amazon</category>
      <content:encoded><![CDATA[<p>What is a virtual assistant? A virtual assistant is a virtual employee hired as an executive or administrative assistant for your business who works remotely.</p>
<p>In other words, a virtual assistant takes on recurring, repetitive, and administrative work to free up other employees’ time within the company.</p>
<p>A virtual assistant may work for a small business in tandem with a business owner to take tasks off their plate. In a larger company, such as a call or contact center, a virtual administrative assistant may work on duties to free up time for customer support representatives.</p>
<blockquote>
<p>“If you don’t know what your passion is, realize that one reason for your existence on earth is to find it.” – Oprah Winfrey, Entrepreneur, Producer, and Philanthropist.</p>
</blockquote>
<h3>What to add to a virtual assistant job description?</h3>
<p>Now that you understand what a virtual assistant is, let’s go over a few of the possible virtual assistant duties they can undertake to help you and your company.</p>
<p><img src="https://www.repricerexpress.com/wp-content/uploads/2020/01/amazon-virtual-assistant.jpg" alt="enter image description here"></p>
<h3>1. Social media management</h3>
<p>Virtual assistant tasks – social media management Since managing social media is inherently an online task, handing off your company’s social media profiles to your virtual assistant is one way to free up time for yourself or other employees.</p>
<p>A virtual assistant can monitor activity and engagement metrics on each social media platform your business is on and make sure to keep each channel active. Whether that includes a daily post or a Story update, keeping social platforms active and up-to-date is a perfect virtual assistant task. Virtual assistants can also take on the management of social media customer service.</p>
<p>If your virtual assistant skills include social media management, you can also assign them to develop a social media strategy and schedule activities in advance.</p>
<h3>2. Blog management and content production</h3>
<p>One of virtual assistant duties – writing a blog post Got a blog? A virtual administrative assistant can be a lifesaver. Tasks like planning and organizing an editorial calendar, editing, formatting, and publishing content – all that can be managed by your assistant even if they don’t have a background in producing content as such. A helping hand with administrative tasks in managing your company’s blog can significantly benefit your day-to-day workflow.</p>
<p>Another virtual assistant task idea includes reviewing the drafted content. About to hire a virtual assistant with some background in content creation and excellent language skills? Maybe they can be an occasional help with proofreading the writing when your team’s hands are full with other duties.</p>
<h3>3. Email management</h3>
<p>Inbox opened on a smart phone If you’re managing a company or you’re in charge of a team, there’s no doubt you have an oversaturated inbox.</p>
<p>Managing your emails–labeling them by type, responding to simple questions, and escalating time-sensitive issues–is something a virtual assistant can do with ease and little to no supervision. By delegating this task, you’ll get back essential hours in your workweek instead of spending your evenings combing through emails.</p>
<h3>4. Customer service</h3>
<p>Virtual assistant working for customer support Another possible responsibility for virtual assistants is customer service and support.</p>
<p>Whether you need a live support specialist to answer and resolve real-time support tickets or someone who responds to less urgent tickets at a slower pace, this is a task you can delegate to a virtual assistant.</p>
<p>Getting back to customer requests can take up quite a lot of time, even if you’re an owner of a small business. Have your virtual assistant field calls, support requests, order processing, and anything support-related you need help with, and you’ll have more time to spend on other duties.</p>
<h3>5. Financial tasks</h3>
<p>Financing Virtual assistants can also deal with financial matters. Since they can either be generalists or specialists, you can hire a finance-specific specialist, like a CPA, for daily financial tasks.</p>
<p>In this case, a virtual assistant’s tasks can include data entry and invoice creation or something more complex, like recording transactions and helping with bookkeeping duties. Whether you hire a data entry virtual assistant or a person skilled in financial matters – remember, you don’t have to deal with everything alone, and there are people happy to provide help and assistance as their professional occupation.</p>
<h2>When to hire a virtual assistant?</h2>
<p>Question mark If you’re in a managing position, you may have a line of time-consuming and repetitive tasks that steal work hours, which should be devoted to, for example, building strategy or meeting new clients.</p>
<p>Things that can fall into the category of such tasks include sending emails, making phone calls, creating lists, organizing files, scheduling meetings, preparing slide decks, developing content, and so much more.</p>
<p>Even if you’re a superhero with a crazy working capacity, it’s in your best interest to evaluate whether there are some duties you could entrust to someone else. Why be constantly tired and overwhelmed from the amount of work when you can hire a virtual assistant instead?</p>
<p>Let’s explore how to train a virtual assistant so they can take some of the work off your shoulders and benefit your business growth.</p>
<p>How to train your virtual personal assistant? Training a virtual assistant might seem daunting when they’re far away. Still, with the global acceleration of remote work in 2020, it’s become a lot easier and more commonplace to train employees at a distance.</p>
<p>Beyond smooth onboarding processes and proper written documentation, it’s essential to use tools that make the training process a breeze.</p>
<p>It’s a good idea to use project management tools, like a shared calendar or a digital vision board, to house all of your team’s projects, with one section specific to your virtual assistant.</p>
<p>We’ve compiled seven easy-to-follow tips for training a virtual assistant that will make the process as seamless as it can be.</p>
<h3>1. Set the right expectations</h3>
<p>Running hurdles Before dumping a ton of work on your new virtual assistant, you need to have a strong foundation in place. If they, for example, live in a different time zone than you, make sure you establish working hours across time zones and what is considered “off-hours”.</p>
<p>Once you set those expectations, create an outline of weekly objectives and longer-term goals. You’re likely bringing on a virtual assistant to make your life or the lives of multiple employees easier, so it’s your job to equip them with the right tools and set expectations from the get-go.</p>
<p>To reiterate, do the following:</p>
<p>Clarify working and off-hours. Provide weekly, monthly, quarterly, and annual objectives and expectations. Figure out how you want to track their working hours, especially those that are asynchronous – a time tracking tool is an obvious way to do this.</p>
<h3>2. Provide adequate training materials</h3>
<p>You want to ease your virtual assistant into daily operations. Providing high-quality training materials like videos, screenshots, written documentation, and more is a great way to get your virtual assistant up and running comfortably.</p>
<p>Create a convenient information hub that contains the most critical deadlines, tools, people to contact on the team, and other resources your virtual assistant needs to be successful in their role.</p>
<p>Plus, ask which communication style your virtual assistant prefers. For example, some people go for emails, others – team chat or phone. Whatever your virtual assistant’s choice of communication is, use that primarily to ease their training process. Additionally, remember to integrate them into the team’s communication, so your virtual assistant is up-to-speed with the latest information.</p>
<h3>3. Use videos and screencasts</h3>
<p>Filming training video Using video is a great way to show and tell how to do more complex business tasks. Apps like CloudApp, Loom, and Vimeo have inexpensive options to record and share processes on your screen.</p>
<p>You can then compile these videos and screencasts in a repository and send them to your virtual assistant during the training process. Such content is an excellent alternative to long-winded powerpoints and screenshots with confusing jargon. However, if you must use screenshots, keep the number to a minimum, and provide context, supplemental notes, and instructions where applicable.</p>
<h3>4. Communicate effectively</h3>
<p>One of the most challenging tasks when training and working with a virtual assistant is staying on the same page. For example, if your virtual assistant lives in a timezone three hours away, this could create a divide if you don’t have a collaboration and communication plan in place.</p>
<p>According to statistics, 83% of companies lost a customer, missed an important deadline, or terminated an employee due to a communication issue in 2019.</p>
<p>One way to stay on top of communication is through regular email updates. You can send and receive daily updates to keep each other accountable on tasks. However, if your virtual assistant has lots of emails filling their inbox, this could pose a communication issue.</p>
<h3>5. Exploit project management tools</h3>
<p>Set of tools Using a cloud-based project management tool is essential when training your virtual assistant. These tools make it easier to collaborate, especially when working on the same documents together. A typical example of this would be you and your virtual assistant working on a slideshow simultaneously.</p>
<p>Even longer-term project planning can be made more accessible through a work board like Asana or Trello. But if you’re interested in the most accessible option on a tighter budget, something like Google Drive may also work for your business needs.</p>
<h3>6. Build a resource center</h3>
<p>Once you’ve created your training documents, step-by-step guides, explainer videos, screencasts, and slide decks for training, collate all your training material into a single repository. This way, you won’t have to create multiple versions of the same documents.</p>
<p>Pro tip: If you’re looking to take it a step further, a learning management system is a great way to centralize your training resources.</p>
<p>Every time you create a new set of instructions, add them to the directory. This will be your master list you can work with and revamp as time goes on. For extra value, include both marketing and sales playbooks to give additional references depending on the type of work you assign to your virtual assistant.</p>
<h3>7. Present feedback, constructive criticism, and praise</h3>
<p>Feedback print While you can’t be in the same physical location as your virtual assistant, this doesn’t mean you can neglect to treat them as you would an in-office employee.</p>
<p>Ensure that you’re offering ample feedback and constructive criticism on their work, especially in areas that need improvement.</p>
<p>If your virtual assistant isn’t doing the job right, explain what you need them to change to be at their best. But if they are excelling, be sure to let them know that too. Lack of performance recognition, on average, drives 44% of employees to look for other jobs. Can you afford to lose a high-performing virtual assistant to another company?</p>
<p>Final thoughts on finding a virtual assistant All in all, hiring a virtual assistant is probably one of the most sensible business decisions you can make this year, especially with remote work continuously on the rise.</p>
<p>Whether you’re a smaller business that could use some extra brain-power or a large enterprise that can no longer spare time for a set of particular tasks, hiring a virtual assistant is a great choice to make. With both niche specialists and generalists galore, you can have your pick of the virtual assistant right for your team’s needs.</p>
<p>19:T2ee0, What is a virtual assistant? A virtual assistant is a virtual employee hired as an executive or</p>
]]></content:encoded>
    </item>
    <item>
      <title>What you need to know about programming.</title>
      <link>https://anzalabidi.dev/writing/what-you-need-to-know-about-programming/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/what-you-need-to-know-about-programming/</guid>
      <pubDate>Thu, 26 Jan 2023 14:13:18 GMT</pubDate>
      <description>We all have heard about Computer Programming gaining a lot of popularity in the past 3 decades. So many students these days want to opt for a Computer Science stream in order to get a job at their dream tech company - Google, Facebook, Microsoft, App...</description>
      <category>Programming Blogs</category>
      <category>Beginner Developers</category>
      <category>Programming Tips</category>
      <category>C++</category>
      <category>Python</category>
      <content:encoded><![CDATA[<p>We all have heard about Computer Programming gaining a lot of popularity in the past 3 decades. So many students these days want to opt for a Computer Science stream in order to get a job at their dream tech company - Google, Facebook, Microsoft, Apple, and whatnot.</p>
<p>What is Programming? In this blog post, we will decipher the term “programming” and understand its usage and many other related terms.</p>
<p>Understanding Programming in layman terms Programming is a way to “instruct the computer to perform various tasks”.</p>
<p>Confusing? Let us understand the definition deeply.</p>
<blockquote>
<p>“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” – Martin Fowler</p>
</blockquote>
<h4>Brief intro to what coding actually is</h4>
<p>“Instruct the computer”: this basically means that you provide the computer a set of instructions that are written in a language that the computer can understand. The instructions could be of various types. For example:</p>
<p>Adding 2 numbers, Rounding off a number, etc. Just like we humans can understand a few languages (English, Spanish, Mandarin, French, etc.), so is the case with computers. Computers understand instructions that are written in a specific syntactical form called a programming language.</p>
<p>“Perform various tasks”: the tasks could be simple ones like we discussed above (adding 2 numbers, rounding off a number) or complex ones which may involve a sequence of multiple instructions. For example:</p>
<p>Calculating simple interest, given principal, rate and time. Calculating the average return on a stock over the last 5 years. The above 2 tasks require complex calculations. They cannot usually be expressed in simple instructions like adding 2 numbers, etc.</p>
<p>Hence, in summary, Programming is a way to tell computers to do a specific task.</p>
<p><img src="https://thumbs.dreamstime.com/b/cartoon-programmer-working-behind-computer-coder-to-sit-armchair-table-77862319.jpg" alt="enter image description here"></p>
<h3>Why should you bother about coding?</h3>
<p>You must be wondering - why does one need a computer for adding or rounding off numbers? Or even for simple interest calculation? After all, even an 8th standard kid can easily do such things even over large numbers. What is programming used for? What benefits do computers offer?</p>
<p>Well, computers offer so many benefits:</p>
<p>Computers are fast: computers are amazingly fast. If you know how to properly utilize the power of Computer programming, you can do wonders with it. For a typical computer of today’s time, an addition of 2 numbers which could be as big as a billion each takes hardly a nanosecond. Read again - nanosecond! That means that in 1 second, a computer can perform about a billion additions. Can any human ever do that? Forget a billion additions a second, typical human can’t even do 10 additions per second. So, computers offer great speed. Computers are cheap: if you were a stock market analyst and you had to monitor the data of say 1000 stocks so that you can quickly trade them. Imagine the hassle that would create if you were to do it manually! It is just impractical. While you are performing your calculation on the stock’s performance, the price may change. The other alternative is to hire people so that you can monitor more stocks in parallel. That means your cost goes up significantly. Not to mention the trouble you will face if some of your employees commit a calculation error in the process. You may end up losing money! Contrast that with the case where you use a computer. Computers can process a huge amount of information quickly and reliably. 1000 stocks are nothing for computers in the 21st century. Computers can work 24x7: Computers can work 24x7 without getting exhausted. So, if you have a task that is big enough, you can without worries allocate it to a computer by programming it and sleep peacefully. What is Programming Language? As mentioned above, Computers understand instructions that are written in a specific syntactical form called a programming language. A programming language provides a way for a programmer to express a task so that it could be understood and executed by a computer. Refer our another blog-post &quot;What is programming language?&quot; to know more about programming languages. Some of the popular Programming languages are Python, C, C++, Java, etc.</p>
<p>Why should you learn Computer Programming? Now, after knowing so many things about programming, the big question to be answered is - why should you learn Computer Programming? Let us understand why:</p>
<p>Programming is fun: Using Programming, you can create your own games, your personal blog/profile page, a social networking site like Facebook, a search engine like Google or an e-commerce platform like Amazon! Won’t that be fun? Imagine creating your own game and putting it on Play Store and getting thousands and thousands of downloads! The backbone of a Technology Company: The backbones of today’s technology companies like Google, Facebook, Microsoft, Apple, Amazon, and many others, are giant computer programs written by a collaboration of thousands of skilled programmers. If you have the right business acumen, knowing programming can help you create the next big tech company. Pretty good salary: Computer Programmers are paid extremely well almost all across the world. Top programmers in Silicon Valley make millions of dollars every year. Quite a few companies offer to start salaries as high as $100,000 per year. Let us now get into an actual program</p>
<h2>Writing your first program</h2>
<p>Python is a widely-used programming language. It is extremely beginner-friendly. You can download Python here: <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a>. After downloading, run the installer in order to install Python on your machine.</p>
<p>Let us delve into our first Python code now. Open your favorite text editor (we’d recommend Sublime Text) and copy-paste the following 3 lines:</p>
<pre><code>a = 54
b = a ** 8
print b
</code></pre>
<p>Save the file on your desktop as my_first_program.py</p>
<p>Now, do one of the following depending on your operating system:</p>
<p>Windows: open command prompt and type python my_first_program.py Ubuntu/Mac OSX: open terminal and type python my_first_program.py When you press enter, what do you see on the screen? Almost instantly after you press the enter key, you will see the following:</p>
<p>What’s that? That’s 548, computed by your computer in the blink of an eye! A typical human will take minutes if not seconds to get the result. You see the power of a Computer?</p>
<p>Congratulations, you’ve written your first program. Let us understand how it works.</p>
<pre><code>a = 54
</code></pre>
<p>We are declaring here that we have a “placeholder” called as a to which we assign the value 54.</p>
<pre><code>b = a ** 8
</code></pre>
<p>Here, we are declaring another placeholder called as b to which we assign the value a 8 . Here, the value of a is 54. So, effectively we are computing 54 8 . What is <code>**</code> ? The <code>**</code> operator is the “power” operator. <code>a ** b</code> means <code>a^b</code>.</p>
<p><code>print b</code></p>
<p>Finally, after the computation is done, we want to display the result on the screen. For this, we have used the print statement which essentially throws the result on your screen.</p>
<p>So, that was about the very basics of Computer programming. Hope you enjoyed reading it. Computer Programming is a huge field and there is a lot to explore further. Keep learning and keep exploring. Please feel free to post your doubts in the comments section. Please don’t worry if you feel that your doubt is maybe silly. Every question/doubt is important. There&#39;s no such thing as a stupid question.</p>
<p>19:T1dbd,We all have heard about Computer Programm</p>
]]></content:encoded>
    </item>
    <item>
      <title>Artificial Intelligence and Robotics In A Nutshell</title>
      <link>https://anzalabidi.dev/writing/artificial-intelligence-and-robotics-in-a-nutshell/</link>
      <guid isPermaLink="true">https://anzalabidi.dev/writing/artificial-intelligence-and-robotics-in-a-nutshell/</guid>
      <pubDate>Thu, 26 Jan 2023 13:55:22 GMT</pubDate>
      <description>Artificial Intelligence is an umbrella term and describes the broad approach of using machines to imitate intelligent human behavior in order to solve problems. Machine Learning is a technology used to achieve Artificial Intelligence. For example, if...</description>
      <category>AI</category>
      <category>chatgpt</category>
      <category>Machine Learning</category>
      <category>Computer Science</category>
      <category>Artificial Intelligence</category>
      <content:encoded><![CDATA[<p>Artificial Intelligence is an umbrella term and describes the broad approach of using machines to imitate intelligent human behavior in order to solve problems.</p>
<p>Machine Learning is a technology used to achieve Artificial Intelligence. For example, if one were to develop an algorithm to detect fraud in financial data, this would be typical AI. If this algorithm still learns itself and also recognizes new facts, it would be called ML. Deep Learning is the further development of Machine Learning. The technology makes use of so-called neural networks (similar to how the human brain works) or artificial neural networks.</p>
<blockquote>
<p>“People worry that computers will get too smart and take over the world, but the real problem is that they&#39;re too stupid and they&#39;ve already taken over the world.&quot; ― Pedro Domingos</p>
</blockquote>
<h4>Tools and conclusive analysis</h4>
<p>Tools What are the tools like programming languages, services and software you can use for data science? Programming Languages — Famous programming languages are:</p>
<ul>
<li>R</li>
<li>Python</li>
</ul>
<p>But also C# and SQL are very common for data science tasks. Services — Here you will find a lot especially in the clouds of the big three like Google, AWS and Azure. Often used services are e.g. image and video recognition, translation, NLP and many more. Software — Here will find also many useful software. Free software like:</p>
<ul>
<li><p>Anaconda</p>
</li>
<li><p>Jupyter Notebook</p>
</li>
<li><p>R Studio</p>
<h4>and also software you have to pay for like:</h4>
</li>
<li><p>alteryx</p>
</li>
<li><p>MS Power BI</p>
</li>
<li><p>Tableau</p>
</li>
<li><p>Methods</p>
</li>
</ul>
<p>Besides certain tools you will also need a data science process. Here, the most famous process to develop AI is the CRISP model.</p>
<p><img src="https://www.state.gov/wp-content/uploads/2021/06/AI-Motherboard-scaled.jpg" alt="enter image description here"></p>
<p>CRISP-DM stands for “Cross Industry Standard Process for Data Mining”. It is a standardized process model that can be used for data mining in order to search data stocks for patterns, trends and correlations. For this purpose, the standard defines six different phases that are to be run through once or several times. The model can be used across many disciplines like data science, business intelligence and engineering . Supervised, Unsupervised and Reinforcement Learning Supervised Learning: Here, the algorithms are defined on the basis of specific examples. An attempt is made to find the solution for other similar problems by generalizing a solution. Supervised learning can be used, for example, to predict customer churn. Popular examples are classifier and regression analysis . Unsupervised Learning: Here, the algorithms are processed with arbitrary examples. The goal here is to identify a structure within the data set. The most important method is clustering.</p>
<p>Reinforcement Learning: Reinforcement learning or reinforcement learning stands for a set of machine learning methods in which an agent autonomously learns a strategy to maximize rewards received. One of the most famous algorithm as an examples is the Monte Carlo algorithm. Conclusion</p>
<p>This is in short what you have to know about Artificial Intelligence. To dive deeper you can use the sources below or just google a bit. Famous platforms to start learning and gaining certificates are for example Udemy, Data Camp or Udacity.</p>
<p>19:Tcb0,Artifi</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
