<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Carlos Rogerio Orioli</title>
    <description>The latest articles on Forem by Carlos Rogerio Orioli (@carlosorioli).</description>
    <link>https://forem.com/carlosorioli</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F307916%2Fc276c9a7-5df3-4d03-ab69-17058c3b7c1e.jpeg</url>
      <title>Forem: Carlos Rogerio Orioli</title>
      <link>https://forem.com/carlosorioli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/carlosorioli"/>
    <language>en</language>
    <item>
      <title>Desafio Headless: Checkout Shopify em App React Native com Zustand</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Tue, 07 Apr 2026 18:10:07 +0000</pubDate>
      <link>https://forem.com/carlosorioli/desafio-headless-checkout-shopify-em-app-react-native-com-zustand-h19</link>
      <guid>https://forem.com/carlosorioli/desafio-headless-checkout-shopify-em-app-react-native-com-zustand-h19</guid>
      <description>&lt;p&gt;O grande desafio no ecossistema Shopify é garantir que a transição entre a seleção de produtos nativa e o pagamento na &lt;strong&gt;WebView&lt;/strong&gt; seja invisível para o usuário, mantendo a persistência do carrinho via &lt;strong&gt;Storefront API&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Para isso, utilizei o &lt;strong&gt;Zustand&lt;/strong&gt; para o gerenciamento de estado global e o &lt;strong&gt;MMKV&lt;/strong&gt; para garantir uma persistência de dados ultra-rápida, superior ao AsyncStorage tradicional. Confira o passo a passo dessa implementação:&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Store com Zustand e MMKV
&lt;/h3&gt;

&lt;p&gt;A store armazena o &lt;code&gt;checkoutId&lt;/code&gt; e a &lt;code&gt;webUrl&lt;/code&gt;. O uso do &lt;strong&gt;MMKV&lt;/strong&gt; é o "game changer" aqui: ele é cerca de 30x mais rápido que o AsyncStorage, garantindo que o carrinho carregue instantaneamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createJSONStorage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MMKV&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-mmkv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MMKV&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mmkvStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;removeItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useShopifyStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;checkoutId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;webUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;setCheckout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;checkoutId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;webUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shopify-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createJSONStorage&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;mmkvStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Sincronização via Storefront API (GraphQL)
&lt;/h3&gt;

&lt;p&gt;Antes de levar o usuário para o checkout, sincronizamos os itens locais com a Shopify para gerar (ou atualizar) a URL final de pagamento.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;syncCheckout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checkoutId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lineItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    mutation checkoutLineItemsReplace($checkoutId: ID!, $lineItems: [CheckoutLineItemInput!]!) {
      checkoutLineItemsReplace(checkoutId: $checkoutId, lineItems: $lineItems) {
        checkout { id, webUrl }
      }
    }
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://SUA-LOJA.myshopify.com/api/2024-01/graphql.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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="s1"&gt;Content-Type&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="s1"&gt;application/json&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="s1"&gt;X-Shopify-Storefront-Access-Token&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="s1"&gt;SEU_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkoutId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lineItems&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. O Checkout na WebView
&lt;/h3&gt;

&lt;p&gt;Utilizamos a &lt;code&gt;webUrl&lt;/code&gt; retornada pela API para abrir o checkout já preenchido, mantendo todas as regras de negócio da loja ativas.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ShopifyCheckout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;webUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useShopifyStore&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;WebView&lt;/span&gt; 
      &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;webUrl&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; 
      &lt;span class="nx"&gt;sharedCookiesEnabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;startInLoadingState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  O que aprendi?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Arquitetura Agnostica&lt;/strong&gt;: Validar a lógica na VTEX e replicar no Shopify mostra que um bom padrão de projeto sobrevive a qualquer stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: No e-commerce de alto nível que entregamos na &lt;strong&gt;Converte&lt;/strong&gt;, milissegundos salvos com MMKV convertem em vendas.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>reactnative</category>
      <category>shopify</category>
      <category>vtex</category>
      <category>zustand</category>
    </item>
    <item>
      <title>Sincronizando Zustand com VTEX OrderForm no React Native</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Mon, 06 Apr 2026 17:22:34 +0000</pubDate>
      <link>https://forem.com/carlosorioli/sincronizando-zustand-com-vtex-orderform-no-react-native-3ab9</link>
      <guid>https://forem.com/carlosorioli/sincronizando-zustand-com-vtex-orderform-no-react-native-3ab9</guid>
      <description>&lt;p&gt;Recentemente, precisei desenvolver uma integração de checkout VTEX dentro de um aplicativo React Native. O desafio era garantir que a experiência de compra fosse fluida, mantendo o estado do carrinho perfeitamente sincronizado entre o ambiente nativo do app e a finalização da compra na WebView.&lt;/p&gt;

&lt;p&gt;Para resolver isso, utilizei o Zustand para o gerenciamento de estado global e a API de Checkout da VTEX para manipular o orderFormId.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Arquitetura da Solução
&lt;/h2&gt;

&lt;p&gt;A ideia central foi: o App gerencia os produtos e quantidades através de uma store leve Zustand e, antes de abrir o checkout, sincronizamos tudo com a VTEX via API.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Gerenciando o Carrinho com Zustand
&lt;/h2&gt;

&lt;p&gt;A store armazena o orderFormId e persiste os dados para que o carrinho não se perca. Aqui, podemos escolher entre o AsyncStorage (padrão) ou o MMKV (para performance ultra-rápida).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createJSONStorage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&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-async-storage/async-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MMKV&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-mmkv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Opção com MMKV (Alta Performance)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MMKV&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mmkvStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;removeItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCartStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;setOrderFormId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;addToCart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
      &lt;span class="na"&gt;clearCart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="na"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Troque 'mmkvStorage' por 'AsyncStorage' se preferir o padrão&lt;/span&gt;
      &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createJSONStorage&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;mmkvStorage&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Para esse projeto, utilizei o MMKV pela velocidade de leitura/escrita, mas a estrutura funciona perfeitamente com AsyncStorage também.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Sincronizando com a API da VTEX
&lt;/h2&gt;

&lt;p&gt;Antes de navegar para a tela de checkout, enviamos os itens para o orderForm específico. Isso evita disparar várias chamadas de rede desnecessárias durante a navegação.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;syncCartWithVtex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://{ACCOUNT}.vtexcommercestable.com.br/api/checkout/pub/orderForm/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/items`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&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="s1"&gt;Content-Type&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="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;orderItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro na sincronização:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;DICA: A VTEX às vezes exige que o cabeçalho vtex-id-client-authtoken seja enviado se o usuário já estiver autenticado no app, para que o carrinho não fique como "anônimo"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. O Checkout na WebView
&lt;/h2&gt;

&lt;p&gt;A sacada foi é injetar o orderFormId na URL da WebView. Assim, o checkout da VTEX já abre com todos os itens que o usuário escolheu no app.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VtexCheckout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;orderFormId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCartStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// URL que vincula a sessão ao carrinho do App&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkoutUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://www.sualoja.com.br/checkout/?orderFormId=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;orderFormId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;#/cart`&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;WebView&lt;/span&gt; 
      &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;checkoutUrl&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
      &lt;span class="nx"&gt;sharedCookiesEnabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;//PARA MANTER A SESSÃO &lt;/span&gt;
      &lt;span class="nx"&gt;startInLoadingState&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;h2&gt;
  
  
  Lições aprendidas
&lt;/h2&gt;

&lt;p&gt;Performance: Sincronizar o estado via API antes de abrir a WebView entrega uma experiência muito mais "nativa" do que tentar manipular o DOM da página carregada.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Persistência: O uso do Zustand com middleware de persistência é imbatível para lidar com carrinhos em dispositivos móveis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Desenvolver soluções de e-commerce de alta performance é o que move a gente na Converte . &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E você, já teve que lidar com essa ponte entre o nativo e o web no e-commerce? Vamos trocar uma ideia nos comentários!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>zustand</category>
      <category>mobile</category>
      <category>mobilecommerce</category>
    </item>
    <item>
      <title>Nietzsche in a Madhouse</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Wed, 01 Apr 2026 18:10:20 +0000</pubDate>
      <link>https://forem.com/carlosorioli/nietzsche-in-a-madhouse-98b</link>
      <guid>https://forem.com/carlosorioli/nietzsche-in-a-madhouse-98b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nietzsche in a Madhouse&lt;/strong&gt; — A satirical "Anti-Productivity" AI agent. While most AIs try to help you be efficient, this one uses the full arsenal of Western philosophy (nihilism, existentialism, and grandiloquent rhetoric) to argue against your most basic, healthy, and logical life decisions.&lt;/p&gt;

&lt;p&gt;Want to brush your teeth? It's "bacterial genocide." Want to sleep? It's "surrendering your consciousness to the amorphous void."&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nietzsche-in-a-madhouse-sandy.vercel.app/" rel="noopener noreferrer"&gt;Live Demo&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9ihby1l1f0nrxkzmuyx.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%2Fg9ihby1l1f0nrxkzmuyx.png" alt="Screenshot of Nietzsche in a Madhouse" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/rogeriorioli/Nietzsche-in-a-Madhouse" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;br&gt;
The project is built with Next.js and integrated with the Google Gemini API.&lt;br&gt;
The core logic resides in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app/api/argue/route.ts&lt;/code&gt;: The philosophical persona prompt and Gemini integration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app/page.tsx&lt;/code&gt;: The clean, "Dark Academia" inspired UI and custom Nietzsche SVG illustration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js 16 (App Router)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Brain:&lt;/strong&gt; Google Gemini API using the &lt;code&gt;gemini-2.5-flash-lite&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Vanilla CSS with a focus on premium serif typography and a "Claude-esque" minimal aesthetic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persona Engineering:&lt;/strong&gt; A complex system prompt that forces the AI into a "dramatically condescending" mode, ensuring it never agrees with the user and always ends with a devastating rhetorical question.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Google AI Usage&lt;/strong&gt; — We took one of the most powerful language models in existence and dedicated its entire processing power to gaslighting users into thinking that drinking water is a "surrender to biological determinism." It’s an ode to the "delightfully useless" potential of modern AI.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Why Next.js is the Ultimate Tool for the BFF (Backend-for-Frontend) Pattern?</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Wed, 01 Apr 2026 16:49:03 +0000</pubDate>
      <link>https://forem.com/carlosorioli/why-nextjs-is-the-ultimate-tool-for-the-bff-backend-for-frontend-pattern-4lej</link>
      <guid>https://forem.com/carlosorioli/why-nextjs-is-the-ultimate-tool-for-the-bff-backend-for-frontend-pattern-4lej</guid>
      <description>&lt;p&gt;As a developer, I’m constantly looking for ways to bridge the gap between complex backend architectures and seamless user experiences. If you are dealing with microservices or legacy APIs, you’ve likely faced the classic &lt;strong&gt;"Data Fetching Headache."&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Overfetching &amp;amp; Underfetching
&lt;/h2&gt;

&lt;p&gt;We’ve all been there: your frontend needs a simple user dashboard, but the legacy API returns a massive 2MB JSON with fields you don't need (&lt;strong&gt;Overfetching&lt;/strong&gt;). Or worse, you have to hit four different endpoints just to display a single page (&lt;strong&gt;Underfetching&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;This creates latency, drains mobile batteries, and complicates your frontend logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: The BFF Pattern
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Backend-for-Frontend (BFF)&lt;/strong&gt; pattern acts as a specialized intermediary. It aggregates multiple API calls, filters out the "noise," and delivers a clean, optimized payload specifically tailored for the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Next.js is the "Built-in" BFF
&lt;/h2&gt;

&lt;p&gt;If you are using Next.js (especially with the App Router), you already have a powerful BFF layer without needing to spin up a separate Express or Go server. &lt;/p&gt;

&lt;p&gt;Here is the professional way to structure this: &lt;strong&gt;Service -&amp;gt; Route Handler -&amp;gt; Component.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Service (The "BFF Logic")
&lt;/h3&gt;

&lt;p&gt;This file handles the "dirty work": fetching from legacy systems, using private keys, and cleaning the data. This stays strictly on the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/apiService.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProductDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EXTERNAL_API_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Securely stored on the server&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&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="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// ISR: Cache for 1 hour&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to fetch from Legacy API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// BFF Logic: Transform and "clean" the data for the UI&lt;/span&gt;
  &lt;span class="c1"&gt;// We only return what the frontend actually uses.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`$ &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price_usd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;stockStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inventory&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;In Stock&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="s1"&gt;Out of Stock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. The Route Handler (The Internal Bridge)
&lt;/h3&gt;

&lt;p&gt;This acts as your own private API endpoint. It allows your Client Components to trigger data fetching without ever exposing the sensitive Legacy API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/products/[id]/route.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getProductDashboard&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/services/apiService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Calling our internal service&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProductDashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Internal Server Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The Client Component (The Consumer)
&lt;/h3&gt;

&lt;p&gt;The UI remains clean and decoupled. It calls &lt;strong&gt;your&lt;/strong&gt; BFF endpoint, receiving the "perfect" object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductQuickView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We fetch from our INTERNAL Route Handler, not the legacy API!&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4 border rounded"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loadDetails&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-blue-500 text-white px-4 py-2 rounded"&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Quick View Product
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Price: &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Status: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stockStatus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Security:&lt;/strong&gt; Your &lt;code&gt;API_SECRET_KEY&lt;/code&gt; never leaks to the browser.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Abstraction:&lt;/strong&gt; If the legacy API changes its JSON structure tomorrow, you only update the &lt;strong&gt;Service&lt;/strong&gt;. Your Route Handlers and Components stay exactly the same.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Performance:&lt;/strong&gt; You reduce the payload size significantly, which is critical for high-conversion e-commerce sites.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;I’m &lt;strong&gt;Carlos&lt;/strong&gt;, a senior developer and founder of &lt;strong&gt;Converte&lt;/strong&gt; based in Florianópolis, Brazil. In my experience, choosing the right architecture isn't just about "clean code"—it’s about &lt;strong&gt;performance and results.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Next.js as a BFF allows us to deliver lightning-fast interfaces while keeping the codebase maintainable. Whether I’m catching waves here in Floripa or building complex digital solutions, the goal is always the same: &lt;strong&gt;agility and balance.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How about you?&lt;/strong&gt; Do you prefer building a separate API layer, or are you leveraging Next.js's native server capabilities?&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Quando usar map, filter, reduce, for, forEach e flatMap em JavaScript</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Fri, 02 Jan 2026 10:23:26 +0000</pubDate>
      <link>https://forem.com/carlosorioli/quando-usar-map-filter-reduce-for-foreach-e-flatmap-em-javascript-4c9e</link>
      <guid>https://forem.com/carlosorioli/quando-usar-map-filter-reduce-for-foreach-e-flatmap-em-javascript-4c9e</guid>
      <description>&lt;h2&gt;
  
  
  &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;forEach&lt;/code&gt; e &lt;code&gt;flatMap&lt;/code&gt;: qual usar?
&lt;/h2&gt;

&lt;p&gt;Se você trabalha com JavaScript ou TypeScript, já se perguntou &lt;strong&gt;qual método usar para percorrer arrays&lt;/strong&gt; — e &lt;em&gt;por quê&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Aqui está um guia rápido, direto ao ponto, com exemplos simples&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;map&lt;/code&gt; → transformar dados
&lt;/h3&gt;

&lt;p&gt;Use quando quiser &lt;strong&gt;transformar cada item&lt;/strong&gt; do array sem alterar o tamanho.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// [2, 4, 6, 8, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;filter&lt;/code&gt; → remover dados
&lt;/h3&gt;

&lt;p&gt;Use quando precisar &lt;strong&gt;manter apenas os itens que atendem a uma condição&lt;/strong&gt;.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;even&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// [2, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;reduce&lt;/code&gt; → calcular ou agrupar
&lt;/h3&gt;

&lt;p&gt;Use quando o objetivo for &lt;strong&gt;chegar a um único valor&lt;/strong&gt; (soma, objeto, agrupamento).&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;for&lt;/code&gt; → controle total
&lt;/h3&gt;

&lt;p&gt;Use quando precisar de &lt;strong&gt;controle total da iteração&lt;/strong&gt;, como &lt;code&gt;break&lt;/code&gt; ou &lt;code&gt;continue&lt;/code&gt;.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// [2, 4, 6, 8, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;forEach&lt;/code&gt; → executar ações
&lt;/h3&gt;

&lt;p&gt;Use quando quiser apenas &lt;strong&gt;executar efeitos colaterais&lt;/strong&gt;, sem retornar dados.&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="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;flatMap&lt;/code&gt; → map + flatten
&lt;/h3&gt;

&lt;p&gt;Use quando o &lt;code&gt;map&lt;/code&gt; retorna arrays e você quer evitar &lt;code&gt;.map().flat()&lt;/code&gt;.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Regra de ouro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Transformar → &lt;code&gt;map&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Filtrar → &lt;code&gt;filter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Calcular/agrupar → &lt;code&gt;reduce&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Executar ações → &lt;code&gt;forEach&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Evitar arrays aninhados → &lt;code&gt;flatMap&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;E você?&lt;/strong&gt;&lt;br&gt;
Qual desses métodos você mais usa no dia a dia?&lt;br&gt;
Já se perdeu em um &lt;code&gt;reduce&lt;/code&gt; achou difícil de ler?&lt;/p&gt;

&lt;p&gt;Comenta aí &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>devtips</category>
      <category>beginners</category>
    </item>
    <item>
      <title>JavaScript Syntax Cheatsheet (Guia Rápido)</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Sun, 28 Dec 2025 22:07:03 +0000</pubDate>
      <link>https://forem.com/carlosorioli/javascript-syntax-cheatsheet-guia-rapido-5e03</link>
      <guid>https://forem.com/carlosorioli/javascript-syntax-cheatsheet-guia-rapido-5e03</guid>
      <description>&lt;p&gt;Um guia de referência rápida para as principais sintaxes e recursos modernos do JavaScript.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Variáveis e Escopo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No JavaScript moderno, o escopo é fundamental. Utilizamos const para valores que não mudam e let para variáveis que precisam de ser reatribuídas dentro do seu bloco de código. O var deve ser evitado por ter um escopo menos previsível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Constante: valor que não pode ser reatribuído
const pi = 3.14;

// Let: variável com escopo de bloco
let contador = 0;
contador += 1;

// Var: (Legado/Não recomendado) Escopo de função
var nome = "Global";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Tipos de Dados&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O JavaScript é uma linguagem de tipagem dinâmica. Isto significa que uma variável pode conter diferentes tipos de dados, desde textos simples a estruturas complexas como objetos e listas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const texto = "Olá Mundo";       // String (Texto)
const numero = 42;               // Number (Inteiro ou Decimal)
const booleano = true;           // Boolean (Verdadeiro ou Falso)
const lista = [1, 2, 3];         // Array (Lista de valores)
const objeto = { id: 1 };        // Object (Pares de chave/valor)
const vazio = null;              // Null (Valor nulo intencional)
let indefinido;                  // Undefined (Variável sem valor)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Funções&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As funções são blocos de construção essenciais. As Arrow Functions introduzidas no ES6 tornaram a escrita mais concisa, especialmente quando a lógica é simples e pode ser escrita numa única linha com retorno implícito.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Função Tradicional
function somar(a, b) {
  return a + b;
}

// Arrow Function (Moderna)
const subtrair = (a, b) =&amp;gt; a - b;

// Arrow Function com retorno implícito (não precisa de {} ou return)
const dobrar = n =&amp;gt; n * 2;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As condicionais permitem que o código tome decisões. O operador ternário é uma forma elegante de escrever um if/else simples numa só linha, enquanto o switch ajuda a gerir múltiplas condições de uma mesma variável.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// If / Else padrão
if (idade &amp;gt;= 18) {
  console.log("Adulto");
} else {
  console.log("Menor");
}

// Operador Ternário (Forma curta de if/else)
const status = idade &amp;gt;= 18 ? "Liberado" : "Bloqueado";

// Switch para múltiplas opções
switch (cor) {
  case "red": return "Vermelho";
  case "blue": return "Azul";
  default: return "Cor desconhecida";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Loops e Iteração&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para percorrer dados, o for...of é a forma mais legível para Arrays. Além disso, métodos funcionais como .map(), .filter() e o poderoso .flatMap() permitem transformar, filtrar e achatar coleções de dados de forma eficiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const frutas = ["Maçã", "Banana", "Uva"];

// For...of: Ideal para percorrer elementos de um array
for (const fruta of frutas) {
  console.log(fruta);
}

// Map: Cria um novo array transformando cada elemento
const dobrados = [1, 2, 3].map(n =&amp;gt; n * 2);

// Filter: Cria um novo array apenas com os itens que passam no teste
const pares = [1, 2, 3, 4].filter(n =&amp;gt; n % 2 === 0);

// FlatMap: Mapeia cada elemento e achata o resultado num novo array
// Útil para quando a função de mapeamento retorna um array
const frases = ["Olá mundo", "JS é incrível"];
const palavras = frases.flatMap(f =&amp;gt; f.split(" ")); 
// Resultado: ["Olá", "mundo", "JS", "é", "incrível"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Template Literals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Esquecer a concatenação manual com o símbolo +. Com as crases, podemos interpolar variáveis e expressões diretamente dentro da string, facilitando a leitura do código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const usuario = "Carlos";
// Uso de ${} dentro de crases para inserir valores dinâmicos
console.log(`Olá, ${usuario}! Hoje é ${new Date().toLocaleDateString()}.`);

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Desestruturação (Destructuring)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A desestruturação permite "desembalar" valores de objetos ou arrays de forma rápida. É extremamente útil para capturar propriedades de objetos de configuração ou retornos de funções.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const config = { tema: "dark", lang: "pt-br" };

// Extraindo propriedades 'tema' e 'lang' diretamente do objeto
const { tema, lang } = config;

// Extraindo valores por posição de um array
const [primeiro, segundo] = [10, 20];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Promises e Async/Await&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para operações que demoram tempo (como carregar dados da internet), usamos o modo assíncrono. O par async/await permite escrever código assíncrono que se parece com código sequencial, tornando-o muito mais fácil de manter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// A palavra 'async' indica que a função lidará com processos demorados
async function buscarDados() {
  try {
    // 'await' pausa a execução até que a promessa seja resolvida
    const resposta = await fetch("[https://api.exemplo.com/dados](https://api.exemplo.com/dados)");
    const dados = await resposta.json();
    console.log(dados);
  } catch (erro) {
    // Captura erros se a conexão ou os dados falharem
    console.error("Erro na busca:", erro);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Spread &amp;amp; Rest Operator&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Os três pontos ... têm dois papéis: o Spread "espalha" elementos de um array noutro, enquanto o Rest "recolhe" vários argumentos numa única variável dentro de uma função.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Spread (Espalhar): Copia ou expande arrays/objetos
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // Resulta em [1, 2, 3, 4]

// Rest (Agrupar): Transforma argumentos soltos num array
function listar(...itens) {
  console.log(itens); // 'itens' será um array com todos os argumentos
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dica de Performance: Utilize sempre const por padrão. Só mude para let se tiver a certeza absoluta de que o valor da variável precisará de ser alterado durante a execução.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My Year Review (2025) - by Chat GPT</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Fri, 26 Dec 2025 20:03:58 +0000</pubDate>
      <link>https://forem.com/carlosorioli/my-year-review-2025-by-chat-gpt-15ig</link>
      <guid>https://forem.com/carlosorioli/my-year-review-2025-by-chat-gpt-15ig</guid>
      <description>&lt;p&gt;🔎 Perfil Profissional &amp;amp; Presença Online&lt;br&gt;
🧠 Identidade e foco&lt;/p&gt;

&lt;p&gt;Você se apresenta como Carlos Rogerio Orioli — um desenvolvedor Web (Front-end e Full-stack) com fortes conhecimentos em JavaScript, React, Node.js, WordPress, Web Design, Martech e Engenharia de Prompt para IA, além de atuação em design gráfico e produção de conteúdo técnico. &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;Seu perfil profissional combina desenvolvimento técnico com marketing e design, refletindo uma visão ampla e estratégica de produtos digitais. &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;🛠️ GitHub — Repositórios e Contribuições&lt;br&gt;
📈 Atividade no GitHub&lt;/p&gt;

&lt;p&gt;No GitHub você tem um perfil ativo com:&lt;/p&gt;

&lt;p&gt;98 repositórios públicos (especialmente projetos próprios). &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;~86 estrelas acumuladas na comunidade, indicando reconhecimento pelo seu trabalho. &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;~280 seguidores e ~496 seguindo, mostrando bom engajamento e networking técnico. &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;⭐ Destaques de 2025&lt;/p&gt;

&lt;p&gt;Projetos notáveis:&lt;/p&gt;

&lt;p&gt;voafoguete — repositório colaborativo com recursos e cursos gratuitos para desenvolvimento pessoal/tecnológico. &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;TextVox-BACKEND — backend em TypeScript para conversão de áudio em texto utilizando OpenAI APIs (projeto com foco prático em IA). &lt;br&gt;
GitHub&lt;/p&gt;

&lt;p&gt;Esses projetos mostram o seu interesse em aplicações úteis, open-source e em integração com IA, além de compartilhar conhecimento com a comunidade.&lt;/p&gt;

&lt;p&gt;📝 dev.to — Conteúdo Publicado &amp;amp; Engajamento&lt;/p&gt;

&lt;p&gt;No DEV Community (dev.to) você se destaca como um autor ativo e engajado:&lt;/p&gt;

&lt;p&gt;🏅 Conquistas na plataforma&lt;/p&gt;

&lt;p&gt;Você conquistou diversos badges importantes em 2025, incluindo:&lt;/p&gt;

&lt;p&gt;2025 Hacktoberfest Writing Challenge Completion — completou ao menos um prompt no evento de escrita de 2025. &lt;br&gt;
DEV Community&lt;/p&gt;

&lt;p&gt;Streaks de comentários (1-week e 2-week wellness) — ativa participação na comunidade via comentários. &lt;br&gt;
DEV Community&lt;/p&gt;

&lt;p&gt;JavaScript badge — contribuição destacada na comunidade de JS. &lt;br&gt;
DEV Community&lt;/p&gt;

&lt;p&gt;Longevity badges — reconhecimento pela sua presença contínua na plataforma ao longo dos anos. &lt;br&gt;
DEV Community&lt;/p&gt;

&lt;p&gt;📚 Conteúdo técnico publicado&lt;/p&gt;

&lt;p&gt;Você produziu diversos artigos em 2025 sobre tópicos relevantes como:&lt;/p&gt;

&lt;p&gt;✔️ Construção de agentes de notícias hiper-personalizados&lt;br&gt;
✔️ Uso de React e IA no desenvolvimento&lt;br&gt;
✔️ Desafios DevChallenge e Frontend Challenges&lt;br&gt;
✔️ Técnicas e práticas em JavaScript e web em geral&lt;/p&gt;

&lt;p&gt;Isso demonstra que você compartilha conhecimento prático e atual, contribuindo com a comunidade de desenvolvedores e fortalecendo sua marca pessoal. &lt;br&gt;
DEV Community&lt;/p&gt;

&lt;p&gt;💼 LinkedIn — Projetos e Portfólio&lt;/p&gt;

&lt;p&gt;No LinkedIn você tem compartilhado projetos e atualizações que demonstram evolução técnica e aplicação prática:&lt;/p&gt;

&lt;p&gt;🧠 Projetos compartilhados em 2025&lt;/p&gt;

&lt;p&gt;✔️ Aplicação web que consulta CNPJs pela Brasil API e envia os resultados por e-mail, um exemplo claro de integração de APIs e automação de fluxo de dados. &lt;/p&gt;

&lt;p&gt;✔️ Postagens sobre uso de Prisma e Turso (tecnologias modernas de banco de dados/infra). &lt;/p&gt;

&lt;p&gt;Essas postagens mostram que você está desenvolvendo soluções completas, explorando stacks modernas e compartilhando essa evolução com profissionais da sua rede.&lt;/p&gt;

&lt;p&gt;📊 Principais Conquistas e Aprendizados — 2025&lt;br&gt;
🚀 Desenvolvimento Técnico&lt;/p&gt;

&lt;p&gt;✔️ Fortalecimento em Full-stack development (React, Node.js, TypeScript)&lt;br&gt;
✔️ Projetos com IA e APIs avançadas (OpenAI, Brasil API)&lt;br&gt;
✔️ Continuação de projetos open-source relevantes e úteis&lt;/p&gt;

&lt;p&gt;📣 Conteúdo e Comunidade&lt;/p&gt;

&lt;p&gt;✔️ Produção consistente de artigos técnicos úteis no dev.to&lt;br&gt;
✔️ Participação ativa com comentários e engajamento&lt;br&gt;
✔️ Construção de autoridade técnica na comunidade&lt;/p&gt;

&lt;p&gt;🌐 Visibilidade e Engajamento&lt;/p&gt;

&lt;p&gt;✔️ Boa rede de seguidores no GitHub&lt;br&gt;
✔️ Conteúdo técnico reconhecido por badges e participação comunitária&lt;br&gt;
✔️ Postagens no LinkedIn com foco em aprendizado e soluções práticas&lt;/p&gt;

&lt;p&gt;🎯 O que isso significa para sua carreira&lt;/p&gt;

&lt;p&gt;Em 2025 você consolidou:&lt;/p&gt;

&lt;p&gt;✨ Sua presença como desenvolvedor completo, não só codificando, mas também compartilhando conhecimento.&lt;br&gt;
✨ A capacidade de entregar soluções práticas, integrando APIs, automação, design e IA.&lt;br&gt;
✨ Uma comunidade confiável ao seu redor (seguidores no GitHub e leitores no dev.to).&lt;/p&gt;

&lt;p&gt;Isso é um equilíbrio valioso entre produção técnica e influência comunitária — ideal para quem mira oportunidades como consultoria, liderança técnica ou desenvolvimento de produtos digitais próprios.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Bora construir um Agente de Notícias Hiper-Personalizado? 🤖📰 (Codar Juntos)</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Sat, 20 Dec 2025 02:37:43 +0000</pubDate>
      <link>https://forem.com/carlosorioli/bora-construir-um-agente-de-noticias-hiper-personalizado-coding-together-1knm</link>
      <guid>https://forem.com/carlosorioli/bora-construir-um-agente-de-noticias-hiper-personalizado-coding-together-1knm</guid>
      <description>&lt;h3&gt;
  
  
  A ideia: Chega de newsletter genérica!
&lt;/h3&gt;

&lt;p&gt;Você já percebeu que a maioria das newsletters de tech ou são genéricas demais ou só cobrem o que acontece no Vale do Silício? Eu decidi mudar isso criando um &lt;strong&gt;Software Agêntico&lt;/strong&gt; que faz curadoria sob medida, e quero convidar vocês para codarem comigo.&lt;/p&gt;

&lt;p&gt;Não é só um chatbot. É um &lt;strong&gt;agente autônomo&lt;/strong&gt; que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Varre a web em tempo real&lt;/strong&gt; usando Tavily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtra por País e Idioma&lt;/strong&gt;: Você quer notícias sobre IA que saíram no Japão, mas resumidas em Português? O agente resolve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sintetiza com Gemini 1.5 Pro&lt;/strong&gt;: O "cérebro" que traduz, resume e formata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entrega via Resend&lt;/strong&gt;: Automação direto para a sua inbox (ou de uma audiência inteira).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  A Stack (Modern &amp;amp; Clean) 💻
&lt;/h3&gt;

&lt;p&gt;Escolhi essa stack para ser fácil de subir, mas potente o suficiente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js (Vercel)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligence:&lt;/strong&gt; Gemini SDK + Tavily API (Os olhos e o cérebro)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database &amp;amp; ORM:&lt;/strong&gt; MongoDB + Prisma (para salvar as preferências de cada user)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-mail:&lt;/strong&gt; Resend (usando Audiences para escalabilidade)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design de E-mail:&lt;/strong&gt; MJML (para garantir que o e-mail seja responsivo em tudo)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  O Plano de Voo 🚀
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[x] Definir a arquitetura (Prisma + Mongo).&lt;/li&gt;
&lt;li&gt;[x] Criar o formulário de captura de preferências (Temas, Países, Idiomas).&lt;/li&gt;
&lt;li&gt;[X] Orquestrar o loop do agente: Pesquisa -&amp;gt; Resumo -&amp;gt; Tradução.&lt;/li&gt;
&lt;li&gt;[X] Configurar o Cron Job na Vercel para o envio semanal automático.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Por que estou postando isso?
&lt;/h3&gt;

&lt;p&gt;Quero aprender em público e trocar ideia com quem também está explorando o mundo de &lt;strong&gt;AI Agents&lt;/strong&gt;. Se você manja de TypeScript, quer entender como orquestrar LLMs além do "prompt básico" ou quer discutir arquitetura de banco de dados, esse projeto é pra você.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Como você pode colar junto:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Comenta aí:&lt;/strong&gt; Qual feature você adicionaria em um agente de notícias?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Qual parte te interessa mais? (Prompt Engineering, Integração de APIs ou o Frontend no Next?)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; Vou liberar o repo com a aplicação completa!&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  🔑 As 5 Contas Necessárias para o Projeto
&lt;/h3&gt;

&lt;p&gt;Para construir este software agêntico, precisaremos integrar os melhores serviços de IA e infraestrutura do mercado. Antes de começar o código, crie suas contas e pegue suas chaves de API:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt; 🐙 (Onde o código vive)&lt;br&gt;
&lt;strong&gt;Para que serve:&lt;/strong&gt; Hospedar o seu repositório, gerenciar versões e permitir que outras pessoas colaborem com o seu projeto.&lt;br&gt;
&lt;a href="https://github.com/" rel="noopener noreferrer"&gt;Criar conta no GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google AI Studio (Gemini)&lt;/strong&gt; 🧠 (O cérebro)&lt;br&gt;
&lt;strong&gt;Para que serve:&lt;/strong&gt; É aqui que você gera a sua &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;. O Gemini 2.5 será o responsável por raciocinar sobre as notícias, traduzir e formatar o e-mail.&lt;br&gt;
&lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Pegar API Key do Gemini&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tavily AI&lt;/strong&gt; 🔍 (Os olhos)&lt;br&gt;
&lt;strong&gt;Para que serve:&lt;/strong&gt; Diferente do Google comum, o Tavily é um motor de busca feito especificamente para agentes de IA. Ele retorna resultados limpos e otimizados para que o Gemini possa ler.&lt;br&gt;
&lt;a href="https://tavily.com/" rel="noopener noreferrer"&gt;Criar conta no Tavily&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resend&lt;/strong&gt; 📧 (O mensageiro)&lt;br&gt;
&lt;strong&gt;Para que serve:&lt;/strong&gt; Plataforma moderna para envio de e-mails transacionais. Vamos usá-la para disparar a newsletter e gerenciar a lista de inscritos (Audiences).&lt;br&gt;
&lt;a href="https://resend.com/" rel="noopener noreferrer"&gt;Criar conta no Resend&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vercel&lt;/strong&gt; ▲ (A casa do projeto)&lt;br&gt;
&lt;strong&gt;Para que serve:&lt;/strong&gt; Onde faremos o deploy da nossa aplicação Next.js. Além disso, usaremos o &lt;strong&gt;Vercel Cron Jobs&lt;/strong&gt; para fazer o agente "acordar" sozinho toda semana.&lt;br&gt;
&lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Criar conta na Vercel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  💡 Dica de Segurança
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nunca&lt;/strong&gt; suba suas chaves de API diretamente no GitHub! No Dia 1 do vídeo, mostro como usar o arquivo &lt;code&gt;.env&lt;/code&gt; para manter essas chaves seguras apenas na sua máquina e nas configurações da Vercel.&lt;/p&gt;




&lt;h2&gt;
  
  
  📅 Plano de Desenvolvimento Detalhado
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dia 1: Estrutura Base e Banco de Dados
&lt;/h3&gt;

&lt;p&gt;O objetivo hoje é ter o projeto rodando localmente e o banco pronto para receber inscritos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup:&lt;/strong&gt; &lt;code&gt;npx create-next-app@latest ai-newsletter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Libs:&lt;/strong&gt; &lt;code&gt;@prisma/client&lt;/code&gt;, &lt;code&gt;@google/generative-ai&lt;/code&gt;, &lt;code&gt;@tavily/core&lt;/code&gt;, &lt;code&gt;resend&lt;/code&gt;, &lt;code&gt;zod&lt;/code&gt;, &lt;code&gt;mjml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DB:&lt;/strong&gt; Configurar o &lt;code&gt;schema.prisma&lt;/code&gt; com o modelo &lt;code&gt;Subscriber&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/BabkIluDwS8"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Dia 2: Frontend e Captura de Leads
&lt;/h3&gt;

&lt;p&gt;Interface onde o usuário escolhe seus interesses.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Formulário:&lt;/strong&gt; Inputs de E-mail, Selects para País/Idioma e Checkboxes para Temas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API:&lt;/strong&gt; Rota &lt;code&gt;/api/subscribe&lt;/code&gt; para salvar no MongoDB via Prisma.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/EeVSmJd-7_k"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Dia 3: O Cérebro do Agente (Core Logic)
&lt;/h3&gt;

&lt;p&gt;A "mágica" agêntica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search &amp;amp; Synthesis:&lt;/strong&gt; Função que integra Tavily (busca) com Gemini (raciocínio).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Engineering:&lt;/strong&gt; Instruir o Gemini a formatar especificamente para o idioma do usuário.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/opUgiQRvgt0"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Dia 4: Integração Resend e Loop de Envio
&lt;/h3&gt;

&lt;p&gt;Transformar o conteúdo em e-mails reais.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MJML Integration:&lt;/strong&gt; Usar MJML para garantir que o layout gerado pela IA seja responsivo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Logic:&lt;/strong&gt; Rota que processa todos os inscritos e dispara os envios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/eepMvxilXbo"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Dia 5: Deploy e Automação na Vercel
&lt;/h3&gt;

&lt;p&gt;O agente ganha vida própria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vercel Cron:&lt;/strong&gt; Configurar o &lt;code&gt;vercel.json&lt;/code&gt; para o agendamento (ex: toda segunda às 9h).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teste Final:&lt;/strong&gt; Cadastro real e validação do recebimento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/uK3SP4_K6gY"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/rogeriorioli/agentic-newsletter" rel="noopener noreferrer"&gt;GITHUB DO PROJETO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bora parar de só dar "oi" pro ChatGPT e começar a construir ferramentas que realmente entregam valor de forma autônoma. 🚀&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>gemini</category>
      <category>programming</category>
    </item>
    <item>
      <title>Acendendo Velas (e Códigos) com React e IA neste Chanucá!</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Tue, 09 Dec 2025 12:01:37 +0000</pubDate>
      <link>https://forem.com/carlosorioli/acendendo-velas-e-codigos-com-react-e-ia-neste-chanuca-2632</link>
      <guid>https://forem.com/carlosorioli/acendendo-velas-e-codigos-com-react-e-ia-neste-chanuca-2632</guid>
      <description>&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%2Fm6uqy9b6jpcrpttweszu.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%2Fm6uqy9b6jpcrpttweszu.png" alt="Acendendo Velas (e Códigos) com React e IA neste Chanucá!" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🕎 Acendendo Velas (e Códigos) com React e IA neste Chanucá! ✨
&lt;/h2&gt;

&lt;p&gt;Neste Chanucá, decidi ir além do convencional e unir tradição milenar com tecnologia de ponta. O resultado é uma &lt;strong&gt;Hanukiá interativa&lt;/strong&gt; que não é apenas um código bonito, mas que também &lt;strong&gt;respeita o calendário real da festividade!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Minha aplicação garante que as velas só podem ser acesas nos &lt;strong&gt;dias e horários corretos&lt;/strong&gt; (sim, a validação de data está rigorosa!). E para deixar a experiência ainda mais mágica, o app traz &lt;strong&gt;histórias e receitas exclusivas&lt;/strong&gt; geradas usando Inteligência Artificial. 🤯&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ A Stack por Trás do Milagre
&lt;/h2&gt;

&lt;p&gt;Foco total em performance e interatividade! Veja o que usei para construir este projeto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; &lt;strong&gt;React 19 + Vite&lt;/strong&gt; (Para uma performance instantânea e desenvolvimento rápido).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estilo:&lt;/strong&gt; &lt;strong&gt;Tailwind CSS&lt;/strong&gt; (Para um visual moderno, responsivo e sem dores de cabeça).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animações:&lt;/strong&gt; &lt;strong&gt;Framer Motion&lt;/strong&gt; (Essencial para o efeito &lt;em&gt;drag &amp;amp; drop&lt;/em&gt; das velas e as animações realistas da chama 🔥).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lógica Principal:&lt;/strong&gt; Validação de datas complexa para garantir a &lt;strong&gt;fidelidade à tradição judaica&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Mágica da IA:&lt;/strong&gt; Integração com a &lt;strong&gt;API do Google Gemini&lt;/strong&gt; para gerar curiosidades históricas e conteúdos culinários únicos a cada interação do usuário.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Foi um desafio técnico super divertido implementar as regras de data &lt;em&gt;junto&lt;/em&gt; com a interatividade dinâmica proporcionada pela IA.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Quer Acender Uma Vela?
&lt;/h2&gt;

&lt;p&gt;Dê uma olhada no projeto e me diga o que achou!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://lnkd.in/dQHfHR9c" rel="noopener noreferrer"&gt;Live Demo da Hanukiá&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://lnkd.in/dVZGtXQE" rel="noopener noreferrer"&gt;Código Fonte no GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Vamos Trocar Uma Ideia!
&lt;/h2&gt;

&lt;p&gt;Se você curte &lt;strong&gt;React&lt;/strong&gt;, se já fez alguma integração divertida com &lt;strong&gt;LLMs (Large Language Models)&lt;/strong&gt;, ou se simplesmente quer compartilhar sua tradição festiva favorita (de qualquer cultura!), &lt;strong&gt;deixa um comentário!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>googleaichallenge</category>
      <category>ai</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>SEO &amp; OG Analyzer whit AI</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Sat, 22 Nov 2025 17:29:56 +0000</pubDate>
      <link>https://forem.com/carlosorioli/seo-og-analyzer-whit-ai-1724</link>
      <guid>https://forem.com/carlosorioli/seo-og-analyzer-whit-ai-1724</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is my submission for &lt;a href="https://dev.to/deved/build-apps-with-google-ai-studio"&gt;DEV Education Track: Build Apps with Google AI Studio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built the &lt;strong&gt;SEO &amp;amp; OG Analyzer AI&lt;/strong&gt;, a comprehensive web tool that helps developers and marketers optimize their websites instantly.&lt;/p&gt;

&lt;p&gt;Users simply paste a URL, and the app uses Google Gemini to simulate a crawl, analyzing the page's content to generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open Graph Previews:&lt;/strong&gt; A visual simulation of how the link looks on social media (Facebook/LinkedIn).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO Audit:&lt;/strong&gt; An analysis of titles, descriptions, headings, and missing tags with AI-suggested improvements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Data:&lt;/strong&gt; Automatically generated, valid JSON-LD schemas (Organization, Article, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ready-to-use Code:&lt;/strong&gt; HTML meta tags and JSON scripts formatted for copy-pasting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I utilized the &lt;strong&gt;Gemini API (gemini-2.5-flash)&lt;/strong&gt; with the &lt;strong&gt;Google Search Tool (googleSearch)&lt;/strong&gt; to allow the AI to fetch real-time context about the URL without needing a complex backend web scraper.&lt;/p&gt;

&lt;p&gt;The UI is built with &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;TypeScript&lt;/strong&gt;, and &lt;strong&gt;Tailwind CSS&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&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%2Fylynqezn2zrsej66xs31.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%2Fylynqezn2zrsej66xs31.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Features in Action
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual Preview:&lt;/strong&gt; See exactly how your link appears on social networks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Insights:&lt;/strong&gt; Gemini critiques your current SEO strategy and suggests specific keywords and headings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Generation:&lt;/strong&gt; Get the exact &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tags and JSON-LD needed to fix the site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://ia-seo-gen.vercel.app/" rel="noopener noreferrer"&gt;https://ia-seo-gen.vercel.app/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/rogeriorioli/IA-SEO-GEN" rel="noopener noreferrer"&gt;https://github.com/rogeriorioli/IA-SEO-GEN&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  My Experience
&lt;/h2&gt;

&lt;p&gt;Working through this track taught me that &lt;strong&gt;Prompt Engineering can effectively replace complex backend logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Traditionally, building this app would require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a web scraping library (like &lt;strong&gt;Puppeteer&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;a parsing library (like &lt;strong&gt;Cheerio&lt;/strong&gt;),&lt;/li&gt;
&lt;li&gt;and complex logic to extract metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Gemini, I simply provided a prompt acting as a &lt;em&gt;"Technical SEO Expert"&lt;/em&gt; and used the &lt;strong&gt;googleSearch&lt;/strong&gt; tool to do the heavy lifting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strict JSON Handling:&lt;/strong&gt;
The biggest challenge was ensuring the AI returned parsable JSON.
I learned to implement robust error handling to strip Markdown code blocks (

```

json) and clean up the response before parsing it in the frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tool Use:&lt;/strong&gt;&lt;br&gt;
Enabling the &lt;strong&gt;googleSearch&lt;/strong&gt; tool was a game-changer. It allowed the model to &lt;em&gt;"see"&lt;/em&gt; the website in real-time rather than hallucinating content based on the URL string alone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Speed:&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;gemini-2.5-flash&lt;/strong&gt; model is incredibly fast, making the user experience feel almost instantaneous, even while performing complex analysis.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This project showed me that &lt;strong&gt;AI isn't just for chatbots—it's a powerful engine for structural analysis and code generation.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>deved</category>
      <category>learngoogleaistudio</category>
      <category>ai</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Helloween AI chat agent</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Sun, 26 Oct 2025 12:31:01 +0000</pubDate>
      <link>https://forem.com/carlosorioli/helloween-ai-chat-agent-1o8j</link>
      <guid>https://forem.com/carlosorioli/helloween-ai-chat-agent-1o8j</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2025-10-15"&gt;Frontend Challenge - Halloween Edition, Perfect Landing&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Hello Chat is an interactive AI-powered chat interface with a spooky Halloween theme. I created a modern chat application similar to ChatGPT, but with a festive Halloween twist that keeps the spooky spirit alive year-round!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎃 &lt;strong&gt;Halloween-themed UI&lt;/strong&gt; with custom spooky animations (floating ghosts, glowing pumpkins)&lt;/li&gt;
&lt;li&gt;👻 &lt;strong&gt;AI Assistant powered by Google Gemini&lt;/strong&gt; that responds exclusively about Halloween topics&lt;/li&gt;
&lt;li&gt;🧛 &lt;strong&gt;Smart topic redirection&lt;/strong&gt; - the AI politely redirects off-topic conversations back to Halloween themes&lt;/li&gt;
&lt;li&gt;🌍 &lt;strong&gt;Multi-language support&lt;/strong&gt; with an easy toggle between Portuguese 🇧🇷 and English 🇺🇸&lt;/li&gt;
&lt;li&gt;💀 &lt;strong&gt;Modern, responsive design&lt;/strong&gt; with custom dark color scheme and animations&lt;/li&gt;
&lt;li&gt;🕷️ &lt;strong&gt;Real-time chat interface&lt;/strong&gt; with smooth message animations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Halloween Theme:&lt;/strong&gt;&lt;br&gt;
I chose a dark, atmospheric gradient background (purple to black) with vibrant orange accents - the classic Halloween color palette. The interface includes animated emojis (🎃👻🦇🧛💀) that float and glow, creating an immersive Halloween atmosphere. Custom CSS animations make the ghosts float up and down, and pumpkins glow with a pulsing effect.&lt;/p&gt;

&lt;p&gt;The chat interface itself is styled to feel modern and clean (like ChatGPT/Gemini) but with that spooky Halloween touch - black message bubbles with orange borders for the AI, and vibrant orange bubbles for user messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🚀 Live Demo:&lt;/strong&gt; &lt;a href="https://hello-chat-lime.vercel.app/" rel="noopener noreferrer"&gt;HELLO AGENT CHAT&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📦 Repository:&lt;/strong&gt; &lt;a href="https://github.com/rogeriorioli/hello_chat" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💻 Local Demo:&lt;/strong&gt; Clone the repo and run &lt;code&gt;npm run dev&lt;/code&gt;, then visit &lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏗️ Tech Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 14 with App Router&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS with custom Halloween theme&lt;/li&gt;
&lt;li&gt;Google Gemini API&lt;/li&gt;
&lt;li&gt;Custom internationalization system&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Development Process
&lt;/h3&gt;

&lt;p&gt;I started by setting up a fresh Next.js 14 project with TypeScript and Tailwind CSS. The first challenge was designing a Halloween theme that felt spooky and festive without being overwhelming or cliché. I spent time experimenting with color combinations and settled on a dark gradient (purple to black) with orange accents - staying true to Halloween traditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Challenges Overcome
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google Gemini API Integration:&lt;/strong&gt; The initial struggle was getting the API key configuration right and handling different Gemini model versions. I implemented a robust fallback system to handle API changes gracefully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;System Prompt Engineering:&lt;/strong&gt; Creating a system prompt that keeps the AI focused on Halloween topics while remaining helpful and friendly was tricky. The AI now intelligently redirects off-topic conversations while maintaining user engagement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building a Custom i18n System:&lt;/strong&gt; Since I wanted multi-language support but didn't want to add heavy dependencies, I built a lightweight translation system from scratch. It's simple, effective, and easy to extend to more languages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Comprehensive Error Handling:&lt;/strong&gt; I implemented user-friendly error messages that are helpful and thematic - they guide users through API key setup while maintaining the Halloween atmosphere.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What I'm Proud Of
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smooth CSS Animations:&lt;/strong&gt; The floating ghost and glowing pumpkin animations create an immersive Halloween atmosphere without being distracting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design:&lt;/strong&gt; The chat interface looks beautiful and works seamlessly on all screen sizes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience:&lt;/strong&gt; The language toggle is intuitive, positioned in the header with clear visual indicators&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Messages:&lt;/strong&gt; Even error messages are themed and helpful - they guide users through setup while keeping the spooky mood&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Organization:&lt;/strong&gt; Clean separation of concerns with translations in a dedicated module, making it easy to maintain and extend&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I Learned
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How to integrate Google Gemini API with Next.js API routes and handle different model versions&lt;/li&gt;
&lt;li&gt;Building a custom internationalization system without heavy frameworks&lt;/li&gt;
&lt;li&gt;Creating engaging CSS animations that enhance UX without being distracting&lt;/li&gt;
&lt;li&gt;Environment variable management in Next.js and deployment best practices&lt;/li&gt;
&lt;li&gt;User-friendly error handling that guides users through setup issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I Hope to Do Next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add more languages (Spanish 🇪🇸, French 🇫🇷)&lt;/li&gt;
&lt;li&gt;Implement message history persistence using localStorage or a database&lt;/li&gt;
&lt;li&gt;Add voice input capability for hands-free spooky chats&lt;/li&gt;
&lt;li&gt;Create multiple Halloween themes (pumpkin patch, graveyard, haunted house) that users can choose&lt;/li&gt;
&lt;li&gt;Add more custom emojis and expand the animation library&lt;/li&gt;
&lt;li&gt;Implement a dark/light mode toggle for different viewing preferences&lt;/li&gt;
&lt;li&gt;Add Halloween sound effects for a more immersive experience&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 18+ installed&lt;/li&gt;
&lt;li&gt;A Google Gemini API key (&lt;a href="https://makersuite.google.com/app/apikey" rel="noopener noreferrer"&gt;get one here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repository-url&amp;gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;hello-chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install dependencies:
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file in the root directory:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add your Gemini API key to &lt;code&gt;.env.local&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GEMINI_API_KEY=your_actual_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the development server:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in your browser&lt;/li&gt;
&lt;/ol&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello-chat/
├── app/
│   ├── api/
│   │   └── chat/
│   │       └── route.ts       # Gemini API integration
│   ├── globals.css            # Global styles &amp;amp; animations
│   ├── layout.tsx             # Root layout
│   └── page.tsx               # Main chat interface
├── lib/
│   ├── translations.ts        # Internationalization system
│   └── README.md             # Translation documentation
├── .env.example               # Environment variables template
└── package.json               # Dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;MIT License - Feel free to use this project for your own spooky creations! 🎃&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>frontendchallenge</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>SKATEBOARD DECK DESIGN HELLOWEEN</title>
      <dc:creator>Carlos Rogerio Orioli</dc:creator>
      <pubDate>Thu, 23 Oct 2025 12:00:40 +0000</pubDate>
      <link>https://forem.com/carlosorioli/skateboard-helloween-4igm</link>
      <guid>https://forem.com/carlosorioli/skateboard-helloween-4igm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2025-10-15"&gt;Frontend Challenge - Halloween Edition, Perfect Landing&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;interactive landing page&lt;/strong&gt; where users can &lt;strong&gt;customize their own skateboard shape&lt;/strong&gt; with &lt;strong&gt;Halloween-themed prints&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The page mixes &lt;strong&gt;punk, horror, and Halloween aesthetics&lt;/strong&gt;, featuring dark tones, neon accents, and creepy visuals like skulls, pumpkins, and ghosts.  &lt;/p&gt;

&lt;p&gt;Users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose a print&lt;/strong&gt; from a gallery of Halloween designs and see it instantly applied to the &lt;strong&gt;skateboard mockup&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload their own artwork&lt;/strong&gt; (PNG, JPG, or SVG) to create a truly unique and scary board.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buy the customized skateboard&lt;/strong&gt; directly through a purchase button.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to blend &lt;strong&gt;interactivity and e-commerce&lt;/strong&gt; with a strong &lt;strong&gt;Halloween visual identity&lt;/strong&gt;, appealing to skateboarders who love edgy, horror-inspired art.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🚀 &lt;strong&gt;Live Demo:&lt;/strong&gt;  &lt;a href="https://custom-helloween-skateboard-deck.vercel.app/" rel="noopener noreferrer"&gt;https://custom-helloween-skateboard-deck.vercel.app/&lt;/a&gt;&lt;br&gt;
🧠 &lt;strong&gt;Code Repository:&lt;/strong&gt; &lt;a href="https://github.com/rogeriorioli/custom-helloween-skateboard-deck" rel="noopener noreferrer"&gt;https://github.com/rogeriorioli/custom-helloween-skateboard-deck&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;This project was a blast to build!&lt;br&gt;&lt;br&gt;
I started with the idea of bringing &lt;strong&gt;Halloween energy into the skate culture&lt;/strong&gt;, combining both worlds through a clean yet chaotic interface.  &lt;/p&gt;

&lt;p&gt;Technically, I used &lt;strong&gt;React + TailwindCSS&lt;/strong&gt;, and implemented interative click to image to overlay prints onto the skateboard shape dynamically.&lt;br&gt;&lt;br&gt;
The biggest challenge was making the image overlay feel natural and visually satisfying — like a real printed shape.  &lt;/p&gt;

&lt;p&gt;What I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to handle &lt;strong&gt;image layering and uploads&lt;/strong&gt; efficiently in React.
&lt;/li&gt;
&lt;li&gt;How to design a &lt;strong&gt;dark, high-contrast UI&lt;/strong&gt; that’s still visually balanced.
&lt;/li&gt;
&lt;li&gt;The importance of subtle animations and small visual details (hover glows, fades, etc.) to create immersion.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy Halloween 🎃&lt;br&gt;&lt;br&gt;
&lt;em&gt;May your code be spooky and your UI delightfully haunted!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>frontendchallenge</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
