<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Neeraj Mukta</title>
    <description>The latest articles on DEV Community by Neeraj Mukta (@fullstacknrj).</description>
    <link>https://dev.to/fullstacknrj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F449255%2Fb9224810-63c6-48cf-91fa-6add96b6d679.jpg</url>
      <title>DEV Community: Neeraj Mukta</title>
      <link>https://dev.to/fullstacknrj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fullstacknrj"/>
    <language>en</language>
    <item>
      <title>Top 3 JEV Alternatives in 2026</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Mon, 19 Oct 2026 12:28:33 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/top-3-jev-alternatives-in-2026-4d2g</link>
      <guid>https://dev.to/fullstacknrj/top-3-jev-alternatives-in-2026-4d2g</guid>
      <description>&lt;p&gt;Jev made AI decisions cheaper and faster. But with open-weight models and new competitors entering the market, is it still the right choice for your application?&lt;/p&gt;

&lt;p&gt;Most AI applications don't need another paragraph of generated text.&lt;/p&gt;

&lt;p&gt;They need an answer to a specific question.&lt;/p&gt;

&lt;p&gt;Is this support ticket urgent? Should this customer be routed to sales or billing? Does this message violate our moderation policy? Should an AI agent call a tool or ask a human for help?&lt;/p&gt;

&lt;p&gt;Traditionally, developers use general-purpose large language models (LLMs) for these decisions. They send a prompt, ask for structured JSON, and parse the response. It works, but it can introduce unnecessary latency, cost, and complexity.&lt;/p&gt;

&lt;p&gt;Jev, developed by TypeSafe AI, takes a different approach: instead of generating text, it returns typed decisions with probabilities that your application can act on directly. Source: TypeSafe AI&lt;/p&gt;

&lt;p&gt;But Jev isn't the only option anymore. Cloudflare, Perplexity, and open-source developers are building alternatives that offer different combinations of price, accuracy, flexibility, and deployment control.&lt;/p&gt;

&lt;p&gt;Let's look at what makes Jev useful, where its pricing can become expensive, and the three alternatives worth evaluating.&lt;/p&gt;

&lt;p&gt;Jev pricing: Is it actually expensive?&lt;/p&gt;

&lt;p&gt;Jev's published pricing is straightforward: $0.042 per million input tokens, with output tokens free, according to TypeSafe AI's pricing information. Source: TypeSafe AI&lt;/p&gt;

&lt;p&gt;There are no per-seat charges in that pricing model. You pay for the input processed by the model.&lt;/p&gt;

&lt;p&gt;Here is what the listed rate means in practice:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Monthly input volume&lt;/th&gt;
&lt;th&gt;Estimated API cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 million tokens&lt;/td&gt;
&lt;td&gt;$0.042&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100 million tokens&lt;/td&gt;
&lt;td&gt;$4.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 billion tokens&lt;/td&gt;
&lt;td&gt;$42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 billion tokens&lt;/td&gt;
&lt;td&gt;$420&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These figures use the published input rate and exclude infrastructure, retries, and other application costs.&lt;/p&gt;

&lt;p&gt;At first glance, Jev is remarkably cheap. So why look for alternatives?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The absence of a free tier matters during experimentation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A low per-token price isn't the same as free experimentation. Developers building an MVP often test prompts, replay datasets, and run evaluations repeatedly. Even if the API bill stays small, there is no reason to pay for a hosted service before establishing that it works for your use case.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Input volume is the real cost driver&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Decision models charge for the information they process. Passing an entire conversation history or a long document when a short excerpt would suffice wastes tokens.&lt;/p&gt;

&lt;p&gt;For example, processing 10,000 tokens per decision instead of 1,000 tokens increases input costs tenfold.&lt;/p&gt;

&lt;p&gt;The solution isn't necessarily switching providers. It may be trimming the input, caching unchanged decisions, and batching related questions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Closed weights limit deployment flexibility&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Jev is a hosted, proprietary model. If you want to run inference within your own infrastructure, fine-tune a model on your own labelled dataset, or exercise greater control over deployment, you need to evaluate other approaches.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cheap inference doesn't guarantee cheap decisions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Accuracy matters. A model that costs less per request but misroutes support tickets or incorrectly blocks legitimate users may be more expensive overall.&lt;/p&gt;

&lt;p&gt;The verdict: Jev's published token price is already very low. Its strongest alternatives aren't necessarily about saving a few dollars. They are about open weights, multimodal inputs, deployment flexibility, and finding a model that performs better on your specific workload.&lt;/p&gt;

&lt;p&gt;The top 3 Jev alternatives&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloudflare Clef-flash — Best for Cloudflare developers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cloudflare introduced Clef and Clef-flash as open-weight decision models in October 2026. Like Jev, they take a state and typed questions and return probabilities for the allowed answers. Source: Cloudflare announcement&lt;/p&gt;

&lt;p&gt;Clef-flash is the smaller, faster-oriented option in the family, with support for text, JSON, images, and video.&lt;/p&gt;

&lt;p&gt;Pricing: Cloudflare lists Clef-flash at $0.038 per million input tokens on Workers AI. Its hosted context window is 24,576 tokens. Source: Cloudflare model documentation&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;p&gt;Slightly cheaper than Jev at the published hosted rate.&lt;/p&gt;

&lt;p&gt;Open weights under the Apache 2.0 licence, allowing self-hosting subject to the licence.&lt;/p&gt;

&lt;p&gt;Supports image and video inputs, unlike Jev's text-only interface.&lt;/p&gt;

&lt;p&gt;A natural option for applications already using Cloudflare Workers AI.&lt;/p&gt;

&lt;p&gt;Decision-oriented outputs avoid the need to parse free-form generated prose.&lt;/p&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;p&gt;The smaller hosted context window may be a limitation for long documents or conversation histories.&lt;/p&gt;

&lt;p&gt;The larger Clef model costs more: $0.24 per million input tokens on Workers AI.&lt;/p&gt;

&lt;p&gt;Open weights don't mean free production inference; self-hosting requires compute and operational work.&lt;/p&gt;

&lt;p&gt;You still need to benchmark accuracy and confidence calibration on your own dataset.&lt;/p&gt;

&lt;p&gt;Best use cases: AI applications running on Cloudflare, image-based moderation, multimodal workflows, and teams that want more control over model deployment.&lt;/p&gt;

&lt;p&gt;My take: If your backend already runs on Cloudflare, Clef-flash is the first alternative I'd benchmark. The combination of a lower listed price, multimodal support, and open weights makes it a compelling option.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Perplexity pplx-decider — Best candidate for cost-conscious, high-volume decisions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Perplexity's pplx-decider family is another direct competitor in the decision-model category. Its newer 27B model, pplx-decider-v1.1-27b, is designed to return structured decisions rather than conventional chat responses.&lt;/p&gt;

&lt;p&gt;Perplexity announced the updated model in October 2026, positioning it as an open-weight, multimodal decision model. Source: Perplexity API announcements&lt;/p&gt;

&lt;p&gt;Pricing: Recent October 2026 comparisons report hosted input pricing as low as $0.02 per million tokens. Verify the current model-specific API rate before committing to a budget, as prices and hosting options can change quickly.&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;p&gt;Potentially the lowest hosted input cost among the three alternatives discussed here.&lt;/p&gt;

&lt;p&gt;A 27B model offers a different quality-versus-compute trade-off from smaller models.&lt;/p&gt;

&lt;p&gt;Open-weight availability provides a route to self-hosting, subject to the model's licence and distribution terms.&lt;/p&gt;

&lt;p&gt;Multimodal capabilities make it worth testing for workflows that go beyond plain text.&lt;/p&gt;

&lt;p&gt;An attractive candidate for applications processing large numbers of repetitive decisions.&lt;/p&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;p&gt;A larger model may require more resources if you self-host it.&lt;/p&gt;

&lt;p&gt;Lower token pricing doesn't guarantee lower total cost if the model uses more tokens or needs more retries.&lt;/p&gt;

&lt;p&gt;You should verify current API compatibility, licensing, and deployment requirements rather than assume they match Jev exactly.&lt;/p&gt;

&lt;p&gt;Public benchmark results may not predict performance on your particular labels, languages, or business rules.&lt;/p&gt;

&lt;p&gt;Best use cases: High-volume classification, ticket routing, moderation, and applications where reducing per-decision inference costs is a priority.&lt;/p&gt;

&lt;p&gt;My take: Perplexity is worth evaluating when you're optimizing for unit economics at scale. However, compare the actual billed tokens per decision, not just the advertised price per million tokens. Different APIs can account for shared input and multiple questions differently.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kev — Best for developers who want self-hosting and control&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kev is an open-weight family of decision models associated with developer Jared Palmer. It is designed for the same general task as Jev: answering predefined questions about an input with structured outputs.&lt;/p&gt;

&lt;p&gt;Kev is particularly interesting because it offers multiple model sizes and documents support for fine-tuning on your own labelled examples. Its server can also use a Jev-compatible request format, making it a candidate for testing as a replacement. Background: Jev alternatives comparison&lt;/p&gt;

&lt;p&gt;Pricing: The model weights can be used without paying a per-token API fee when you run them yourself, subject to the applicable licence. Compute, hosting, storage, and engineering time are still costs.&lt;/p&gt;

&lt;p&gt;Pros&lt;/p&gt;

&lt;p&gt;Self-hosting gives you greater control over where inference happens.&lt;/p&gt;

&lt;p&gt;Multiple model sizes let you explore the trade-off between speed, resource requirements, and accuracy.&lt;/p&gt;

&lt;p&gt;Fine-tuning can help with domain-specific classifications and custom labels.&lt;/p&gt;

&lt;p&gt;A Jev-compatible server interface can reduce migration effort.&lt;/p&gt;

&lt;p&gt;No mandatory per-token provider charge when you operate your own inference infrastructure.&lt;/p&gt;

&lt;p&gt;Cons&lt;/p&gt;

&lt;p&gt;You must deploy, monitor, scale, and maintain the model.&lt;/p&gt;

&lt;p&gt;Hardware and engineering costs can outweigh API savings at low volumes.&lt;/p&gt;

&lt;p&gt;Fine-tuning requires good labelled data, evaluation, and ongoing maintenance.&lt;/p&gt;

&lt;p&gt;Performance and calibration must be tested; open weights don't automatically mean equivalent quality to Jev.&lt;/p&gt;

&lt;p&gt;Best use cases: Teams with privacy or deployment constraints, products with stable classification tasks, and developers who want to customize a model for their own data.&lt;/p&gt;

&lt;p&gt;My take: Kev is the option I'd investigate if control matters more than convenience. For a weekend MVP, a hosted API is generally simpler. For a mature product with substantial inference volume or strict data requirements, self-hosting becomes a more serious contender.&lt;/p&gt;

&lt;p&gt;Jev vs. its alternatives: Quick comparison&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Jev&lt;/th&gt;
&lt;th&gt;Clef-flash&lt;/th&gt;
&lt;th&gt;pplx-decider&lt;/th&gt;
&lt;th&gt;Kev&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main strength&lt;/td&gt;
&lt;td&gt;Simple hosted decisions&lt;/td&gt;
&lt;td&gt;Cloudflare and multimodal workflows&lt;/td&gt;
&lt;td&gt;Cost-conscious decisions&lt;/td&gt;
&lt;td&gt;Self-hosting and customization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listed input price&lt;/td&gt;
&lt;td&gt;$0.042/M&lt;/td&gt;
&lt;td&gt;$0.038/M hosted&lt;/td&gt;
&lt;td&gt;Reported as low as $0.02/M hosted&lt;/td&gt;
&lt;td&gt;No mandatory per-token fee when self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output token charge&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Check current API pricing&lt;/td&gt;
&lt;td&gt;Depends on deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open weights&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Available; verify licence&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multimodal&lt;/td&gt;
&lt;td&gt;Text-focused&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes, for supported inputs&lt;/td&gt;
&lt;td&gt;Model-dependent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational effort&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low when hosted&lt;/td&gt;
&lt;td&gt;Low when hosted&lt;/td&gt;
&lt;td&gt;Higher when self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best fit&lt;/td&gt;
&lt;td&gt;Quick integration&lt;/td&gt;
&lt;td&gt;Cloudflare applications&lt;/td&gt;
&lt;td&gt;High-volume evaluation&lt;/td&gt;
&lt;td&gt;Custom infrastructure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Prices are in USD and are based on published or recently reported October 2026 rates. They are not a like-for-like performance benchmark. Check each provider's current documentation before deployment.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Which alternative should you choose?&lt;/p&gt;

&lt;p&gt;There isn't one universal winner. The right decision depends on what you're optimizing for.&lt;/p&gt;

&lt;p&gt;Choose Jev if you want a straightforward hosted API for typed decisions and its performance meets your requirements. At its published price, switching solely to save money may not justify the migration.&lt;/p&gt;

&lt;p&gt;Choose Clef-flash if you use Cloudflare, need multimodal decision-making, or want open weights without giving up hosted inference.&lt;/p&gt;

&lt;p&gt;Choose pplx-decider if low hosted inference cost is a priority and your own evaluations confirm that it performs well on your workload.&lt;/p&gt;

&lt;p&gt;Choose Kev if you need self-hosting, greater customization, or control over your inference environment.&lt;/p&gt;

&lt;p&gt;How I'd evaluate them before switching&lt;/p&gt;

&lt;p&gt;Don't choose based on benchmark rankings alone. Build a small evaluation set from real inputs in your application.&lt;/p&gt;

&lt;p&gt;Collect 200–500 representative examples from your actual workload.&lt;/p&gt;

&lt;p&gt;Label the correct answers and identify decisions where an error would be costly.&lt;/p&gt;

&lt;p&gt;Run Jev and the alternatives on the same examples with equivalent questions.&lt;/p&gt;

&lt;p&gt;Measure accuracy, per-class precision and recall, latency, and calibration.&lt;/p&gt;

&lt;p&gt;Record the actual billed tokens and cost per accepted decision, including retries.&lt;/p&gt;

&lt;p&gt;Test how each model behaves on ambiguous or unfamiliar inputs.&lt;/p&gt;

&lt;p&gt;For production systems, define explicit confidence thresholds and route uncertain or high-impact decisions to human review. A probability is useful only if it helps you make better decisions about when to trust the model.&lt;/p&gt;

&lt;p&gt;One additional consideration: if your label set is fixed and you have enough labelled data, a conventional trained classifier may outperform all these options on cost and latency. If your task requires open-ended reasoning or explanations, a general-purpose LLM with structured outputs may be the better fit.&lt;/p&gt;

&lt;p&gt;Final thoughts&lt;/p&gt;

&lt;p&gt;Jev is interesting because it challenges a common assumption in AI development: that every intelligent operation needs to generate text.&lt;/p&gt;

&lt;p&gt;Most applications don't need prose at every step. They need reliable decisions that software can act on.&lt;/p&gt;

&lt;p&gt;That distinction creates opportunities to build faster, cheaper, and more predictable AI workflows. But the market is evolving quickly, and open-weight models are making it easier to choose where and how those decisions happen.&lt;/p&gt;

&lt;p&gt;My recommendation is simple: start with the simplest hosted option, benchmark alternatives against your own data, and switch only when you can demonstrate a meaningful improvement in cost, quality, latency, or control.&lt;/p&gt;

&lt;p&gt;The best decision model isn't the one with the most impressive benchmark. It's the one that makes your application work better.&lt;/p&gt;

&lt;p&gt;Have you tried Jev, Clef, pplx-decider, or Kev in production? I'd be interested in hearing about your measured latency, accuracy, and cost per decision.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>softwaredevelopment</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Top 4 Jev Use Cases: Why AI Needs a Decision Engine</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Tue, 13 Oct 2026 16:47:30 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/top-4-jev-use-cases-why-ai-needs-a-decision-engine-hbe</link>
      <guid>https://dev.to/fullstacknrj/top-4-jev-use-cases-why-ai-needs-a-decision-engine-hbe</guid>
      <description>&lt;h1&gt;
  
  
  Top 4 Jev Use Cases: Why AI Needs a Decision Engine
&lt;/h1&gt;

&lt;p&gt;The AI boom has focused on generating better text: bigger models, longer reasoning, and larger context windows.&lt;/p&gt;

&lt;p&gt;But production AI systems have a different problem. They need to make decisions.&lt;/p&gt;

&lt;p&gt;Should a request go to a particular agent? Is an answer grounded in the source material? Is a tool call safe? Which retrieved documents are actually relevant?&lt;/p&gt;

&lt;p&gt;Developers often use LLMs for these tasks, even though they don't need a paragraph of text. They need a reliable answer, fast.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Jev comes in.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Jev?
&lt;/h2&gt;

&lt;p&gt;Jev, developed by TypeSafe AI, is designed for structured decisions rather than text generation.&lt;/p&gt;

&lt;p&gt;Think of traditional LLMs as System 2 thinkers: capable of reasoning through complex problems, but relatively expensive and slow for simple checks.&lt;/p&gt;

&lt;p&gt;Jev takes the System 1 approach: fast, focused decisions with structured outputs.&lt;/p&gt;

&lt;p&gt;The idea is simple: &lt;strong&gt;use generative models to create, and decision models to evaluate.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If decisions become cheaper and faster, software can make more of them without adding unnecessary latency or cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Jev Work?
&lt;/h2&gt;

&lt;p&gt;Instead of asking a model to generate text and then parsing the response, you give Jev a state and a set of questions.&lt;/p&gt;

&lt;p&gt;It supports three types of decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Noul:&lt;/strong&gt; A binary decision, such as whether an answer is supported by the source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score:&lt;/strong&gt; A rating, such as customer sentiment from 1 to 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choice:&lt;/strong&gt; A classification, such as routing a request to billing, support, or sales.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jev returns structured values that your application can use directly in its logic.&lt;/p&gt;

&lt;p&gt;For example, instead of asking an LLM to explain whether a refund is eligible, your application can ask for a binary decision and use the result to determine the next step.&lt;/p&gt;

&lt;p&gt;No unnecessary prose. No parsing generated JSON. Just structured output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jev vs. Traditional LLMs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Traditional LLM&lt;/th&gt;
&lt;th&gt;Jev&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Generation and complex reasoning&lt;/td&gt;
&lt;td&gt;Classification, scoring and selection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;Text or generated JSON&lt;/td&gt;
&lt;td&gt;Structured decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latency&lt;/td&gt;
&lt;td&gt;Depends on model and output length&lt;/td&gt;
&lt;td&gt;Designed for low-latency inference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Input and output tokens&lt;/td&gt;
&lt;td&gt;Designed for low-cost decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best role&lt;/td&gt;
&lt;td&gt;Creating answers&lt;/td&gt;
&lt;td&gt;Evaluating and routing work&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Jev isn't a replacement for GPT or Claude. It fills a different role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think of it as a decision layer alongside your LLM stack.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Top 4 Practical Use Cases for Jev
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Evaluating LLM Outputs
&lt;/h3&gt;

&lt;p&gt;LLMs can generate convincing answers that aren't necessarily correct. One common solution is to use another LLM as a judge.&lt;/p&gt;

&lt;p&gt;But running a second generative model for every response adds latency and cost.&lt;/p&gt;

&lt;p&gt;Jev could handle simpler evaluation tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fact-checking:&lt;/strong&gt; Is the generated answer supported by the retrieved context?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety checks:&lt;/strong&gt; Does the response violate a defined policy?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality scoring:&lt;/strong&gt; Does the answer meet a predefined rubric?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can set thresholds to decide what happens next. High-confidence results pass, clear failures get blocked, and uncertain cases go to a stronger model or human reviewer.&lt;/p&gt;

&lt;p&gt;The key benefit is not eliminating evaluation. It's making routine evaluation cheaper and faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Routing Requests to the Right Agent
&lt;/h3&gt;

&lt;p&gt;Multi-agent systems need to decide which agent, tool, or workflow should handle an incoming request.&lt;/p&gt;

&lt;p&gt;A traditional approach is to prompt an LLM to return a category such as &lt;code&gt;billing&lt;/code&gt;, &lt;code&gt;support&lt;/code&gt;, or &lt;code&gt;sales&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Jev can handle this as a classification problem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route requests using predefined categories.&lt;/li&gt;
&lt;li&gt;Avoid generating and parsing unnecessary text.&lt;/li&gt;
&lt;li&gt;Ask a clarifying question when confidence is too low.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially useful when routing sits directly in the request path and every extra millisecond matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Filtering Context in RAG Pipelines
&lt;/h3&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) systems often retrieve documents that look relevant to a query but don't actually help answer it.&lt;/p&gt;

&lt;p&gt;Passing every retrieved chunk to an LLM wastes tokens and can dilute the useful context.&lt;/p&gt;

&lt;p&gt;Jev can score retrieved passages against the user's query before generation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rank chunks by relevance.&lt;/li&gt;
&lt;li&gt;Remove irrelevant or redundant content.&lt;/li&gt;
&lt;li&gt;Send a smaller, more useful context to the generation model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result could be lower inference costs and better answers, provided the scoring model is accurate enough for the task.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Verifying Agent Tool Calls
&lt;/h3&gt;

&lt;p&gt;AI agents can make risky tool calls, repeat the same actions, or get stuck in loops.&lt;/p&gt;

&lt;p&gt;Jev can act as an additional decision layer between an agent and its tools.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Risk checks:&lt;/strong&gt; Should a proposed database operation be allowed?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy checks:&lt;/strong&gt; Does a tool call comply with predefined rules?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop detection:&lt;/strong&gt; Is the agent making progress or repeating previous steps?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can help stop suspicious or unproductive actions before they execute.&lt;/p&gt;

&lt;p&gt;However, an important distinction remains: a model's judgment should not replace deterministic permission checks, sandboxing, or other security controls. Use Jev as an additional layer, not your only line of defense.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Not every AI task needs a generative model.&lt;/p&gt;

&lt;p&gt;Sometimes you don't need an explanation. You need a classification, a score, or a decision that your application can act on immediately.&lt;/p&gt;

&lt;p&gt;That's the interesting idea behind Jev: &lt;strong&gt;separate decision-making from generation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For AI engineers building agents, RAG pipelines, and production workflows, that separation could make systems cheaper, faster, and easier to control.&lt;/p&gt;

&lt;p&gt;The real question isn't whether Jev replaces LLMs. It doesn't.&lt;/p&gt;

&lt;p&gt;It's whether a specialized decision model can handle routine checks better than a general-purpose LLM at the same level of accuracy.&lt;/p&gt;

&lt;p&gt;That's what developers should benchmark before choosing their next AI architecture.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Scored 880 on the Claude Certified Architect Exam. Here's How I Prepared in 2 Weeks</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Thu, 24 Sep 2026 07:42:56 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/i-scored-880-on-the-claude-certified-architect-exam-heres-how-i-prepared-in-2-weeks-16n0</link>
      <guid>https://dev.to/fullstacknrj/i-scored-880-on-the-claude-certified-architect-exam-heres-how-i-prepared-in-2-weeks-16n0</guid>
      <description>&lt;h3&gt;
  
  
  &lt;em&gt;What surprised me, what I actually studied, and why the exam is more about judgment than memorization.&lt;/em&gt;
&lt;/h3&gt;

&lt;h2&gt;
  
  
  880/1000. Two Weeks of Preparation.
&lt;/h2&gt;

&lt;p&gt;Last week, I submitted the final question on Pearson VUE, completed the candidate survey, and waited for the screen to refresh.&lt;/p&gt;

&lt;p&gt;Then my score appeared:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;880 out of 1,000.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The passing score is 720, so there was definitely some relief.&lt;/p&gt;

&lt;p&gt;I had spent roughly two weeks preparing for the &lt;strong&gt;Claude Certified Architect — Foundations (CCAR-F)&lt;/strong&gt; exam, usually 90 minutes to two hours a night.&lt;/p&gt;

&lt;p&gt;Going in, I expected the exam to test how well I knew Anthropic's documentation.&lt;/p&gt;

&lt;p&gt;It did—but not in the way I expected.&lt;/p&gt;

&lt;p&gt;The hardest questions weren't simply about knowing &lt;em&gt;what Claude can do&lt;/em&gt;. They were about deciding &lt;strong&gt;which architectural approach makes the most sense given a specific set of constraints.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what the exam was actually like, how I prepared, and what I would do if I had to prepare again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Took the Exam
&lt;/h2&gt;

&lt;p&gt;AI certifications have exploded over the past year.&lt;/p&gt;

&lt;p&gt;And, honestly, not all of them are particularly useful.&lt;/p&gt;

&lt;p&gt;Many certifications can feel like a collection of multiple-choice questions testing whether you remember definitions, terminology, or product specifications.&lt;/p&gt;

&lt;p&gt;I was interested in the CCAR-F for a different reason.&lt;/p&gt;

&lt;p&gt;Anthropic positioned it as a scenario-based assessment focused on building and reasoning about Claude-powered systems.&lt;/p&gt;

&lt;p&gt;That was relevant to the work I was already doing.&lt;/p&gt;

&lt;p&gt;My team uses &lt;strong&gt;Claude Code, Model Context Protocol (MCP), and the Claude Agent SDK&lt;/strong&gt; for customer-facing workflows and developer tooling. I wanted a structured way to test whether the architectural patterns I was using were actually sound—or whether I was just building prototypes that happened to work.&lt;/p&gt;

&lt;p&gt;So the certification became less about collecting another badge and more about getting an external gut-check on my understanding.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Biggest Surprise: This Isn't Just a Memory Test
&lt;/h2&gt;

&lt;p&gt;The biggest misconception I had going into the exam was that I needed to memorize a lot of documentation.&lt;/p&gt;

&lt;p&gt;Of course, there are things you need to know.&lt;/p&gt;

&lt;p&gt;But memorization alone isn't enough.&lt;/p&gt;

&lt;p&gt;A typical scenario might describe an agent that is consuming too much context, repeatedly calling tools, or producing unreliable outputs.&lt;/p&gt;

&lt;p&gt;Then you're given several possible approaches.&lt;/p&gt;

&lt;p&gt;And here's the interesting part:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More than one answer can look technically reasonable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The challenge is figuring out which answer best addresses the &lt;em&gt;actual constraint&lt;/em&gt; in the scenario.&lt;/p&gt;

&lt;p&gt;Is the problem primarily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost?&lt;/li&gt;
&lt;li&gt;Latency?&lt;/li&gt;
&lt;li&gt;Context usage?&lt;/li&gt;
&lt;li&gt;Reliability?&lt;/li&gt;
&lt;li&gt;Safety?&lt;/li&gt;
&lt;li&gt;Output structure?&lt;/li&gt;
&lt;li&gt;Tool orchestration?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That changes the answer.&lt;/p&gt;

&lt;p&gt;For example, two architectures might both solve a problem. One might introduce additional agents and parallel processing, while another uses a simpler coordinator with structured outputs.&lt;/p&gt;

&lt;p&gt;Neither is inherently wrong.&lt;/p&gt;

&lt;p&gt;But if the scenario emphasizes cost efficiency and predictable execution, adding more agents may introduce unnecessary complexity.&lt;/p&gt;

&lt;p&gt;The question isn't always:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What works?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"What is the simplest approach that satisfies the stated constraints?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction became one of the most important lessons from the exam.&lt;/p&gt;




&lt;h2&gt;
  
  
  I Prepared in Two Weeks
&lt;/h2&gt;

&lt;p&gt;I spent roughly &lt;strong&gt;90 minutes to two hours per night&lt;/strong&gt; for two weeks.&lt;/p&gt;

&lt;p&gt;That worked for me largely because I wasn't starting from zero. I already had practical experience with Claude Code, MCP, and agentic workflows.&lt;/p&gt;

&lt;p&gt;My goal wasn't to read everything Anthropic had ever published.&lt;/p&gt;

&lt;p&gt;It was to identify the major domains, understand the architectural patterns behind them, find my weak spots, and then practice applying them.&lt;/p&gt;

&lt;p&gt;My preparation essentially had four stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand the core architecture.&lt;/li&gt;
&lt;li&gt;Get hands-on with Claude Code and MCP.&lt;/li&gt;
&lt;li&gt;Review context management and structured outputs.&lt;/li&gt;
&lt;li&gt;Practice scenario-based questions under time pressure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hands-on part ended up being more valuable than I expected.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Resources I Actually Used
&lt;/h2&gt;

&lt;p&gt;I deliberately kept the study stack small.&lt;/p&gt;

&lt;p&gt;You don't need 15 courses and six different cheat sheets. You need a few reliable sources and enough practice to recognize architectural patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official Documentation &amp;amp; Learning Portal
&lt;/h3&gt;

&lt;p&gt;Anthropic's official documentation and their &lt;a href="https://anthropic.skilljar.com/?utm_source=gemini" rel="noopener noreferrer"&gt;Skilljar training portal&lt;/a&gt; were my baseline.&lt;/p&gt;

&lt;p&gt;I focused less on memorizing individual API details and more on understanding how the pieces fit together.&lt;/p&gt;

&lt;p&gt;Some areas I paid particular attention to included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic loops&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stop_reason&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tool use&lt;/li&gt;
&lt;li&gt;Context management&lt;/li&gt;
&lt;li&gt;MCP&lt;/li&gt;
&lt;li&gt;Structured outputs&lt;/li&gt;
&lt;li&gt;Claude Code workflows&lt;/li&gt;
&lt;li&gt;Permissions and project configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, understanding the difference between a &lt;code&gt;"tool_use"&lt;/code&gt; and an &lt;code&gt;"end_turn"&lt;/code&gt; &lt;code&gt;stop_reason&lt;/code&gt; is much more useful than simply memorizing that those values exist.&lt;/p&gt;

&lt;p&gt;The important question is what your application should do when each one occurs.&lt;/p&gt;




&lt;h3&gt;
  
  
  Domain Summaries
&lt;/h3&gt;

&lt;p&gt;I also used the &lt;a href="https://anthropic-claude-architect.vercel.app/?utm_source=gemini" rel="noopener noreferrer"&gt;Anthropic Claude Architect Study Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was useful for turning a large amount of documentation into smaller domain-level summaries.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly jumping between documentation pages, I could quickly review the major concepts and then go back to the official documentation when something needed deeper understanding.&lt;/p&gt;

&lt;p&gt;That combination worked well:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary → identify gap → official documentation → hands-on experiment.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Mock Tests
&lt;/h3&gt;

&lt;p&gt;This was probably the most important part of my preparation.&lt;/p&gt;

&lt;p&gt;I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://claudecertificationguide.com/mock-exam/start?utm_source=gemini" rel="noopener noreferrer"&gt;Claude Certification Guide Mock Exam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.certsafari.com/anthropic/claude-certified-architect-foundations?utm_source=gemini" rel="noopener noreferrer"&gt;CertSafari's CCAR-F Practice Tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest benefit wasn't memorizing the answers.&lt;/p&gt;

&lt;p&gt;It was learning how to &lt;strong&gt;read the scenarios&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The questions can be wordy. Instead of trying to hold the entire scenario in my head, I started looking for the core constraint first.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Is this primarily a latency problem?&lt;/p&gt;

&lt;p&gt;Is this a context-management problem?&lt;/p&gt;

&lt;p&gt;Is this a reliability problem?&lt;/p&gt;

&lt;p&gt;Is this a safety problem?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once I started doing that consistently, the answer choices became much easier to evaluate.&lt;/p&gt;




&lt;h2&gt;
  
  
  I Actually Used Claude Code
&lt;/h2&gt;

&lt;p&gt;This was the part of my preparation I found most useful.&lt;/p&gt;

&lt;p&gt;I didn't just read about Claude Code.&lt;/p&gt;

&lt;p&gt;I used it.&lt;/p&gt;

&lt;p&gt;I experimented with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Project-level permissions&lt;/li&gt;
&lt;li&gt;Custom slash commands&lt;/li&gt;
&lt;li&gt;Plan Mode&lt;/li&gt;
&lt;li&gt;Headless workflows&lt;/li&gt;
&lt;li&gt;Local MCP servers&lt;/li&gt;
&lt;li&gt;Tool integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal wasn't to build anything impressive.&lt;/p&gt;

&lt;p&gt;It was to understand how these things behave when you actually use them.&lt;/p&gt;

&lt;p&gt;There's a big difference between reading:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Claude Code can use project instructions through &lt;code&gt;CLAUDE.md&lt;/code&gt;."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and actually creating a &lt;code&gt;CLAUDE.md&lt;/code&gt;, changing the instructions, running Claude Code, and seeing how the behavior changes.&lt;/p&gt;

&lt;p&gt;The latter sticks.&lt;/p&gt;

&lt;p&gt;And when I encountered Claude Code questions during practice, the concepts were much easier to reason about because I'd actually used them.&lt;/p&gt;




&lt;h1&gt;
  
  
  What the Exam Felt Like
&lt;/h1&gt;

&lt;p&gt;The exam consists of &lt;strong&gt;60 scenario-based questions over 120 minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That works out to roughly two minutes per question.&lt;/p&gt;

&lt;p&gt;The time itself wasn't particularly scary.&lt;/p&gt;

&lt;p&gt;The mental load was.&lt;/p&gt;

&lt;p&gt;You're repeatedly given a situation, several constraints, and multiple possible solutions. Then you have to determine which approach best fits the scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Hardest Part: Choosing Between Two Good Answers
&lt;/h3&gt;

&lt;p&gt;This was the part that surprised me most.&lt;/p&gt;

&lt;p&gt;Some questions don't feel like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Right answer vs. obviously wrong answer.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They feel more like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reasonable architecture A vs. reasonable architecture B.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The difference comes down to the constraints.&lt;/p&gt;

&lt;p&gt;Imagine you're designing an agent workflow.&lt;/p&gt;

&lt;p&gt;You could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add another specialized agent.&lt;/li&gt;
&lt;li&gt;Parallelize the work.&lt;/li&gt;
&lt;li&gt;Give the existing agent another tool.&lt;/li&gt;
&lt;li&gt;Introduce structured outputs.&lt;/li&gt;
&lt;li&gt;Change how context is passed between steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Several of these approaches could work.&lt;/p&gt;

&lt;p&gt;But the scenario might specifically require minimizing latency, controlling costs, maintaining strict execution order, or preventing unreliable outputs.&lt;/p&gt;

&lt;p&gt;That constraint should drive the decision.&lt;/p&gt;

&lt;p&gt;This is where I felt the exam was testing &lt;strong&gt;architectural judgment rather than API recall&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Other Surprise: Some Answers Looked Contradictory
&lt;/h2&gt;

&lt;p&gt;I also came across questions where two answers initially seemed almost contradictory.&lt;/p&gt;

&lt;p&gt;For example, one option might suggest using a coordinator agent with structured outputs, while another might use multiple specialized agents working in parallel.&lt;/p&gt;

&lt;p&gt;If you look at the architecture in isolation, both can sound perfectly reasonable.&lt;/p&gt;

&lt;p&gt;But the scenario changes everything.&lt;/p&gt;

&lt;p&gt;The exam forces you to ask:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem are we actually solving?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's an important distinction in real engineering too.&lt;/p&gt;

&lt;p&gt;Good architecture isn't about finding the most sophisticated solution.&lt;/p&gt;

&lt;p&gt;It's about finding the solution that fits the requirements without introducing unnecessary complexity.&lt;/p&gt;




&lt;h1&gt;
  
  
  My 14-Day Preparation Plan
&lt;/h1&gt;

&lt;p&gt;Here's roughly how I divided my preparation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 1–4: Agent SDK &amp;amp; Core Loops
&lt;/h3&gt;

&lt;p&gt;I focused on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic control flow&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stop_reason&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tool execution&lt;/li&gt;
&lt;li&gt;Passing tool results back into conversation state&lt;/li&gt;
&lt;li&gt;Structured outputs&lt;/li&gt;
&lt;li&gt;Common agent-loop failure modes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to understand the mechanics rather than memorize API documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 5–8: Claude Code &amp;amp; MCP
&lt;/h3&gt;

&lt;p&gt;I spent these days actually using Claude Code.&lt;/p&gt;

&lt;p&gt;I experimented with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Permissions&lt;/li&gt;
&lt;li&gt;Plan Mode&lt;/li&gt;
&lt;li&gt;Headless usage&lt;/li&gt;
&lt;li&gt;Custom commands&lt;/li&gt;
&lt;li&gt;MCP servers&lt;/li&gt;
&lt;li&gt;Tool configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was deliberately hands-on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 9–11: Context Management &amp;amp; Structured Outputs
&lt;/h3&gt;

&lt;p&gt;I reviewed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-context strategies&lt;/li&gt;
&lt;li&gt;Chunking&lt;/li&gt;
&lt;li&gt;Summarization&lt;/li&gt;
&lt;li&gt;Context degradation&lt;/li&gt;
&lt;li&gt;JSON Schema&lt;/li&gt;
&lt;li&gt;Output validation&lt;/li&gt;
&lt;li&gt;Failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part here was understanding &lt;strong&gt;when&lt;/strong&gt; to use each strategy rather than simply knowing that it exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Days 12–14: Timed Practice
&lt;/h3&gt;

&lt;p&gt;The final few days were mostly mock tests and scenario drills.&lt;/p&gt;

&lt;p&gt;I started paying less attention to whether I remembered a specific fact and more attention to whether I could identify the &lt;strong&gt;primary constraint&lt;/strong&gt; quickly.&lt;/p&gt;

&lt;p&gt;That became my main exam strategy.&lt;/p&gt;




&lt;h1&gt;
  
  
  6 Things I'd Do If I Prepared Again
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. Build a One-Page Summary for Each Domain
&lt;/h3&gt;

&lt;p&gt;Don't try to memorize the entire documentation.&lt;/p&gt;

&lt;p&gt;For each domain, write down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core concepts&lt;/li&gt;
&lt;li&gt;Important architectural patterns&lt;/li&gt;
&lt;li&gt;Common failure modes&lt;/li&gt;
&lt;li&gt;Key trade-offs&lt;/li&gt;
&lt;li&gt;When to use each approach&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can't explain a domain in your own words, you probably don't understand it deeply enough yet.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Practice Reading the Constraint First
&lt;/h3&gt;

&lt;p&gt;This was probably the most useful change I made.&lt;/p&gt;

&lt;p&gt;When I saw a scenario, I started asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the constraint?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cost?&lt;/p&gt;

&lt;p&gt;Latency?&lt;/p&gt;

&lt;p&gt;Reliability?&lt;/p&gt;

&lt;p&gt;Context?&lt;/p&gt;

&lt;p&gt;Safety?&lt;/p&gt;

&lt;p&gt;Output format?&lt;/p&gt;

&lt;p&gt;Once you identify that, the architecture becomes easier to reason about.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Don't Treat Every Question Like a Documentation Lookup
&lt;/h3&gt;

&lt;p&gt;You won't necessarily recognize every question from something you've read.&lt;/p&gt;

&lt;p&gt;Instead, understand the underlying principle.&lt;/p&gt;

&lt;p&gt;If you understand why an architecture works, you can reason through a new scenario.&lt;/p&gt;

&lt;p&gt;If you've only memorized a documentation page, you're in trouble as soon as the question is phrased differently.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Get Hands-On With Claude Code
&lt;/h3&gt;

&lt;p&gt;Don't just read about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Permissions&lt;/li&gt;
&lt;li&gt;MCP&lt;/li&gt;
&lt;li&gt;Plan Mode&lt;/li&gt;
&lt;li&gt;Tools&lt;/li&gt;
&lt;li&gt;Headless workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use them.&lt;/p&gt;

&lt;p&gt;Break things.&lt;/p&gt;

&lt;p&gt;Change configurations.&lt;/p&gt;

&lt;p&gt;See what happens.&lt;/p&gt;

&lt;p&gt;Practical experience makes abstract concepts much easier to recall.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Practice With a Timer
&lt;/h3&gt;

&lt;p&gt;The exam gives you enough time, but you don't want to spend five minutes debating one question.&lt;/p&gt;

&lt;p&gt;I found timed practice useful because it forced me to make architectural decisions without endlessly second-guessing myself.&lt;/p&gt;

&lt;p&gt;I'd also recommend doing multiple practice runs rather than stopping after your first passing score.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Don't Overcomplicate the Architecture
&lt;/h3&gt;

&lt;p&gt;This is probably the lesson that extends beyond the certification.&lt;/p&gt;

&lt;p&gt;When two approaches seem viable, don't automatically choose the more sophisticated one.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is the simplest architecture that satisfies the requirements?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More agents aren't automatically better.&lt;/p&gt;

&lt;p&gt;More tools aren't automatically better.&lt;/p&gt;

&lt;p&gt;More context isn't automatically better.&lt;/p&gt;

&lt;p&gt;More abstraction isn't automatically better.&lt;/p&gt;

&lt;p&gt;Sometimes the best architectural decision is simply not adding another moving part.&lt;/p&gt;




&lt;h1&gt;
  
  
  Who Should Consider Taking It?
&lt;/h1&gt;

&lt;p&gt;I wouldn't recommend this certification to everyone who uses Claude.&lt;/p&gt;

&lt;p&gt;It makes more sense if your work involves actually designing or implementing AI-powered systems.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Software engineers building Claude-powered applications&lt;/li&gt;
&lt;li&gt;Technical leads&lt;/li&gt;
&lt;li&gt;Solution architects&lt;/li&gt;
&lt;li&gt;Engineers implementing agentic workflows&lt;/li&gt;
&lt;li&gt;Developers working with MCP&lt;/li&gt;
&lt;li&gt;Teams adopting Claude Code across engineering workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're primarily using Claude for writing, brainstorming, research, or everyday productivity, the certification may not provide the same practical value.&lt;/p&gt;

&lt;p&gt;In that case, simply becoming better at using the product may be more useful than preparing for an architecture exam.&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Actually Got Out of It
&lt;/h1&gt;

&lt;p&gt;The digital badge is nice.&lt;/p&gt;

&lt;p&gt;The 880 looks nice on paper too.&lt;/p&gt;

&lt;p&gt;But neither was the most valuable part.&lt;/p&gt;

&lt;p&gt;The useful part was spending two weeks deliberately thinking about architecture.&lt;/p&gt;

&lt;p&gt;The preparation forced me to revisit concepts I had used casually and ask why I was using them.&lt;/p&gt;

&lt;p&gt;It made me think more carefully about context, tool orchestration, agent boundaries, structured outputs, and failure modes.&lt;/p&gt;

&lt;p&gt;More importantly, it reinforced a principle that applies well beyond Claude:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Good architecture isn't about using the most advanced technology. It's about making the right trade-offs for the problem you're actually solving.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I went into the exam expecting to validate how much Claude I knew.&lt;/p&gt;

&lt;p&gt;I came out thinking more about &lt;strong&gt;how I make engineering decisions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And for me, that's probably the most valuable thing I got from the certification.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>architecture</category>
      <category>certification</category>
    </item>
    <item>
      <title>What is AEO? A Beginner’s Guide to Answer Engine Optimization</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Wed, 23 Sep 2026 05:23:21 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/what-is-aeo-a-beginners-guide-to-answer-engine-optimization-1aff</link>
      <guid>https://dev.to/fullstacknrj/what-is-aeo-a-beginners-guide-to-answer-engine-optimization-1aff</guid>
      <description>&lt;p&gt;keyTakeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'AEO (Answer Engine Optimization) is the process of structuring content so AI answer engines (ChatGPT, Perplexity, Google AI Overviews) can easily understand and cite it.'&lt;/li&gt;
&lt;li&gt;'Traditional SEO targets search engine ranking pages, whereas AEO targets being synthesized directly into AI generated answers.'&lt;/li&gt;
&lt;li&gt;'Modern users search in complete conversational queries rather than fragmented keywords, demanding direct, factual, and high-density answers.'&lt;/li&gt;
&lt;li&gt;'AEO does not replace SEO it builds on technical SEO, semantic clarity, and authoritative structured data to make content machine-understandable.'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You probably have heard of &lt;strong&gt;SEO (Search Engine Optimization)&lt;/strong&gt;. For decades, it has been the standard playbook for getting your website discovered on search engines.&lt;/p&gt;

&lt;p&gt;But now there is another term rapidly taking center stage: &lt;strong&gt;AEO, or Answer Engine Optimization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So what is AEO, exactly—and why are businesses and creators' attention is increasing towards it?&lt;/p&gt;

&lt;h2&gt;
  
  
  AEO Briefly: What Is It?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AEO (Answer Engine Optimization)&lt;/strong&gt; is the process of creating and structuring your content in a way that AI tools and answer engines can easily understand, extract, and utilize when answering people's questions.&lt;/p&gt;

&lt;p&gt;Here is the fundamental difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traditional SEO&lt;/strong&gt; is about getting your website to show up on Google when someone searches for a query.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AEO&lt;/strong&gt; is about making your content the &lt;strong&gt;direct answer&lt;/strong&gt; when someone asks ChatGPT, Gemini, Perplexity, Google AI Overviews, or another AI powered search tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A Concrete Example
&lt;/h3&gt;

&lt;p&gt;Consider how someone searches for business software:&lt;/p&gt;

&lt;p&gt;In traditional search, someone might type a short keyword into Google:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best CRM for a small business"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Traditional SEO&lt;/strong&gt; tries to get your website onto the first page of Google search results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AEO&lt;/strong&gt; asks a fundamentally different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Will an AI have enough structured, reliable knowledge of my website to answer this question and cite our brand?”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Do AEO?
&lt;/h2&gt;

&lt;p&gt;The simple answer is that &lt;strong&gt;people search differently today&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of typing a few keywords into a search bar, people are increasingly asking AI tools complete, nuanced questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"What's the best CRM for a startup of 10 people?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"How do I make a SaaS landing page that converts?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What project management software should I use for a remote design team?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AI Understands Intent, Not Just Keywords
&lt;/h3&gt;

&lt;p&gt;Artificial intelligence systems do not simply look for web pages that contain an exact keyword match. They comprehend the question, retrieve relevant information across sources, and &lt;strong&gt;synthesize an answer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means businesses need to think beyond ranking for keywords.&lt;/p&gt;

&lt;p&gt;They also need to make their content easy for machines to &lt;strong&gt;understand&lt;/strong&gt;, &lt;strong&gt;trust&lt;/strong&gt;, and &lt;strong&gt;reference&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  AEO vs. SEO: How They Compare
&lt;/h2&gt;

&lt;p&gt;The easiest way to think about the distinction is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SEO&lt;/strong&gt;: Helps search engines &lt;strong&gt;find and rank&lt;/strong&gt; your content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AEO&lt;/strong&gt;: Helps answer engines &lt;strong&gt;understand and use&lt;/strong&gt; your content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are not replacements for each other. In fact, good AEO usually starts with good SEO: useful content, clear structure, strong technical foundations, and trustworthy information.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Traditional SEO&lt;/th&gt;
&lt;th&gt;Answer Engine Optimization (AEO)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Platform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google, Bing, Yahoo&lt;/td&gt;
&lt;td&gt;ChatGPT, Perplexity, Google AI Overviews, Claude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User Experience&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scrolling lists of blue links and clicking websites&lt;/td&gt;
&lt;td&gt;Reading a synthesized answer with source citation tags&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query Style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keyword-centric (&lt;em&gt;"best CRM small business"&lt;/em&gt;)&lt;/td&gt;
&lt;td&gt;Conversational questions (&lt;em&gt;"What's the best CRM for a 10-person startup?"&lt;/em&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Core Metric&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SERP rankings, organic impressions, CTR&lt;/td&gt;
&lt;td&gt;AI citation frequency, generative share of voice, direct conversions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Content Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long-form articles optimized for keyword density&lt;/td&gt;
&lt;td&gt;High-density declarative answers, bulleted facts, and structured schema&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How Do You Optimize for AEO?
&lt;/h2&gt;

&lt;p&gt;There isn't a magic "AEO button" you can toggle on. But you can start by mastering the fundamentals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Answer real questions your customers ask&lt;/strong&gt;: Pay attention to the exact language and questions your customers use in sales calls, support tickets, and community discussions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write clear, direct answers&lt;/strong&gt;: Put the direct answer right at the top of your section before expanding into supporting context. If an AI engine cannot find the core answer immediately, it moves to another source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use descriptive headings and structured content&lt;/strong&gt;: Organize your articles with clear &lt;code&gt;H2&lt;/code&gt; and &lt;code&gt;H3&lt;/code&gt; questions, bulleted lists, and clean comparison tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explain concepts in simple language&lt;/strong&gt;: Avoid dense marketing buzzwords or corporate jargon. Clear, factual statements are much easier for LLM chunkers to extract accurately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep important information easy to find&lt;/strong&gt;: Put key data points, pricing details, specifications, and steps front and center.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build credibility with original data and expertise&lt;/strong&gt;: AI engines prioritize reliable sources. Back your insights with original research, case study findings, and experienced perspectives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep your website technically accessible&lt;/strong&gt;: Ensure search engines and AI crawlers (like GPTBot and PerplexityBot) can index your pages, and provide clean Schema.org structured data (such as &lt;code&gt;Article&lt;/code&gt;, &lt;code&gt;FAQPage&lt;/code&gt;, and &lt;code&gt;Product&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;The goal of AEO isn't to write robotic copy for AI bots.&lt;/p&gt;

&lt;p&gt;The goal is to make your content &lt;strong&gt;so clear and useful that both humans and machines can understand it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that's ultimately what AEO is all about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SEO helps people find your content. AEO helps answer engines understand and recommend it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>aeo</category>
      <category>marketing</category>
    </item>
    <item>
      <title>Code Is Cheap. Software Isn’t.</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:31:05 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/new-editing-5ego</link>
      <guid>https://dev.to/fullstacknrj/new-editing-5ego</guid>
      <description>&lt;p&gt;&lt;em&gt;AI has made writing code incredibly cheap. But building software that can survive change, scale, and someone else’s bad decisions is still engineering.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A founder told me this while negotiating a contract.&lt;/p&gt;

&lt;p&gt;His argument was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If we have AI to generate code, why should we pay for a developer’s hours?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He said code had become cheap to write. He only wanted a working MVP. He didn’t care about code quality.&lt;/p&gt;

&lt;p&gt;I hesitated.&lt;/p&gt;

&lt;p&gt;And he didn’t sign the SOW.&lt;/p&gt;

&lt;p&gt;At first, I thought it was a fair question.&lt;/p&gt;

&lt;p&gt;Then the product engineer in me remembered the last project where we had to rebuild a broken app because the previous agency couldn’t maintain it.&lt;/p&gt;

&lt;p&gt;Most of the code was AI-generated.&lt;/p&gt;

&lt;p&gt;Random directory structures. Files and functions that didn’t quite match. Long, meaningless comments. Weird test cases. Logic scattered across the codebase with no obvious reason why.&lt;/p&gt;

&lt;p&gt;While rebuilding it, we realized just how expensive bad code actually is.&lt;/p&gt;

&lt;p&gt;And nobody understands this better than a burnt-out founder or a CTO who has inherited a codebase where every seemingly simple change turns into a mini archaeological expedition.&lt;/p&gt;

&lt;p&gt;But from a founder’s perspective, all of this sounds like technical jargon.&lt;/p&gt;

&lt;p&gt;Clean Code. System Design. Architecture. Domain language. TDD.&lt;/p&gt;

&lt;p&gt;How do you explain the value of all that to someone who just wants the product shipped?&lt;/p&gt;

&lt;p&gt;I tried to explain it like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI has made generating code cheap. It hasn’t made building software cheap.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Writing a few thousand lines of code is easy.&lt;/p&gt;

&lt;p&gt;Building a system where those thousands of lines continue to make sense six months later is a different problem.&lt;/p&gt;

&lt;p&gt;It’s like building a house.&lt;/p&gt;

&lt;p&gt;Having AI generate bricks faster doesn’t eliminate the need for a blueprint, structural design, foundations, plumbing, or someone who understands how the whole thing fits together.&lt;/p&gt;

&lt;p&gt;The fundamentals of software engineering haven’t disappeared.&lt;/p&gt;

&lt;p&gt;If anything, they matter more now.&lt;/p&gt;

&lt;p&gt;Because the bottleneck has moved.&lt;/p&gt;

&lt;p&gt;The most draining part of building with AI agents isn’t writing code anymore.&lt;/p&gt;

&lt;p&gt;It’s keeping the agents in sync.&lt;/p&gt;

&lt;p&gt;You need a shared system design.&lt;/p&gt;

&lt;p&gt;A shared language for the product and its domain.&lt;/p&gt;

&lt;p&gt;Clear boundaries around what each part of the system is supposed to do.&lt;/p&gt;

&lt;p&gt;And increasingly, you need a leash.&lt;/p&gt;

&lt;p&gt;That’s where practices like test-driven development become interesting in the age of AI agents.&lt;/p&gt;

&lt;p&gt;Tests aren’t just there to catch bugs.&lt;/p&gt;

&lt;p&gt;They become guardrails for agents that can otherwise happily run in ten different directions.&lt;/p&gt;

&lt;p&gt;The irony is that AI can make a bad engineer dramatically faster at producing bad code.&lt;/p&gt;

&lt;p&gt;It can also make a good engineer dramatically faster at building great software.&lt;/p&gt;

&lt;p&gt;The difference isn’t the cost of generating the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The difference is who is responsible for the system.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>Copilot DEVTO Strict Live Test 2026-09-03</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Thu, 03 Sep 2026 03:28:29 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/copilot-devto-strict-live-test-2026-09-03-611</link>
      <guid>https://dev.to/fullstacknrj/copilot-devto-strict-live-test-2026-09-03-611</guid>
      <description>&lt;h1&gt;
  
  
  DEVTO Strict Live Test
&lt;/h1&gt;

&lt;p&gt;Testing strict live mode without fallback.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloudflare</category>
    </item>
    <item>
      <title>Bharat general elections 2024 and the paradox of success</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Sun, 05 May 2024 13:00:04 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/bharat-general-elections-2024-and-the-paradox-of-success-178e</link>
      <guid>https://dev.to/fullstacknrj/bharat-general-elections-2024-and-the-paradox-of-success-178e</guid>
      <description>&lt;p&gt;I will be 28 years old by the end of this year i.e. 2024. And by no measure, do I consider myself a successful person. Success as we all know is a relative metric. For a poor beggar it is to beg a day enough to survive the day, for a rickshaw driver success is to make enough money to provide for the family, for an aspiring youth it is to get a job, for a corporate employee it is to become the boss, for the boss success is well to become a super boss and so on.  &lt;/p&gt;

&lt;p&gt;Do you see a pattern? Success gets redefined every time we achieve it and it’s like a never-ending path that we embark on from the moment we are born.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;But, what is common between Bharat elections this year and the paradox of&lt;/strong&gt;&lt;/em&gt;  &lt;em&gt;&lt;strong&gt;success?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before, getting to the elections I would like to talk about the “Paradox of success”. Most of us believe that becoming successful will make us happy, and feel respected and loved by the people around us. To be honest it often does but success also entails ‘ENVY’.  The very feeling that makes childhood friends writing an exam bitter when results are declared, despises the person doing well or working hard in life. Sometimes, you don’t even have to be successful to feel the bitterness and jealousy from such people around you just a little spark, a small step towards that path is enough. I know it exists because I’ve felt it throughout my school days, college days, and corporate journey and you must have too!&lt;/p&gt;

&lt;p&gt;Too much or even too little success can break life-long friendships, and families, jeopardize your career, and make you a lonely person wondering what went wrong. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Trust me if you value or crave certain people in life, it’s better to avoid success or to hide it from them.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As we all hear that Bharat is a developing country, she is working hard to match global standards of living, healthcare, infrastructure, military &amp;amp; defense, manufacturing &amp;amp; services, etc.&lt;/p&gt;

&lt;p&gt;Bharat is a nation aspiring to share the table with developed nations. A patriot (or a naive) person like me would think that nations sitting at the top will lend a hand and help us reach there. But is that the case?  Who will benefit from having another developed nation on the earth? What does Bharat has to offer to the world? These are questions raised when someone talks about a developed and prosperous Bharat. Now, who might ask such questions? &lt;em&gt;&lt;strong&gt;You can take a guess, someone who is envious and afraid of our progress.&lt;/strong&gt;&lt;/em&gt; These people are present both inside and outside the Bharat. &lt;/p&gt;

&lt;p&gt;It saddens me and at the same time makes me chuckle when I see rising hate for my nation. A nation that just wants to elevate its citizens. This hate only gets worse with time. When a 3rd world country filled with poor and snake charmers suddenly comes out and helps other nations during a pandemic. When it decides to take a stand for itself and push back the terrorism. &lt;/p&gt;

&lt;p&gt;The propaganda and false narratives are at their peak against my nation. The attempts to tarnish Bharat’s achievement in the last 10 years are rampant. These attacks against our sovereignty are launched by both internal and external actors. What does it signify? Why a democratic country is constantly targeted by a dictator-run country or a deep state-run country?&lt;/p&gt;

&lt;p&gt;I think the answer is simple, “Paradox of success” i.e. &lt;em&gt;&lt;strong&gt;envy. Envy that Bharat might become better than them.&lt;/strong&gt;&lt;/em&gt; Everyone loved Bharat when we were weak and poor. The moment we started walking the path of progress, that love started to fade, we were still too far so the hatred was hidden but it always existed. As we are getting closer and closer to our goals the fear and the jealousy among the peer nations are also peaking. Ladies and gentlemen, Bharat General Election 2024 is that crucial step that will catapult us to a new trajectory, and of course, some developed nations will not like it. &lt;/p&gt;

&lt;p&gt;I don’t know the answer to this paradox or rather human nature of enviousness but my guess is it is all because of evolution and conditioning that life is a zero-sum game. I’m most certainly sure that it is not.&lt;/p&gt;

&lt;p&gt;The lesson is simple: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Every time someone sneers at you, tries to belittle you, just smile and tell yourself, “I’m most certainly on the right path to success &amp;amp; start running on that path.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>[React Native Guide 2024] Part 1: Builds and flavors.</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Tue, 23 Apr 2024 04:10:06 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/react-native-guide-2024-part-1-builds-and-flavors-1571</link>
      <guid>https://dev.to/fullstacknrj/react-native-guide-2024-part-1-builds-and-flavors-1571</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“&lt;em&gt;Before building an actual rocket, one should build a prototype. Before experimenting on the actual rocket, one should experiment on the prototype.&lt;/em&gt;” - not elon musk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: &lt;code&gt;react-native-config&lt;/code&gt; breaks with latesst  react-native 0.74&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/fullstackNRJ/rn-setup-2024" rel="noopener noreferrer"&gt;Source code&lt;/a&gt; for the impatients.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost all of the web apps I have ever worked on had some sort of dev/prod parity setup. The larger teams and codebases even had more build types like local, QA, preprod etc. And it does make  sense to separate out your main build from the one being actively developed. It is also in conjecture with &lt;a href="https://12factor.net/" rel="noopener noreferrer"&gt;12 factor app&lt;/a&gt; philosophy.&lt;/p&gt;

&lt;p&gt;In the mobile apps world, we follow something similar called build variants. If you’re not aware of it please read &lt;a href="https://developer.android.com/build" rel="noopener noreferrer"&gt;this &lt;/a&gt;blog first. It explains &lt;code&gt;buildtypes&lt;/code&gt; and &lt;code&gt;productflavors&lt;/code&gt; in detail. To put it in simple words. We have something called Build types, Product flavors cross product of the two gives us Build variants. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 BuildTypes * ProductFlavors = BuildVariants&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The way it works in react native is also similar, we define buildTypes and productFlavor in &lt;em&gt;app/build.gradle&lt;/em&gt; file. BuildTypes usually represent debug and release mode bundle whereas ProductFlavor is further divided into two more axis.&lt;br&gt;
One axis is our &lt;em&gt;environments&lt;/em&gt; like &lt;strong&gt;local, dev, qa, test, prod,&lt;/strong&gt; etc. and the other one &lt;em&gt;flavorDimensions, which&lt;/em&gt; is optional but useful in apps that have for ex. free and pro versions with almost similar code, or uber like separate apps for the riders and the drivers. You can enable flavors and write conditional code which gets built and compiled based on productflavors and flavorDimensions. &lt;/p&gt;

&lt;p&gt;Now that we’re clear about build types and product flavors let’s set it up in a new RN project. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create a new RN project using React-native cli.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; npx react-native@0.73.6 init MyApp &lt;span class="nt"&gt;--version&lt;/span&gt; 0.73.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Install&lt;/strong&gt; &lt;em&gt;&lt;strong&gt;react-native-config&lt;/strong&gt;&lt;/em&gt; &lt;strong&gt;package&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;MyApp &lt;span class="k"&gt;**&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;**&lt;/span&gt;  npm i react-native-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Define config for the build types, product Flavors in app/build.gradle.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Add the following lines in the same file in the defaultConfig block. This will be applied to all the&lt;/p&gt;

&lt;p&gt;buildVarirants and we can also override these values.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;
 &lt;span class="n"&gt;defaultConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"build_config_package"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"com.myapp"&lt;/span&gt;
        &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"build_config_package"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"com.myapp"&lt;/span&gt;
        &lt;span class="n"&gt;applicationId&lt;/span&gt; &lt;span class="s2"&gt;"com.mmadmin"&lt;/span&gt;
        &lt;span class="n"&gt;minSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minSdkVersion&lt;/span&gt;
        &lt;span class="n"&gt;targetSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;targetSdkVersion&lt;/span&gt;
        &lt;span class="n"&gt;versionCode&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"VERSION_CODE"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toInteger&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;versionName&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"VERSION_NAME"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;b. You’ll notice buildTypes already exists. You can add/edit the configuration related to the specific bundle for ex. enableHermes option or enable source map. We’ll leave it as it is for now.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;buildTypes&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Caution! In production, you need to generate your own keystore file.&lt;/span&gt;
            &lt;span class="c1"&gt;// see https://reactnative.dev/docs/signed-apk-android.&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;
            &lt;span class="n"&gt;minifyEnabled&lt;/span&gt; &lt;span class="n"&gt;enableProguardInReleaseBuilds&lt;/span&gt;
            &lt;span class="n"&gt;proguardFiles&lt;/span&gt; &lt;span class="nf"&gt;getDefaultProguardFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"proguard-android.txt"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;"proguard-rules.pro"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;c. Let’s now define flavorDimensions and productFlavors. Since, we need only one app we will use &lt;code&gt;default&lt;/code&gt; as flavorDismension. But we need 4 productFlavors local, dev, qa, and prod hence we add four blocks with some values. We’re overriding &lt;code&gt;app_name&lt;/code&gt; and adding applicationIdSuffix and versionNameSuffix for each flavor. This will help us differentiate between apps and generate different buildVariants. Helps with testing on the same device or simulator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;flavorDimensions&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
    &lt;span class="n"&gt;productFlavors&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;local&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app_name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"MyApp Debug"&lt;/span&gt;
            &lt;span class="n"&gt;applicationIdSuffix&lt;/span&gt; &lt;span class="s1"&gt;'.debug'&lt;/span&gt;
            &lt;span class="n"&gt;versionNameSuffix&lt;/span&gt; &lt;span class="s2"&gt;"-DEBUG"&lt;/span&gt;
            &lt;span class="n"&gt;minSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minSdkVersion&lt;/span&gt;
            &lt;span class="n"&gt;targetSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;targetSdkVersion&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app_name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"MyApp Dev"&lt;/span&gt;
            &lt;span class="n"&gt;applicationIdSuffix&lt;/span&gt; &lt;span class="s1"&gt;'.dev'&lt;/span&gt;
            &lt;span class="n"&gt;versionNameSuffix&lt;/span&gt; &lt;span class="s2"&gt;"-DEV"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;versionBuild&lt;/span&gt;
            &lt;span class="n"&gt;minSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minSdkVersion&lt;/span&gt;
            &lt;span class="n"&gt;applicationId&lt;/span&gt; &lt;span class="s2"&gt;"com.reactnativeproject.stage"&lt;/span&gt;
            &lt;span class="n"&gt;targetSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;targetSdkVersion&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;qa&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app_name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"MyApp Qa"&lt;/span&gt;
            &lt;span class="n"&gt;applicationIdSuffix&lt;/span&gt; &lt;span class="s1"&gt;'.qa'&lt;/span&gt;
            &lt;span class="n"&gt;versionNameSuffix&lt;/span&gt; &lt;span class="s2"&gt;"-QA"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;versionBuild&lt;/span&gt;
            &lt;span class="n"&gt;minSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minSdkVersion&lt;/span&gt;
            &lt;span class="n"&gt;applicationId&lt;/span&gt; &lt;span class="s2"&gt;"com.reactnativeproject.stage"&lt;/span&gt;
            &lt;span class="n"&gt;targetSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;targetSdkVersion&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;prod&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;resValue&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app_name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"MyApp"&lt;/span&gt;
            &lt;span class="n"&gt;minSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minSdkVersion&lt;/span&gt;
            &lt;span class="n"&gt;applicationId&lt;/span&gt; &lt;span class="s2"&gt;"com.reactnativeproject.prod"&lt;/span&gt;
            &lt;span class="n"&gt;targetSdkVersion&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;targetSdkVersion&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:  Setup environments&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create your environment files like .env.local, .env.dev, .env.prod files and add the keys.&lt;/li&gt;
&lt;li&gt;Update &lt;em&gt;&lt;strong&gt;app/build.gradle&lt;/strong&gt;&lt;/em&gt; file with the following code at the beginning of the file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;
&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;envConfigFiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="nl"&gt;localdebug:&lt;/span&gt;&lt;span class="s2"&gt;".env.local"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;localrelease&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;".env.local"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;devdebug:&lt;/span&gt; &lt;span class="s2"&gt;".env.dev"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;devrelease:&lt;/span&gt; &lt;span class="s2"&gt;".env.dev"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;qadebug:&lt;/span&gt;&lt;span class="s1"&gt;'.env.qa'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;qarelease:&lt;/span&gt;&lt;span class="s1"&gt;'.env.qa'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;proddebug:&lt;/span&gt;&lt;span class="s1"&gt;'.env.prod'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;prodrelease:&lt;/span&gt;&lt;span class="s1"&gt;'.env.prod'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;apply&lt;/span&gt; &lt;span class="nl"&gt;from:&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;':react-native-config'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;projectDir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPath&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/dotenv.gradle"&lt;/span&gt;
&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;versionBuild&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BUILD_NUMBER'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"+"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BUILD_NUMBER'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we have different combinations for buildTypes and productFlavors like &lt;em&gt;productFlavorbuildTypes&lt;/em&gt;. So, every productFlavor has two buildTypes debug and release.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Important, thing here is to match the buildVaraint name with the correct .env file.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we can access our variables inside the react components&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;HomeScreen&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="na"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;ENVIROMENT&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENVIROMENT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:::&lt;/span&gt; &lt;span class="nx"&gt;APP_ID&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Go to Details&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;onPress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Stack_Details&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also access them inside the &lt;em&gt;&lt;strong&gt;build.gradle&lt;/strong&gt;&lt;/em&gt; file ex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;versionCode&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"VERSION_CODE"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;toInteger&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access env variables inside android .java/.kt files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="no"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BuildConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;API_URL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and inside iOS files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; //import header
#import "ReactNativeConfig.h"
// then read individual key like:
NSString *apiUrl = [ReactNativeConfig envFor:@"API_URL"];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Final Step: Update Package.json with build commands.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, we just need to update scripts to build and run different build variants of our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"android:local"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-native run-android  --mode=localDebug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"android:dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"react-native run-android  --mode=devDebug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd android &amp;amp;&amp;amp; .&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;gradlew assembleProdRelease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release-aab"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd android &amp;amp;&amp;amp; .&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;gradlew bundleProdRelease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd android &amp;amp;&amp;amp; .&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;gradlew assembleDevRelease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release-qa"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cd android &amp;amp;&amp;amp; .&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;gradlew assembleQaRelease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cleanDeps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rm -rf node_modules &amp;amp;&amp;amp; npm i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint ."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-native start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;scripts are modified to run on windows terminal.*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can run the app locally with &lt;code&gt;npm run android:local&lt;/code&gt;, we can generate &lt;code&gt;.apk&lt;/code&gt; for prod, dev, qa with &lt;code&gt;npm run release&lt;/code&gt;, &lt;code&gt;npm run release-dev&lt;/code&gt; , &lt;code&gt;npm run release-qa&lt;/code&gt; respectively. &lt;/p&gt;

&lt;p&gt;And, we can generate &lt;code&gt;.aab&lt;/code&gt; file for playstore submission with  &lt;code&gt;npm run release-aab&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hey, I’m Neeraj Mukta I expertise in crafting resilient apps tailored for startups.  I’ve been crafting web and mobile apps for 8+ years now. If you would like to chat or need assistance with technical problems, feel free to reach out on &lt;a href="https://twitter.com/devnrj07" rel="noopener noreferrer"&gt;X,&lt;/a&gt; &lt;a href="https://www.linkedin.com/in/devnrj07/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Serving React app from S3 bucket using Cloudflare CDN</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Wed, 20 Sep 2023 15:00:17 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/serving-react-app-from-s3-bucket-using-cloudflare-cdn-4d85</link>
      <guid>https://dev.to/fullstacknrj/serving-react-app-from-s3-bucket-using-cloudflare-cdn-4d85</guid>
      <description>&lt;p&gt;The most common way to deploy any static website today is, through AWS. Specifically, S3 bucket in combination with &lt;strong&gt;Certificate Manager&lt;/strong&gt; and &lt;strong&gt;Cloudfront&lt;/strong&gt; services. The combination of these AWS services works well and it's straightforward to set up. However, this may not be the best and easiest solution to host and serve a static website built with frameworks like React, Svelte, or Angular. The major issues in using this combination are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup is not easy, configuring the bucket, then the certificate for SSL, and then creating Cloudfront distribution.&lt;/li&gt;
&lt;li&gt;It becomes expensive as you have to pay for a bucket and CDN service and if you activate WAF that costs you extra. If you have a high-traffic website the costs can rise exponentially.&lt;/li&gt;
&lt;li&gt;There are at least 3 network hops before it reaches the user. It may not add a significant delay but it's absolutely unnecessary.&lt;/li&gt;
&lt;li&gt;There’s no DDoS mitigation system available by default unless we set it up by using another AWS service like AWS Shield or WAF.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fb564328b-0051-4ea8-a5e7-55201819bfe1" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fb564328b-0051-4ea8-a5e7-55201819bfe1" alt="Serving static website with AWS stack" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will look into an alternate way to serve your website securely with an inbuilt &lt;strong&gt;DDoS protection&lt;/strong&gt; and &lt;strong&gt;Bot mitigation system&lt;/strong&gt;. We will use S3 bucket as our primary storage for static files. We will then leverage Cloudflare infrastructure to proxy all the requests to the S3 bucket. By using Cloudflare we get the following advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to set up HTTPS with automatic SSL certificate generation and renewal for our website.&lt;/li&gt;
&lt;li&gt;Low latency CDN network with caching enabled across the globe&lt;/li&gt;
&lt;li&gt;Cost-effective when compared to the AWS system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fbe0b6db1-c47f-4100-aae5-80d4f146cba8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fbe0b6db1-c47f-4100-aae5-80d4f146cba8" alt="An alternate approach to serving S3 bucket content" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;The implementation process can be broken down into three steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Deploy the static files to a S3 bucket&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Assuming you already have a bucket endpoint ready, I will not explain this step in much detail. If you don’t have a bucket ready, follow &lt;a href="https://writernrj.hashnode.dev/deploy-react-app-to-aws-s3-bucket-in-under-5-mins" rel="noopener noreferrer"&gt;this&lt;/a&gt; article to deploy your app to the bucket and enable static hosting.&lt;/p&gt;

&lt;p&gt;Once, you have static hosting enabled in the bucket you’ll get an HTTP endpoint which you use to access your web app. Something like this &lt;code&gt;[http://app.nrj.agency.s3-website.ap-south-1.amazonaws.com](http://app.nrj.agency.s3-website.ap-south-1.amazonaws.com/admin/default)&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Use CloudFlare name servers
&lt;/h3&gt;

&lt;p&gt;Now, we need to delegate the authority to manage DNS records to Cloudflare. This step is fairly simple. You just need to replace the name server in your registrar dashboard with Cloudflare’s provided nameservers. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;CloudFlare account&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Add site&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Copy &lt;strong&gt;name servers&lt;/strong&gt; and paste them into your GoDaddy or whichever DNS provider you use.&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fff4ff1e3-699f-4709-87f8-7a89cfbbb5d1" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fff4ff1e3-699f-4709-87f8-7a89cfbbb5d1" alt="Sample DNS names server page in GoDaddy" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can see all your DNS records in the CloudFlare dashboard. If any of the records are missing please, add them manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5a909b26-5db9-4c2f-90ea-149787f85c13" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5a909b26-5db9-4c2f-90ea-149787f85c13" alt="DNS records in Cloudflare dashboard" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Enable the proxy mode
&lt;/h3&gt;

&lt;p&gt;If you already have a record pointing to your web app, you’ll notice it is also present in the DNS record list. I’m assuming the CNAME record value points to the CloudFront URL. You need to replace this with your bucket's endpoint from step 1. There’s a toggle to switch between a normal DNS record and a proxy. Turn it on, the cloud should become orange. This indicates that all the traffic to this subdomain is routed through the CloudFlare network. Remember to remove the HTTP prefix from the static site URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fbdd9864c-7c21-48fd-b1fe-6c7d6c83d0da" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fbdd9864c-7c21-48fd-b1fe-6c7d6c83d0da" alt="Creating a record in Cloudflare DNS record manager" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You have to manage all your records through cloudflare now. Not all records need to be proxied through CloudFlare. You can add normal records just like you would in any other DNS provider.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try visiting &lt;code&gt;app.yourdomin.com&lt;/code&gt;, (app.nrj.agency in my case) you should see your React app deployed. Check the URL bar it should have an &lt;code&gt;HTTPS&lt;/code&gt; protocol now. This is possible because Cloudflare encrypts the request between the browser and Cloudflare with its own SSL certificate.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffca31df5-704c-42e1-a2bc-1da59c45a2c5" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffca31df5-704c-42e1-a2bc-1da59c45a2c5" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We were able to set up CDN for our S3 bucket in minimum steps. This method of serving content saves time, effort, and money. It also adds an extra layer of safety against common web attacks with zero configuration.&lt;/p&gt;

&lt;p&gt;This method can be used with any similar hosted website be it on Azure or Google Cloud.&lt;/p&gt;

&lt;p&gt;If you found this article helpful. Drop a like and stay tuned for more neat articles.&lt;/p&gt;

&lt;p&gt;This article was published on Medium, Hashnode, Devto using &lt;a href="https://buzpen.com/" rel="noopener noreferrer"&gt;Buzpen&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploy React App to AWS S3 bucket in under 5 mins</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Tue, 19 Sep 2023 15:50:19 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/deploy-react-app-to-aws-s3-bucket-in-under-5-mins-3mi0</link>
      <guid>https://dev.to/fullstacknrj/deploy-react-app-to-aws-s3-bucket-in-under-5-mins-3mi0</guid>
      <description>&lt;p&gt;AWS is the leading Cloud service provider in the world. They offer a variety of services for deploying web applications at scale. These services offload a lot of work that was once required to take any application to production. Traditionally, companies used to have their own servers in their premises to serve their applications to their users. However, with the introduction of cloud-based services, this model has rapidly changed, and more and more companies have moved their infrastructure to the cloud.&lt;/p&gt;

&lt;p&gt;Today, we will look into one such service from AWS called S3 buckets. S3 is shorthand for Simple storage service. It is a service that lets you store files and objects on the cloud.&lt;/p&gt;

&lt;p&gt;From AWS website,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance. Customers of all sizes and industries can use Amazon S3 to store and protect any amount of data for a range of use cases, such as data lakes, websites, mobile applications, backup and restore, archive, enterprise applications, IoT devices, and big data analytics. Amazon S3 provides management features so that you can optimize, organize, and configure access to your data to meet your specific business, organizational, and compliance requirements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why should we use S3 bucket for static site hosting?
&lt;/h2&gt;

&lt;p&gt;S3 is quite a popular service which is widely used all over the world. It is cheap, reliable, and straightforward to set up. It also has the option to enable static hosting on the bucket items.&lt;/p&gt;

&lt;p&gt;Hence, S3 is quite popular when it comes to deploying SPAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before diving into the actual process let’s make sure we have the following things ready:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS accoun&lt;/li&gt;
&lt;li&gt;Static files or the build version or your app. (In most of the react apps it is the build directory)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to deploy your app
&lt;/h2&gt;

&lt;p&gt;Step 1: Search for the S3 bucket in the AWS console. Click on the &lt;code&gt;Create Bucket&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5b704529-0781-4e22-aa03-7b1d30f7df4f" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5b704529-0781-4e22-aa03-7b1d30f7df4f" alt="create_s3_bucket.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Configure your bucket. Give a name to your bucket. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 It is important to note that the bucket name should match the sub domain/ domain name on which you would like this app to be served on. In my case, I’ve got a domain &lt;a href="http://nrj.agency/" rel="noopener noreferrer"&gt;&lt;code&gt;nrj.agency&lt;/code&gt;&lt;/a&gt; but I want to serve it on the &lt;code&gt;app&lt;/code&gt; subdomain. So, I have named my bucket &lt;a href="http://app.nrj.agency/" rel="noopener noreferrer"&gt;&lt;code&gt;app.nrj.agency&lt;/code&gt;&lt;/a&gt; .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have to make our bucket public so that users across the globe can access the files inside it. Acknowledge the warning. Now, the rest of the settings can be left to default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F89bb9ead-6f3d-4f5a-b997-8ec1b1d69a5c" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F89bb9ead-6f3d-4f5a-b997-8ec1b1d69a5c" alt="block_access_1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F658b2465-4b55-4915-a22d-af7fc6a86cf5" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F658b2465-4b55-4915-a22d-af7fc6a86cf5" alt="block_access_2.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you should be able to see the newly created bucket in the Buckets list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F085da3ee-ba27-47c6-bf2d-ac64de8a4513" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F085da3ee-ba27-47c6-bf2d-ac64de8a4513" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Upload Files.&lt;/strong&gt; We can upload files manually by drag and drop or we can use AWS CLI to sync files to our bucket. We will manually put our build folder or the static files in the bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2a1d5628-8e15-4547-bc4f-a0094caa699e" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2a1d5628-8e15-4547-bc4f-a0094caa699e" alt="upload_1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F6fe049f5-f675-48a2-b2ac-cd9e05e939d7" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F6fe049f5-f675-48a2-b2ac-cd9e05e939d7" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Set up a bucket policy.&lt;/strong&gt; This step is crucial and required because it tells AWS that this service will be used only to read the objects from it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2012-10-17&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Statement&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PublicReadGetObject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Effect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Allow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Principal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s3:GetObject&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Resource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arn:aws:s3:::app.nrj.agency/*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Enable static site hosting.&lt;/strong&gt; In the permissions tab scroll to the bottom of the page. Click on the edit button to enable the static site hosting. Put index.html in both boxes as our SPA or react app will handle the errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5cb92018-602f-428e-b4b1-75086dc266ec" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5cb92018-602f-428e-b4b1-75086dc266ec" alt="static_hosting_1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F3298d243-39e3-482d-bac6-1089371d20f1" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F3298d243-39e3-482d-bac6-1089371d20f1" alt="static_hosting_2.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it you can see a URL generated by the AWS which you can use to access your app. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fd18622e2-d283-4e47-bcca-14d39a52c426" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fd18622e2-d283-4e47-bcca-14d39a52c426" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F60bf9033-9bea-4e20-83dc-4bbf64a381ea" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F60bf9033-9bea-4e20-83dc-4bbf64a381ea" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Notice it has HTTP, not HTTPS protocol. This is because S3 doesn’t support it. We need to set up other services to get an SSL certificate and serve it through CDN via HTTPS protocol.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check out my other blog which tells you how to do this with CloudFlare CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog, we learned how to host static files using an S3 bucket in under 5 mins. All the steps described here can be followed easily.&lt;/p&gt;

&lt;p&gt;If you found this article, give it a thumbs up and share with your friends.&lt;/p&gt;

&lt;p&gt;This article was published on Medium, Devto, and Hashnode using &lt;a href="https://buzpen.com/" rel="noopener noreferrer"&gt;Buzpen&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Setting up a reverse proxy with CloudFlare workers</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Fri, 08 Sep 2023 23:21:09 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/setting-up-a-reverse-proxy-with-cloudflare-workers-16ki</link>
      <guid>https://dev.to/fullstacknrj/setting-up-a-reverse-proxy-with-cloudflare-workers-16ki</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What is a reverse proxy in the first place?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In layman's terms, it is a middleman sitting between two parties to make transactions between them smoother, faster, and more secure. Think of a waiter in a busy restaurant. The job of a waiter is to take orders from you and pass them to the kitchen staff and when your order is ready, serve the food from the kitchen to your table. As you can tell, you really don’t have to do much at a restaurant. All the hard work of communication and serving the food is handled by the waiter, here the waiter is acting as a &lt;strong&gt;middleman&lt;/strong&gt; or &lt;strong&gt;reverse proxy&lt;/strong&gt; between you and the chef.&lt;/p&gt;

&lt;p&gt;If we apply this analogy to the digital world, a reverse proxy is a &lt;strong&gt;server&lt;/strong&gt;&amp;nbsp;between your clients (browser, mobile app etc.) and &lt;strong&gt;web servers&lt;/strong&gt;. It can intercept the requests from the client before it reaches the server. This in turn opens a lot of opportunities for improving web server’s characteristics. Just as the waiter in a restaurant takes orders and serves food. It also takes care of billing and payments, managing multiple customers at the same time, managing crow during rush hours etc. A reverse proxy server can also do similar tasks in the internet world like &lt;strong&gt;balancing traffic&lt;/strong&gt; between multiple servers, mitigating &lt;strong&gt;risky behaviors,&lt;/strong&gt; and &lt;strong&gt;caching&lt;/strong&gt; the responses for the same queries.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt;, our goal for using a reverse proxy is different.&amp;nbsp; We want to perform redirects between our websites. In this case, I’ve three websites &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a&lt;/strong&gt;. &lt;strong&gt;Main landing page&lt;/strong&gt; which I want to point to &lt;code&gt;kanvasai.com&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. Medium integration page&lt;/strong&gt; which I want to point to &lt;code&gt;kanvasai.com/medium&lt;/code&gt; followed by my app’s query parameters like &lt;code&gt;_?utm_source=&amp;amp;page=&lt;/code&gt;_&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Dev. to integration page&lt;/strong&gt; again kanvasai.com/devto&lt;code&gt;followed by my app’s query parameters like _&lt;/code&gt;?utm_source=&amp;amp;page=`_&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2499291f-1cce-4a69-87cc-5af389b0d57f" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2499291f-1cce-4a69-87cc-5af389b0d57f" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the sake of brevity all there websites are hosted on &lt;a href="http://webflow.io/" rel="noopener noreferrer"&gt;webflow.io&lt;/a&gt; and these are records on my GoDaddy DNS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffae7add9-93fc-4fe0-915d-c50d20fd8dde" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffae7add9-93fc-4fe0-915d-c50d20fd8dde" alt="DNS records, Godaddy.com" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice, that I created three records (main, medium, devto) with CNAME pointing to a non-ssl server of &lt;a href="http://webflow.io/" rel="noopener noreferrer"&gt;webflow&lt;/a&gt; (Usually, we use `proxy-ssl.webflow.com). I'll explain later why.&lt;/p&gt;

&lt;p&gt;This gives me three websites with &lt;strong&gt;three&lt;/strong&gt; &lt;strong&gt;different&lt;/strong&gt; &lt;strong&gt;subdomains&lt;/strong&gt; under one domain. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;However, an interesting thing to note here is all the web crawlers and robots treat all these three websites as a different entity hence, this hurts the SEO significantly and results in a ranking drop.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://main.kanvasai.com/" rel="noopener noreferrer"&gt;main.kanvasai.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://medium.kanvasai.com/" rel="noopener noreferrer"&gt;medium.kanvasai.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://devto.kanvasai.com/" rel="noopener noreferrer"&gt;devto.kanvasai.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, how do we fix it such that when any crawler/user tries to access the&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://main.kanvasai.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;main.kanvasai.com&lt;/strong&gt;&lt;/a&gt; gets redirected to &lt;strong&gt;kanvasai.com/&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://medium.kanvasai.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;medium.kanvasai.com&lt;/strong&gt;&lt;/a&gt; gets redirected to &lt;strong&gt;kanvasai.com/medium,&lt;/strong&gt; and&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://devto.kanvasai.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;devto.kanvasai.com&lt;/strong&gt;&lt;/a&gt; gets redirected to &lt;strong&gt;kanvasai.com/devto&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let’s find out how CloudFlare workers can help&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Workers are just javascript code running in Chrome browser environment. The good thing is that it runs closer to your user's browsers. The bad thing is that you cannot use node packages like in Serverless functions but all modern browsers APIs are supported. Read more about them&lt;/em&gt; &lt;a href="https://developers.cloudflare.com/workers/learning/how-workers-works/" rel="noopener noreferrer"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer : This article assumes you know little bit about cloudflare workers and have tried building with it. So, basic stuff will be excluded and maybe hyperlinked to other blogs.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note : If you’re going to apply this technique on production apps, please note that every &lt;code&gt;CNAME&lt;/code&gt; record will be intercepted by worker, hence needs to be handled with correct worker logic for every route.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Prerequisite :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;working CloudFlare account (free tier also works for this tutorial),&lt;/li&gt;
&lt;li&gt;access to your domain registrar (in this case I’m using Godaddy but the process is the same for every other DNS providers),&lt;/li&gt;
&lt;li&gt;Any code editor that supports JS/TS language features(I will use VS code),&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1 : Create a worker project with Cloudflare cli&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a new worker project by running the following command in the terminal. &lt;code&gt;website-stitcher&lt;/code&gt; is the project name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create cloudflare@2 &lt;span class="nt"&gt;--&lt;/span&gt; website-stitcher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this command, CLI will create a directory named &lt;code&gt;web-stitcher&lt;/code&gt; and you’ll be prompted through a series of questions,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;choose &lt;strong&gt;hello world&lt;/strong&gt; worker&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F80c3b5c3-edfd-4ab5-8d3a-4d48a454169a" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F80c3b5c3-edfd-4ab5-8d3a-4d48a454169a" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;b. Always say &lt;strong&gt;yes&lt;/strong&gt; to typescript&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fd36b2cdb-4d4c-47e4-9b4a-1a88bc92d78d" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fd36b2cdb-4d4c-47e4-9b4a-1a88bc92d78d" alt="Screenshot_2023-08-16_at_8.44.30_PM.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;c. git version control (you can do this later also)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F9ff9b788-3cc1-4abc-8059-1ef71c043ff5" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F9ff9b788-3cc1-4abc-8059-1ef71c043ff5" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;d. Yes, deploy our sample worker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F1a14f08d-85ac-4311-b8eb-d060d692b14e" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F1a14f08d-85ac-4311-b8eb-d060d692b14e" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting ‘yes’, Cloudflare cli will try to log in to your Cloudflare account via browser. Authorize the authentication of cli with the account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F6497e21d-66d0-4892-a23c-9a9459a59d44" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F6497e21d-66d0-4892-a23c-9a9459a59d44" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and Voila! we have our Cloudflare worker ready and deployed. (A browser window should open up automatically with the message ‘hello world’)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe8e5dba7-67ef-49e1-8721-646d452fce82" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe8e5dba7-67ef-49e1-8721-646d452fce82" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we have a Cloudflare worker boilerplate code ready. Open it in your editor of choice. We don’t need to worry about all the files now. We’ll write all our logic in &lt;code&gt;src/worker.ts&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F0f1b65e7-fb07-4153-bb17-8fb1c829e544" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F0f1b65e7-fb07-4153-bb17-8fb1c829e544" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Write the logic to handle incoming requests and redirect its response&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The fetch function has access to the request object which we will use to identify domains, subdomains, pathname, search params, etc. using the below snippet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe37fe5fb-cc71-4964-9353-12003f9477b0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe37fe5fb-cc71-4964-9353-12003f9477b0" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s define our constants &lt;strong&gt;ROOT_DOMAIN&lt;/strong&gt;, &lt;strong&gt;SUBDOMAINS&lt;/strong&gt;, &lt;strong&gt;MAIN_SUBDOMAIN&lt;/strong&gt; and main &lt;strong&gt;WEBSITE_URL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F31efa7cb-7dcc-492f-aa68-f58fb20a9aab" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F31efa7cb-7dcc-492f-aa68-f58fb20a9aab" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we need to write js/ts code to check the incoming hostname for subdomains and redirect it to sub- route. Something like this,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F81016548-f1c7-4850-a7be-45be059f29cc" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F81016548-f1c7-4850-a7be-45be059f29cc" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By looking at the test cases we can break down the logic into three main blocks&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if the &lt;strong&gt;hostname&lt;/strong&gt; is not the same as the &lt;strong&gt;ROOT_DOMAIN&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;here, we need to check SUBDOMAINS if they match the hostname’s subdomain. If it matches one of the SUBDOMAINS we need to redirect the user to the right url.&lt;/li&gt;
&lt;li&gt;we should also check if it matches our MAIN_SUBDOMAIN and redirect the user to the main website&lt;/li&gt;
&lt;li&gt;If does not meet the above two conditions then just return data from the original request URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;if the &lt;strong&gt;pathname&lt;/strong&gt; matches one of the &lt;strong&gt;SUBDOMAINS&lt;/strong&gt; and the &lt;strong&gt;hostname&lt;/strong&gt; is the same as &lt;strong&gt;ROOT_DOMAIN&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;here, we just need to fetch the data from the matching subdomain and redirect the user to the correct URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- or if there’s no subdomain or subroute, fetch data from **MAIN_DOMAIN** and return a response or redirect the user.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;ul&gt;
&lt;li&gt;If the pathname has a trailing &lt;code&gt;slash&lt;/code&gt; (important case)

&lt;ul&gt;
&lt;li&gt;SEO crawlers treat &lt;code&gt;kanvasai.com/medium and [&lt;/code&gt;kanvasi.com/medium/&lt;code&gt;](http://kanvasi.com/medium/) as separate routes. Hence, we need to take care of the&lt;/code&gt;trailing slash`. It’s easy with a bunch of js string methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;It took some time and hit and trail to come up with logic and could be a little overwhelming to understand at once. Hence, I’m attaching a flow diagram to visualize the conditions.&lt;/p&gt;

&lt;p&gt;If you prefer you can just copy and paste the same code change values of constants ROOT_DOMAIN, SUBDOMAINS, MAIN_SUBDOMAIN, and main MAIN_URL to your records.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fa496359c-4e84-46c5-b4f5-6c3e9c4c8dba" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fa496359c-4e84-46c5-b4f5-6c3e9c4c8dba" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The complete code looks like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/fullstackNRJ/7c8a1a12612749f04dc08c6403fe4789" rel="noopener noreferrer"&gt;embed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the following command to deploy the code/worker&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
npx wrangler deploy&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Head over to the Cloudflare &lt;em&gt;&lt;strong&gt;dashboard &amp;gt; workers &amp;amp; pages&lt;/strong&gt;&lt;/em&gt;. You should see list of all the workers here. I have multiple workers but if it’s a new account you should see just one worker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2ca88147-9621-457d-ae81-c1b0da3562eb" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F2ca88147-9621-457d-ae81-c1b0da3562eb" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate inside your worker by clicking on it. You can see all relevant information related to your worker. There are tabs like triggers, logs, deployments, etc.&lt;/p&gt;

&lt;p&gt;Next, we need to define the trigger for this worker. Right now, it is deployed to some random URL by Cloudflare.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Register your site with Cloudflare zone&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before adding a trigger for our worker we need to delegate our DNS nameserver to the Cloudflare. (If your DNS registrar is Cloudflare you don’t need to do this step).&lt;/p&gt;

&lt;p&gt;On the main dashboard, click &lt;code&gt;Add Site&lt;/code&gt; button on the top right corner, and enter your domain name ex. kanvasai.com. &lt;/p&gt;

&lt;p&gt;Now, follow the steps shown by Cloudflare for moving nameservers. This will allow Cloudflare to fetch all the existing DNS records. But, please make sure you have all the records present. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fb60e733c-02de-478d-b945-ba4d94b16949" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fb60e733c-02de-478d-b945-ba4d94b16949" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding &lt;a href="http://albert.ns.clouflare.com/" rel="noopener noreferrer"&gt;&lt;code&gt;albert.ns.clouflare.com&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://annabel.ns.cloudflare.com/" rel="noopener noreferrer"&gt;&lt;code&gt;annabel.ns.cloudflare.com&lt;/code&gt;&lt;/a&gt; to my goDaddy domain DNS setting page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffa17348b-8653-4ab1-9bfc-a94743d15ae0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Ffa17348b-8653-4ab1-9bfc-a94743d15ae0" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finish the site setup by clicking continue and check the DNS nameserver status. This may take some time to verify new nameservers. &lt;em&gt;&lt;strong&gt;Important, thing to note here is now you have to manage all your DNS records from your Cloudflare account. Your DNS registrar will not have control over your records.’&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fcc90a152-a517-47c8-ada1-5c81de5b78ca" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fcc90a152-a517-47c8-ada1-5c81de5b78ca" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;: Make sure you have all the records available in the cloudflare DNS records too. In my case, my two records were not transferred so I had to add them again manually. This can cause&lt;/em&gt; &lt;em&gt;&lt;strong&gt;downtime&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;to your app so be careful while doing this transfer.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Add your root domain as the worker’s trigger&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, we are ready to add triggers to our workers. Navigate to your worker by clicking workers &amp;amp; pages on the left panel and then clicking on your worker from the list.&lt;/p&gt;

&lt;p&gt;On this page, click on the &lt;code&gt;Triggers&lt;/code&gt; tab next to &lt;code&gt;Metrics.&lt;/code&gt;  Here, click on the &lt;strong&gt;Add Custom Domain&lt;/strong&gt; button and add your domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F4796a68e-0206-40f0-a7f4-1e7a5928d392" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F4796a68e-0206-40f0-a7f4-1e7a5928d392" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: you might see this error if you did not follow the last step correctly. In order to add your custom domain as a trigger for workers, your custom domain must be delegated to Cloudflare nameservers.(Don’t worry, your registrar will stay the same, GoDaddy in this case).&lt;/p&gt;

&lt;p&gt;Cloudflare adds a new DNS record to type worker, you can check this to verify if your custom domain is set up correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F020f453f-cfbf-4dfe-bd6b-e15babd98ac4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F020f453f-cfbf-4dfe-bd6b-e15babd98ac4" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Attach a wildcard route to your worker&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, for our worker logic to run correctly we need to forward all the requests from all the sub domains to our worker. So, we’ll add a route for this we are going to use a wildcard (&lt;em&gt;) to define a pattern of URLs that are allowed or that trigger our worker. So,&lt;/em&gt; just below the custom domain, there is a section for routes (also called worker routes).  I’ll add &lt;code&gt;*.kanvasai.com/*&lt;/code&gt;  as the route and choose &lt;a href="http://kanvasi.com/" rel="noopener noreferrer"&gt;&lt;code&gt;kanvasi.com&lt;/code&gt;&lt;/a&gt; as the zone. This represents all the subdomains and subroutes that have &lt;a href="http://kanvasi.com/" rel="noopener noreferrer"&gt;kanvasi.com&lt;/a&gt; as the root domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F371ded2c-8662-4d60-98bd-24655ae1c1c4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F371ded2c-8662-4d60-98bd-24655ae1c1c4" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we should see this message once the route is properly configured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe1c0209a-7e20-4772-af08-0b9bb34e1ec4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fe1c0209a-7e20-4772-af08-0b9bb34e1ec4" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can already see the worker in action. Try visiting your root domain and subdomains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5ec867db-209c-4735-abf6-c0673921f5da" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2F5ec867db-209c-4735-abf6-c0673921f5da" alt="ezgif.com-video-to-gif.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it's not working for you wait for some time to let DNS propagate changes. Try on a different device because Chrome caches the websites on disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 6: Handling www CNAME record :&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are a couple of ways to handle this, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can add another CNAME record pointing to the same Cloudflare worker,&lt;/li&gt;
&lt;li&gt;handle it in the worker code with JS or,&lt;/li&gt;
&lt;li&gt;iii. Define a page rule such that anyone accessing &lt;a href="http://www.kanvasai.com/*" rel="noopener noreferrer"&gt;&lt;strong&gt;www.kanvasai.com/&lt;/strong&gt;*&lt;/a&gt; gets automatically redirected to &lt;strong&gt;&lt;a href="https://kanvasai.com/" rel="noopener noreferrer"&gt;https://kanvasai.com/&lt;/a&gt;&lt;/strong&gt;*&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fee7d2053-2e64-47b6-8c2a-a08df2060b2b" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Fee7d2053-2e64-47b6-8c2a-a08df2060b2b" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 7: Handling relative URL (hrefs) in your applications&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If your app uses an anchor tag and has subroutes, you should probably prefix those with subdomain names (/medium/about or /devto/about). You’ll understand why after trying it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 8: SSL/TLS certificates between Cloudflare and your application server&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For Vercel and similar applications, SSL is generated by the platform itself. Hence, we need full security&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Webflow&lt;/strong&gt;, we keep it flexible and let Cloudflare manage SSL certificates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Faf82d30c-bf05-4a7d-a3fa-432f91ab6232" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog-images-prod.s3.amazonaws.com%2Faf82d30c-bf05-4a7d-a3fa-432f91ab6232" alt="Untitled.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cons of this approach&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, we’ll have to manage all our DNS records through Cloudflare.&lt;/li&gt;
&lt;li&gt;Adding a new record becomes a little tricky.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In the follow-up article, we’ll see how to do this with SPAs.&lt;/strong&gt; Please comment if you want a tutorial on that topic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are trying to setup this reverse proxy and facing any issues, feel free to reach out or book a &lt;strong&gt;free&lt;/strong&gt; consultation &lt;a href="https://calendly.com/niraj-mukta123/introductory-call?month=2023-09" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I’ll be more than happy to help.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article was published using&lt;a href="https://buzpen.com/" rel="noopener noreferrer"&gt; Buzpen.&lt;/a&gt; If you want to publish the same article to three major platforms at once, then do try out Buzpen.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building an Android and iOS app in 2023</title>
      <dc:creator>Neeraj Mukta</dc:creator>
      <pubDate>Wed, 06 Sep 2023 15:10:05 +0000</pubDate>
      <link>https://dev.to/fullstacknrj/building-an-android-and-ios-app-in-2023-4lol</link>
      <guid>https://dev.to/fullstacknrj/building-an-android-and-ios-app-in-2023-4lol</guid>
      <description>&lt;p&gt;“Ideas are cheap, execution is expensive!” &lt;/p&gt;

&lt;p&gt;I’m sure you must have heard this quote in some or the other form. A billion dollar ideas requires millions in investments before it turns profitable. The road to profitability is a tough one as we have seen in the recent few years with companies adapting all the means to save every buck. &lt;/p&gt;

&lt;p&gt;So, the question is should you also spend millions and then start saving thousands to become profitable? I leave this question to be answered by you.&lt;/p&gt;

&lt;p&gt;In the past few months I have met at least 10 founders (or wanna be founders) who have this startup or business idea that they think is amazing, has potential to disrupt the market and in turn  make them rich. Of course, this was all in their heads and they were trying hard to pitch the idea and find a co founder who can help them build the product or service. And one common question they had was how expensive is it to build a product or service? Mind you all these people didn’t have a technical background and the only thing according to them that was stopping them was tech. The wild wild world of app development.&lt;/p&gt;

&lt;p&gt;My goal through this article is to help you make right technological decisions to test your ideas. That’s right! Testing an idea is the first stage of any &lt;strong&gt;billion dollar&lt;/strong&gt; company in making. You need to bet enough resources and time to validate your &lt;em&gt;product idea&lt;/em&gt;, &lt;em&gt;find early adopters&lt;/em&gt; and then do some serious analytics. Most of the founders make a mistake here, they go all in on the product development and marketing without even proper development and business plan. There are many steps involved before committing to full on development. (Maybe I’ll cover those in some other blog.)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;TIP 1: Save money by building something trivial but functional first that can help you validate the idea. It does not have to be an app or a website. It could be a simple spreadsheet also.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of the time they end up losing money and sometimes reputation too. You certainly don’t have to sell your house to validate your product idea.&lt;/p&gt;

&lt;p&gt;Returning to the original question how much does it cost to build an MVP (minimal viable product)?&lt;/p&gt;

&lt;p&gt;Well, the answer varies on the requirements of your MVP. Let’s assume you need an android or iOS app or both for your MVP or initial version. The effort in building any native mobile app from scratch is significantly high when compared to web apps. It takes around 100 hrs just to write basic building blocks of an native app and time increases based on complexity of business rules.&lt;/p&gt;

&lt;p&gt;You can easily save time and effort by choosing a cross-platform technology like &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;React Native&lt;/strong&gt;&lt;/a&gt;. This helps you in jumpstarting the native app development with little knowledge on native languages like Java/Kotlin (used to build native android apps), Objective C/Swift (used to build native iOS apps).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;TIP 2: If you need an app for your idea, choose a cross platform technology to build it. This will help you build it faster, iterate over features quickly and roll out to users in shortest amount of time without burning a hole in your pocket.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Honestly, &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;React native&lt;/strong&gt;&lt;/a&gt; has become pretty good in 2023 and &lt;a href="https://expo.dev/about" rel="noopener noreferrer"&gt;&lt;strong&gt;expo team&lt;/strong&gt;&lt;/a&gt; has made it even easier for any javascript developer to build cross platform mobile apps. No matter what stage you are at as a company you should almost always bet on react native because it’s very stable and rapid to develop. If you’re just starting out or you are already at startup level you should save costs on technology by leveraging &lt;a href="https://expo.dev/" rel="noopener noreferrer"&gt;expo&lt;/a&gt; and react native ecosystem. If you google how to build a mobile app for android and iOS you will find tons of frameworks and technology to do it. But, broadly speaking there are two type of app development native and cross-platform, cross-platform being the quickest of the two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;TIP 3: In 2023, you can use&lt;/strong&gt; &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;React native&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;/Expo to build prototype apps as well as high traffic  professional quality apps&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s discuss a development plan where you want an app (android/ios) that users can use to find their morning ride to office. &lt;strong&gt;A social carpooling app&lt;/strong&gt;. Now, before making this into a flow blown app something like the Uber and then launching it to your customers, what you should do first is to figure out if the users actually want to carpool with strangers in their area?  Just ask around, interview people. Once, you are sure then you should test it by giving them an app.&lt;/p&gt;

&lt;p&gt;For, this you can start with simple website that lists all the available cars from region A to region B in that city. Mobile devices are more common for such services so let’s focus on building the iOS and android app. Breaking down the requirements looks something like :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;people signup into your app,&lt;/li&gt;
&lt;li&gt;they share some identity like driver’s license and other relevant information,&lt;/li&gt;
&lt;li&gt;they can view available car pools for today,&lt;/li&gt;
&lt;li&gt;they can send a request to join a certain car pool,&lt;/li&gt;
&lt;li&gt;and they have the an option to host a car themselves and approve new requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I just did is to write down a high level overview of what app should do and this should be enough to validate our idea. As you can already see we need at least 5 screens already for our app. Imagine building these same screens separately on iOS and android &amp;amp; this will also need a backend. 😱&amp;nbsp;Thus, by using a cross platform framework like React Native or &lt;a href="https://flutter.dev/" rel="noopener noreferrer"&gt;flutter&lt;/a&gt; we can save time and cost on app and maybe spend that time on building a robust server. Because at the end data is what matters in this century.  So I’m picking expo for few simple reasons,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it’s open source &amp;amp; it’s based on Typescript and React,&lt;/li&gt;
&lt;li&gt;it complies down to actual native code for both android and iOS unlike flutter,&lt;/li&gt;
&lt;li&gt;it has relatively less steep learning curve, it’s easy to find devs or train React devs,&lt;/li&gt;
&lt;li&gt;it has good support/libraries for camera, location, bluetooth etc, all the common native functionalities,&lt;/li&gt;
&lt;li&gt;it is extensible meaning you can write custom native plugins if existing components or libraries are not suitable enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;Also, why not Flutter? will be answered in an separate post.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My next post will be on setting up a React Native app with expo. Stay tuned and follow me on whichever platform you are reading this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: I provide free consultation on MVP Planning. I do a 1 on 1 session where we figure out the viability of your idea and how to bring it to life in most appropriate and quickest manner possible. If you are struggling with making right technological choice for your Product feel free to reach out. You can book free consultation &lt;a href="https://calendly.com/niraj-mukta123/introductory-call?month=2023-09" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article was publish on &lt;em&gt;medium&lt;/em&gt;, &lt;em&gt;devto&lt;/em&gt; and &lt;em&gt;hasnode&lt;/em&gt; using &lt;a href="https://buzpen.com/" rel="noopener noreferrer"&gt;buzpen&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
