<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Alvaro Camillo Neto]]></title><description><![CDATA[Desenvolvedor e palestrinha]]></description><link>https://alvarocamillont.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1560517105707/l2Pv0Oaep.png</url><title>Alvaro Camillo Neto</title><link>https://alvarocamillont.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Apr 2026 18:28:54 GMT</lastBuildDate><atom:link href="https://alvarocamillont.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Construindo um App com IA: Um Guia com Angular, Genkit e o Poder do Gemini no Mundo de Naruto]]></title><description><![CDATA[E aí, dev? Se você é fã de animes e de desenvolvimento de software, vai adorar este projeto. Que tal unir a força do universo Naruto com o poder da Inteligência Artificial para criar uma aplicação moderna?
Neste artigo, vamos construir o "Hokage Desk...]]></description><link>https://alvarocamillont.dev/construindo-um-app-com-ia-um-guia-com-angular-genkit-e-o-poder-do-gemini-no-mundo-de-naruto</link><guid isPermaLink="true">https://alvarocamillont.dev/construindo-um-app-com-ia-um-guia-com-angular-genkit-e-o-poder-do-gemini-no-mundo-de-naruto</guid><category><![CDATA[gemini]]></category><category><![CDATA[Angular]]></category><category><![CDATA[firebase genkit]]></category><category><![CDATA[genkit]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Mon, 15 Dec 2025 12:18:47 GMT</pubDate><content:encoded><![CDATA[<p>E aí, dev? Se você é fã de animes e de desenvolvimento de software, vai adorar este projeto. Que tal unir a força do universo Naruto com o poder da Inteligência Artificial para criar uma aplicação moderna?</p>
<p>Neste artigo, vamos construir o "Hokage Desk": um aplicativo onde você descreve uma missão ninja e uma IA, agindo como um mestre de Konoha, gera um pergaminho de missão completo. Para isso, usaremos <strong>Angular</strong> no front-end e, no back-end, a dupla dinâmica <strong>Genkit</strong> e a <strong>API do Gemini</strong>, a mais nova geração de modelos de IA do Google.</p>
<p>Prepare-se para mergulhar em um projeto que combina uma API de IA de ponta com um dos universos mais amados da cultura pop. Vamos nessa?</p>
<h2 id="heading-pre-requisitos">Pré-requisitos</h2>
<p>Antes de começarmos nossa jornada ninja, garanta que você tenha as seguintes ferramentas instaladas em sua máquina:</p>
<ul>
<li><p><strong>Node.js:</strong> <a target="_blank" href="https://www.google.com/url?q=https%3A%2F%2Fnodejs.org%2F">https://nodejs.org/</a></p>
</li>
<li><p><strong>Angular CLI:</strong> <code>npm install -g @angular/cli</code></p>
</li>
<li><p><strong>Git:</strong> <a target="_blank" href="https://www.google.com/url?q=https%3A%2F%2Fgit-scm.com%2F">https://git-scm.com/</a></p>
</li>
</ul>
<h3 id="heading-obtendo-sua-chave-de-api-do-gemini">Obtendo sua Chave de API do Gemini</h3>
<p>Para que nossa IA funcione, precisamos de uma chave de API do Gemini. É grátis e fácil de conseguir.</p>
<ol>
<li><p>Acesse o <a target="_blank" href="https://aistudio.google.com/app"><strong>Google AI Studio</strong></a>.</p>
</li>
<li><p>Faça login com sua conta do Google.</p>
</li>
<li><p>No menu à esquerda, clique em <strong>"Get API key"</strong>.</p>
</li>
<li><p>Clique em <strong>"Create API key in new project"</strong>.</p>
</li>
<li><p>Copie a chave de API gerada. Ela será seu passe para o mundo da IA.</p>
</li>
</ol>
<h3 id="heading-configurando-a-variavel-de-ambiente">Configurando a Variável de Ambiente</h3>
<p>O Genkit precisa "ler" essa chave. Para isso, crie uma variável de ambiente em seu sistema chamada <code>GOOGLE_API_KEY</code> com a chave que você copiou.</p>
<pre><code class="lang-bash">GOOGLE_API_KEY=&lt;SUA_API_KEY&gt;
</code></pre>
<hr />
<h2 id="heading-1-criando-o-projeto-angular-a-fundacao-da-aldeia">1. Criando o Projeto Angular: A Fundação da Aldeia</h2>
<p>Vamos começar erguendo as estruturas da nossa aplicação com o Angular CLI. Vamos criar um projeto já com Server-Side Rendering (SSR) ativado, o que é uma ótima prática.</p>
<pre><code class="lang-bash">ng new hokage-desk --ssr
</code></pre>
<p>Quando perguntado sobre o sistema de CSS, escolha <strong>Tailwind CSS</strong>, pois ele nos dará a agilidade necessária para estilizar nossa aldeia digital.</p>
<p>Com o projeto criado, instale as dependências que usaremos para o Genkit e o servidor Express:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> hokage-desk
npm i genkit
npm i express@^4.21.1
npm i @genkit-ai/express
npm i @genkit-ai/google-genai
npm i zod@^3.25
npm i uuid
</code></pre>
<hr />
<h2 id="heading-2-configurando-o-fluxo-do-genkit-o-cerebro-da-operacao">2. Configurando o Fluxo do Genkit: O Cérebro da Operação</h2>
<p>Agora, vamos para a parte mais legal: criar o cérebro de IA que irá gerar nossas missões.</p>
<h3 id="heading-crie-o-arquivo-de-fluxo">Crie o Arquivo de Fluxo</h3>
<p>Dentro da pasta <code>src/</code>, crie um novo arquivo chamado <code>flows.ts</code>. É aqui que a mágica vai acontecer.</p>
<h3 id="heading-definindo-o-fluxo">Definindo o Fluxo</h3>
<p>Abra o arquivo <code>src/flows.ts</code> e cole o código a seguir. Este é o coração da nossa funcionalidade.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { genkit } <span class="hljs-keyword">from</span> <span class="hljs-string">'genkit'</span>;
<span class="hljs-keyword">import</span> { z } <span class="hljs-keyword">from</span> <span class="hljs-string">'zod'</span>;
<span class="hljs-keyword">import</span> { googleAI } <span class="hljs-keyword">from</span> <span class="hljs-string">'@genkit-ai/google-genai'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-keyword">const</span> ai = genkit({
  plugins: [googleAI()],
  model: googleAI.model(<span class="hljs-string">'gemini-2.5-flash'</span>, {
    temperature: <span class="hljs-number">0.8</span>,
  }),
});

<span class="hljs-comment">// Define input schema</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MissionDefinitionSchema = z.object({
  definition: z.string().describe(<span class="hljs-string">'Definition of the mission'</span>),
});

<span class="hljs-comment">// Define output schema</span>
<span class="hljs-comment">// Final schema for the Ninja Mission</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> missionSchema = z
  .object({
    id: z.string().describe(<span class="hljs-string">'Unique identifier for the mission'</span>),
    title: z.string().describe(<span class="hljs-string">'A creative and fitting title for the mission.'</span>),
    difficulty: z
      .string()
      .describe(
        <span class="hljs-string">'Classify the mission into one of the following ranks, based on its complexity and danger: D, C, B, A, or S.'</span>
      ),
    missionValue: z
      .string()
      .describe(
        <span class="hljs-string">"Define a reward in Ryō. The value must be consistent with the mission's difficulty (e.g., Rank-D missions are low-value, Rank-S missions are very high-value)."</span>
      ),
    detailedDescription: z
      .string()
      .describe(
        <span class="hljs-string">"Create a detailed, narrative-style mission briefing based on the user's initial input. It should include the background context, a clear primary objective, known risks or enemy intel, and the mission's location. This should read like an official mission scroll given to the team leader."</span>
      ),
    ninjaTeamLevel: z
      .string()
      .describe(
        <span class="hljs-string">'Based on the mission\'s difficulty, suggest the team\'s rank. Use standard Naruto ranks like Genin, Chunin, Jonin, or ANBU. For legendary missions, you could even specify Sannin ou Kage-level.'</span>
      ),
    assignedTeam: z
      .string()
      .describe(
        <span class="hljs-string">"Assign a suitable team. If a known, official team from the Naruto or Boruto universe fits the mission and members (e.g., 'Team 7', 'Ino-Shika-Cho', 'Team Guy'), use its official name. If no existing team is a perfect fit, create a new, thematic squad name (e.g., 'Sand Village Barrier Unit', 'Mist Village Cipher Squad')."</span>
      ),
    teamMembers: z
      .array(
        z.object({
          name: z
            .string()
            .describe(
              <span class="hljs-string">"Select a real character from the Naruto or Boruto anime who would be suitable for this mission's rank and objective."</span>
            ),
          specialty: z
            .string()
            .describe(
              <span class="hljs-string">"State this character's known signature jutsu or primary skill (e.g., 'Rasengan', 'Sharingan', 'Byakugan', 'Shadow Possession Jutsu')."</span>
            ),
        })
      )
      .describe(
        <span class="hljs-string">'A list containing exactly 3 members for the ninja team. The members chosen must be real characters from Naruto or Boruto.'</span>
      ),
  })
  .describe(<span class="hljs-string">'The complete mission file in JSON format.'</span>);

<span class="hljs-comment">// Define a recipe generator flow</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> missionGeneratorFlow = ai.defineFlow(
  {
    name: <span class="hljs-string">'missionGeneratorFlow'</span>,
    inputSchema: MissionDefinitionSchema,
    outputSchema: missionSchema,
  },
  <span class="hljs-keyword">async</span> (input) =&gt; {
    <span class="hljs-comment">// Create a prompt based on the input</span>
    <span class="hljs-keyword">const</span> prompt = <span class="hljs-string">`
        You are a mission assignment expert from Konohagakure, with deep knowledge of every shinobi and official team from both the Naruto and Boruto eras.
        Your primary task is to take a brief mission concept and expand it into a complete, official mission file. The initial concept from the user is: "<span class="hljs-subst">${input.definition}</span>".
        All generated content must be in the same language as the user's input.
        IMPORTANT LOGIC:
        1.  Generate a creative and fitting title for the mission.
        2.  Elaborate on the user's concept to create a detailed mission description, including background, objectives, and known risks.
        3.  Select REAL characters from the Naruto or Boruto universe for the team. The team composition must be logical for the mission's assigned difficulty. Do not assign Kage-level shinobi to a D-rank mission.
        4.  For the team name, prioritize using an official team name (e.g., 'Team 7') if the members align. Otherwise, create a fitting squad name.
        Generate the output in the requested JSON format.
      `</span>;

    <span class="hljs-comment">// Generate structured recipe data using the same schema</span>
    <span class="hljs-keyword">const</span> { output } = <span class="hljs-keyword">await</span> ai.generate({
      prompt,
      output: { schema: missionSchema },
    });

    <span class="hljs-keyword">if</span> (!output) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Failed to generate recipe'</span>);

    <span class="hljs-keyword">return</span> {
      ...output,
      id: uuidv4(),
    };
  }
);
</code></pre>
<h3 id="heading-o-que-este-codigo-faz"><strong>O que este código faz?</strong></h3>
<ol>
<li><p><strong>Configura o Genkit:</strong> Dizemos ao Genkit para usar o plugin da Google AI e especificamos o modelo <code>gemini-2.5-flash</code>, que é rápido e poderoso.</p>
</li>
<li><p><strong>Define um "System Prompt":</strong> Damos instruções detalhadas ao Gemini, dizendo a ele para atuar como um especialista em missões de Konoha.</p>
</li>
<li><p><strong>Usa Zod para Validação:</strong> Criamos esquemas de validação (schemas) com Zod. Isso é incrível porque garante que a entrada do usuário e, mais importante, a saída da IA, sigam uma estrutura JSON exata que definimos. É como um contrato com a IA.</p>
</li>
<li><p><strong>Cria o</strong> <code>missionGeneratorFlow</code>: Este é o nosso fluxo principal. Ele recebe a definição da missão, envia para o Gemini com o nosso prompt e o schema, e retorna um objeto JSON completo e validado.</p>
</li>
</ol>
<hr />
<h2 id="heading-3-criando-o-endpoint-da-api-conectando-o-back-end">3. Criando o Endpoint da API: Conectando o Back-end</h2>
<p>Com nosso fluxo de IA pronto, precisamos de uma porta de entrada para ele em nosso servidor Angular.</p>
<p>Abra o arquivo <code>src/server.ts</code> e adicione o seguinte trecho no início do arquivo:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {
  AngularNodeAppEngine,
  createNodeRequestHandler,
  isMainModule,
  writeResponseToNodeResponse,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/ssr/node'</span>;
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> { missionGeneratorFlow } <span class="hljs-keyword">from</span> <span class="hljs-string">'./flows'</span>;
<span class="hljs-keyword">import</span> { join } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:path'</span>;

<span class="hljs-keyword">const</span> browserDistFolder = join(<span class="hljs-keyword">import</span>.meta.dirname, <span class="hljs-string">'../browser'</span>);

<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> angularApp = <span class="hljs-keyword">new</span> AngularNodeAppEngine();

app.use(express.json());

app.post(<span class="hljs-string">'/api/mission'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> missionGeneratorFlow(req.body);
    res.json(result);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    res.status(<span class="hljs-number">500</span>).json({ error: (error <span class="hljs-keyword">as</span> <span class="hljs-built_in">Error</span>).message });
  }
});

<span class="hljs-comment">// O código do servidor continua aqui...</span>
</code></pre>
<p>Este código cria uma rota <code>POST</code> em <code>/api/mission</code>. Quando o front-end envia uma definição de missão para este endpoint, ele aciona nosso <code>missionGeneratorFlow</code> e devolve a missão completa gerada pela IA. Simples assim!</p>
<hr />
<h2 id="heading-4-criando-o-servico-de-missoes-no-angular-gerenciando-o-estado">4. Criando o Serviço de Missões no Angular: Gerenciando o Estado</h2>
<p>De volta ao front-end, vamos criar um serviço para cuidar do estado das nossas missões e da comunicação com o back-end.</p>
<h3 id="heading-gere-o-servico">Gere o Serviço</h3>
<p>Use o Angular CLI para criar um novo serviço:</p>
<pre><code class="lang-bash">ng generate service mission
</code></pre>
<h3 id="heading-implemente-o-servico">Implemente o Serviço</h3>
<p>Abra o arquivo recém-criado <code>src/app/mission.service.ts</code> e adicione este código:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { HttpClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> { Injectable, computed, inject, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { take } <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Mission {
  id: <span class="hljs-built_in">string</span>;
  title: <span class="hljs-built_in">string</span>;
  difficulty: <span class="hljs-built_in">string</span>;
  missionValue: <span class="hljs-built_in">string</span>;
  detailedDescription: <span class="hljs-built_in">string</span>;
  ninjaTeamLevel: <span class="hljs-built_in">string</span>;
  assignedTeam: <span class="hljs-built_in">string</span>;
  teamMembers: {
    name: <span class="hljs-built_in">string</span>;
    specialty: <span class="hljs-built_in">string</span>;
  }[];
}

<span class="hljs-meta">@Injectable</span>({
  providedIn: <span class="hljs-string">'root'</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MissionService {
  missions = signal&lt;Mission[]&gt;([]);
  loading = signal(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> http = inject(HttpClient);

  createMission(definition: <span class="hljs-built_in">string</span>) {
    <span class="hljs-built_in">this</span>.loading.set(<span class="hljs-literal">true</span>);
    <span class="hljs-built_in">this</span>.http
      .post&lt;Mission&gt;(<span class="hljs-string">'/api/mission'</span>, { definition })
      .pipe(take(<span class="hljs-number">1</span>))
      .subscribe(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-built_in">this</span>.missions.update(<span class="hljs-function">(<span class="hljs-params">missions</span>) =&gt;</span> [...missions, response]);
        <span class="hljs-built_in">this</span>.loading.set(<span class="hljs-literal">false</span>);
      });
  }

  getMissionById(id: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">return</span> computed(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.missions().find(<span class="hljs-function">(<span class="hljs-params">mission</span>) =&gt;</span> mission.id === id));
  }
}
</code></pre>
<h3 id="heading-por-que-este-servico-e-importante"><strong>Por que este serviço é importante?</strong></h3>
<ol>
<li><p><strong>Reatividade com Signals:</strong> Ele usa um <code>signal</code> (<code>missions</code>) para armazenar a lista de missões. Qualquer componente que usar este <code>signal</code> será atualizado automaticamente quando uma nova missão chegar.</p>
</li>
<li><p><strong>Estado de Carregamento:</strong> O <code>loading</code> signal nos ajuda a mostrar um feedback visual para o usuário enquanto a IA está "pensando".</p>
</li>
<li><p><strong>Comunicação com a API:</strong> O método <code>createMission</code> faz a chamada <code>POST</code> para o nosso back-end e atualiza o <code>signal</code> de missões com a resposta.</p>
</li>
<li><p><strong>Busca por ID:</strong> O <code>getMissionById</code> nos permite encontrar uma missão específica na lista, o que será útil para a nossa página de detalhes.</p>
</li>
</ol>
<hr />
<h2 id="heading-5-criando-os-componentes-da-interface-o-rosto-da-aplicacao">5. Criando os Componentes da Interface: O Rosto da Aplicação</h2>
<p>Chegou a hora de dar vida à nossa interface.</p>
<h3 id="heading-configurando-o-indexhtml-e-o-tema">Configurando o <code>index.html</code> e o Tema</h3>
<p>Primeiro, vamos preparar nosso <code>index.html</code> e o tema com Tailwind.</p>
<p>Abra <code>src/index.html</code> e deixe-o assim:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dark"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>HokageDesk<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">base</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/x-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"favicon.ico"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-background-dark font-display text-gray-100"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">app-root</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">app-root</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Agora, crie um arquivo <code>src/theme.css</code> com as variáveis de cor e fontes:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@theme</span> {
  <span class="hljs-selector-tag">--color-primary</span>: <span class="hljs-selector-id">#4A6741</span>;
  <span class="hljs-selector-tag">--color-background-light</span>: <span class="hljs-selector-id">#FDFBF5</span>;
  <span class="hljs-selector-tag">--color-background-dark</span>: <span class="hljs-selector-id">#2D2D2D</span>;
  <span class="hljs-selector-tag">--color-card-dark</span>: <span class="hljs-selector-id">#3C3C3C</span>;
  <span class="hljs-selector-tag">--color-leaf-green</span>: <span class="hljs-selector-id">#4A5C43</span>;
  <span class="hljs-selector-tag">--color-leaf-green-dark</span>: <span class="hljs-selector-id">#3A4A35</span>;
  <span class="hljs-selector-tag">--color-text-light</span>: <span class="hljs-selector-id">#2D3748</span>;
  <span class="hljs-selector-tag">--color-text-dark</span>: <span class="hljs-selector-id">#E2E8F0</span>;
  <span class="hljs-selector-tag">--font-display</span>: "<span class="hljs-selector-tag">Space</span> <span class="hljs-selector-tag">Grotesk</span>", <span class="hljs-selector-tag">sans-serif</span>;
  <span class="hljs-selector-tag">--radius</span>: 0<span class="hljs-selector-class">.25rem</span>;
  <span class="hljs-selector-tag">--radius-lg</span>: 0<span class="hljs-selector-class">.5rem</span>;
  <span class="hljs-selector-tag">--radius-xl</span>: 0<span class="hljs-selector-class">.75rem</span>;
  <span class="hljs-selector-tag">--radius-full</span>: 9999<span class="hljs-selector-tag">px</span>;
}
</code></pre>
<p>Finalmente, abra <code>src/styles.css</code> e importe tudo:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">'https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&amp;display=swap'</span>);
<span class="hljs-keyword">@import</span> <span class="hljs-string">"tailwindcss"</span>;
<span class="hljs-keyword">@import</span> <span class="hljs-string">"./theme.css"</span>;
</code></pre>
<h3 id="heading-gere-os-componentes">Gere os Componentes</h3>
<p>Vamos usar o Angular CLI para gerar os dois componentes principais da nossa UI:</p>
<pre><code class="lang-bash">ng generate component dashboard
ng generate component detail
</code></pre>
<h3 id="heading-configurando-as-rotas">Configurando as Rotas</h3>
<p>Abra <code>src/app/app.routes.ts</code> e defina as rotas para nossos novos componentes. Usaremos <code>loadComponent</code> para carregá-los de forma assíncrona (lazy loading).</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Routes } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> routes: Routes = [
    { path: <span class="hljs-string">''</span>, loadComponent: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./dashboard/dashboard'</span>).then(<span class="hljs-function"><span class="hljs-params">c</span> =&gt;</span> c.Dashboard) },
    { path: <span class="hljs-string">'detail/:id'</span>, loadComponent: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./detail/detail'</span>).then(<span class="hljs-function"><span class="hljs-params">c</span> =&gt;</span> c.Detail) },
];
</code></pre>
<p>Limpe o <code>src/app/app.html</code>, deixando apenas o <code>router-outlet</code>:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">router-outlet</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-outlet</span>&gt;</span>
</code></pre>
<h3 id="heading-implementando-o-dashboard">Implementando o <code>Dashboard</code></h3>
<p>Este será nosso painel principal, com o formulário para criar missões e a lista de missões geradas.</p>
<p><code>src/app/dashboard/dashboard.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ChangeDetectionStrategy, Component, inject, signal } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { MissionService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../mission'</span>;
<span class="hljs-keyword">import</span> { FormsModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;
<span class="hljs-keyword">import</span> { RouterLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-dashboard'</span>,
  templateUrl: <span class="hljs-string">'./dashboard.html'</span>,
  styleUrls: [<span class="hljs-string">'./dashboard.css'</span>],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: <span class="hljs-literal">true</span>,
  imports: [FormsModule, RouterLink],
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Dashboard {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> missionService = inject(MissionService);
  missionDefinition = signal(<span class="hljs-string">''</span>);
  missions = <span class="hljs-built_in">this</span>.missionService.missions;
  loading = <span class="hljs-built_in">this</span>.missionService.loading;

  createMission() {
    <span class="hljs-built_in">this</span>.missionService.createMission(<span class="hljs-built_in">this</span>.missionDefinition());
    <span class="hljs-built_in">this</span>.missionDefinition.set(<span class="hljs-string">''</span>);
  }
}
</code></pre>
<p><code>src/app/dashboard/dashboard.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.avatar-stack</span> &gt; <span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">margin-left</span>: -<span class="hljs-number">0.75rem</span>;
}

<span class="hljs-selector-class">.avatar-stack</span> &gt; <span class="hljs-selector-tag">div</span><span class="hljs-selector-pseudo">:first-child</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<p><code>src/app/dashboard/dashboard.html</code></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"min-h-screen w-full p-4 sm:p-6 md:p-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mx-auto max-w-5xl"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center mb-8 md:mb-12"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl sm:text-4xl md:text-5xl font-bold text-white"</span>&gt;</span>Genkit-Jutsu: Mission Generator<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-10 md:mb-16"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-card-dark p-6 sm:p-8 rounded-xl shadow-lg"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"space-y-6"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block text-sm font-medium text-gray-300 mb-2"</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"mission-directive"</span>&gt;</span>Mission Directive<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
                [<span class="hljs-attr">ngModel</span>]=<span class="hljs-string">"missionDefinition()"</span>
                (<span class="hljs-attr">ngModelChange</span>)=<span class="hljs-string">"missionDefinition.set($event)"</span>
                [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"loading()"</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full border rounded-lg border-gray-600 bg-gray-700/50 focus:border-primary focus:ring-primary placeholder:text-gray-500 py-2 px-3 "</span>
                <span class="hljs-attr">id</span>=<span class="hljs-string">"mission-directive"</span>
                <span class="hljs-attr">name</span>=<span class="hljs-string">"mission-directive"</span>
                <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Describe the mission objectives, targets, and any special considerations..."</span>
                <span class="hljs-attr">rows</span>=<span class="hljs-string">"4"</span>
              &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
              (<span class="hljs-attr">click</span>)=<span class="hljs-string">"createMission()"</span>
              [<span class="hljs-attr">disabled</span>]=<span class="hljs-string">"loading()"</span>
              <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full bg-primary text-white font-bold py-3 px-4 rounded-lg hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-card-dark focus:ring-primary transition-colors"</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
            &gt;</span>
              @if (loading()) {
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center justify-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"animate-spin -ml-1 mr-3 h-5 w-5 text-white"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"opacity-25"</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">"12"</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">"12"</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"opacity-75"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Generating...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              } @else {
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Generate Mission Scroll<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              }
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl sm:text-3xl font-bold mb-6 text-white"</span>&gt;</span>Generated Mission Scrolls<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        @defer (on immediate) {
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-cols-1 md:grid-cols-2 gap-6"</span>&gt;</span>
          @for (mission of missions(); track mission.id) {
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> [<span class="hljs-attr">routerLink</span>]=<span class="hljs-string">"['/detail', mission.id]"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-background-light p-6 rounded-xl shadow-md flex flex-col space-y-4 cursor-pointer hover:bg-primary/10 transition-colors"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex-grow"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-between items-start mb-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl font-bold text-gray-800"</span>&gt;</span>{{ mission.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"inline-block bg-blue-200 text-blue-800 text-xs font-semibold px-2.5 py-0.5 rounded-full"</span>&gt;</span>Rank {{ mission.difficulty }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center space-x-2"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-sm text-gray-600"</span>&gt;</span>Assigned Team: {{ mission.assignedTeam }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          }
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        } @loading {
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex justify-center items-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"animate-spin -ml-1 mr-3 h-10 w-10 text-white"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">circle</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"opacity-25"</span> <span class="hljs-attr">cx</span>=<span class="hljs-string">"12"</span> <span class="hljs-attr">cy</span>=<span class="hljs-string">"12"</span> <span class="hljs-attr">r</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">stroke</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">stroke-width</span>=<span class="hljs-string">"4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">circle</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">path</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"opacity-75"</span> <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span> <span class="hljs-attr">d</span>=<span class="hljs-string">"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        }
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<h3 id="heading-implementando-o-detail">Implementando o <code>Detail</code></h3>
<p>Este componente mostrará todos os detalhes de uma missão quando o usuário clicar em um dos cards do dashboard.</p>
<p><code>src/app/detail/detail.ts</code></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ChangeDetectionStrategy, Component, inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { ActivatedRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;
<span class="hljs-keyword">import</span> { MissionService } <span class="hljs-keyword">from</span> <span class="hljs-string">'../mission'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-detail'</span>,
  templateUrl: <span class="hljs-string">'./detail.html'</span>,
  styleUrls: [<span class="hljs-string">'./detail.css'</span>],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: <span class="hljs-literal">true</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Detail {
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> route = inject(ActivatedRoute);
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> missionService = inject(MissionService);

  mission = <span class="hljs-built_in">this</span>.missionService.getMissionById(
    <span class="hljs-built_in">this</span>.route.snapshot.paramMap.get(<span class="hljs-string">'id'</span>)!
  );
}
</code></pre>
<p><code>src/app/detail/detail.component.css</code></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.custom-red-chip</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#991b1b</span>;
}

<span class="hljs-selector-class">.custom-blue-chip</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#1e3a8a</span>;
}
</code></pre>
<p><code>src/app/detail/detail.html</code></p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"min-h-screen flex items-center justify-center p-4"</span>&gt;</span>
  @if (mission(); as vm) {
  <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-full max-w-4xl bg-primary text-text-light dark:bg-gray-800 dark:text-text-dark rounded-xl shadow-lg p-6 md:p-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-6"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-3xl md:text-4xl font-bold text-leaf-green dark:text-leaf-green-dark"</span>&gt;</span>{{ vm.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center gap-3"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"custom-red-chip text-white text-xs font-bold px-3 py-1 rounded-full"</span>&gt;</span>Rank {{ vm.difficulty }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"custom-blue-chip text-white text-xs font-bold px-3 py-1 rounded-full"</span>&gt;</span>{{ vm.ninjaTeamLevel }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"space-y-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl font-bold mb-2 text-leaf-green dark:text-leaf-green-dark"</span>&gt;</span>Mission Briefing<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-gray-600 dark:text-gray-400 leading-relaxed"</span>&gt;</span>
          {{ vm.detailedDescription }}
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl font-bold mb-2 text-leaf-green dark:text-leaf-green-dark"</span>&gt;</span>Mission Value<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex items-center gap-2"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"material-symbols-outlined text-2xl text-leaf-green dark:text-leaf-green-dark"</span>&gt;</span>
            account_balance_wallet
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-lg font-bold text-gray-700 dark:text-gray-300"</span>&gt;</span>{{ vm.missionValue }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-xl font-bold mb-4 text-leaf-green dark:text-leaf-green-dark"</span>&gt;</span>Assigned Team: {{ vm.assignedTeam }}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6"</span>&gt;</span>
          @for (team of vm.teamMembers; track team) {
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col items-center p-4 bg-background-light dark:bg-gray-700 rounded-lg shadow-sm"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-bold text-lg text-text-light dark:text-text-dark"</span>&gt;</span>{{ team.name }}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-sm text-gray-600 dark:text-gray-400"</span>&gt;</span>{{ team.specialty }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          }
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  }
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<hr />
<h2 id="heading-conclusao-e-proximos-passos">Conclusão e Próximos Passos</h2>
<p>Parabéns, shinobi do código! Você construiu com sucesso uma aplicação Angular completa que utiliza Genkit e a API do Gemini para gerar conteúdo dinâmico de IA. Você viu como é fácil integrar um back-end de IA diretamente em um projeto Angular SSR.</p>
<p>Para rodar sua aplicação e ver a mágica acontecer, execute:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>Acesse <a target="_blank" href="http://localhost:4200"><code>http://localhost:4200</code></a> em seu navegador, descreva uma missão como "Proteger um construtor de pontes" ou "Infiltrar-se na base da Akatsuki", e veja a IA criar um pergaminho de missão completo para você!</p>
<p><strong>E agora?</strong> O céu é o limite! Aqui estão algumas ideias para evoluir o projeto:</p>
<ul>
<li><p><strong>Adicionar Autenticação:</strong> Permita que diferentes "Hokages" façam login e gerenciem suas próprias missões.</p>
</li>
<li><p><strong>Salvar Missões em um Banco de Dados:</strong> Integre um banco de dados como Firebase ou Supabase para persistir as missões geradas.</p>
</li>
<li><p><strong>Explorar Mais a Fundo a API do Gemini:</strong> Experimente com diferentes prompts, adicione mais campos ao seu schema Zod (como "Itens Recomendados" ou "Plano de Fuga"), ou até mesmo use a capacidade multimodal do Gemini para gerar uma imagem para cada missão.</p>
</li>
</ul>
<p>Espero que você tenha se divertido construindo este projeto tanto quanto eu me diverti escrevendo este guia. Agora é sua vez de expandir suas habilidades e criar seus próprios "jutsus" de IA.</p>
<p>Todo o código fonte está nesse repositório: <a target="_blank" href="https://github.com/alvarocamillont/hokage-desk-angular-genkit-gemini">GITHUB</a></p>
<p>Até a próxima</p>
]]></content:encoded></item><item><title><![CDATA[De Angular a Fullstack: Por que "Kotlin for Java Developers" deve ser sua próxima leitura]]></title><description><![CDATA[Olá, comunidade! Hoje trago um review muito especial de um livro que recebi gentilmente da editora Packt: "Kotlin for Java Developers", escrito por José Dimas Luján Castillo e Ron Veen.
Como especialista em Angular e alguém que advoga constantemente ...]]></description><link>https://alvarocamillont.dev/de-angular-a-fullstack-por-que-kotlin-for-java-developers-deve-ser-sua-proxima-leitura</link><guid isPermaLink="true">https://alvarocamillont.dev/de-angular-a-fullstack-por-que-kotlin-for-java-developers-deve-ser-sua-proxima-leitura</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Angular]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 23 Nov 2025 22:35:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763937308479/5f8ccb25-0712-45ca-a042-35e4b7d8b44f.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Olá, comunidade! Hoje trago um review muito especial de um livro que recebi gentilmente da editora <strong>Packt</strong>: <em>"Kotlin for Java Developers"</em>, escrito por José Dimas Luján Castillo e Ron Veen.</p>
<p>Como especialista em Angular e alguém que advoga constantemente pelo crescimento em "T" (o profissional T-Shaped), sempre recebo a pergunta: <em>"Qual o próximo passo na minha carreira além do Frontend?"</em>. A resposta, muitas vezes, reside em dominar uma linguagem de backend robusta ou explorar o desenvolvimento mobile. É aqui que este livro brilha, e vou explicar por que ele é uma leitura estratégica, mesmo que o título mencione "Java Developers".</p>
<h3 id="heading-sobre-o-livro">Sobre o Livro</h3>
<p><em>"Kotlin for Java Developers"</em> não é apenas um manual de sintaxe; é um guia de transição. Os autores focam em ensinar como escrever código Kotlin idiomático, seguro e conciso, aproveitando o ecossistema da JVM. Ele cobre desde os fundamentos de tipos e nulabilidade até conceitos avançados como Coroutines e DSLs. A abordagem é prática, comparando como as coisas eram feitas (no estilo verboso do Java) e como são resolvidas elegantemente no Kotlin.</p>
<h3 id="heading-para-quem-e-este-livro">Para quem é este Livro?</h3>
<p>Embora o título seja direcionado a desenvolvedores Java, o conteúdo é extremamente valioso para <strong>desenvolvedores TypeScript/Angular</strong>. Por que? Porque o Kotlin e o TypeScript compartilham muitos conceitos de design de linguagem moderna. Se você já entende tipagem estática, <em>generics</em> e programação funcional no Angular, a leitura deste livro será fluida. Ele serve para:</p>
<ul>
<li><p><strong>Iniciantes</strong>: Que querem começar no backend com o pé direito.</p>
</li>
<li><p><strong>Veteranos</strong>: Que desejam modernizar sua stack e sair da verbosidade do Java legado.</p>
</li>
</ul>
<h3 id="heading-o-caminho-das-pedras-para-o-desenvolvedor-angular">O Caminho das Pedras para o Desenvolvedor Angular</h3>
<p>Para nós, que vivemos no mundo dos Observables, Componentes e Tipagem Estrita, selecionei os capítulos que considero essenciais para fazer a ponte mental entre o TypeScript e o Kotlin:</p>
<ol>
<li><p><strong>Capítulo 3: Null and Non-Nullable Types</strong></p>
<ul>
<li><em>A conexão Angular:</em> Assim como ativamos o <code>strictNullChecks</code> no TypeScript para evitar erros em tempo de execução, o Kotlin trata a nulabilidade como parte do sistema de tipos. Este capítulo é fundamental para entender como o Kotlin elimina o temido <code>NullPointerException</code> (o equivalente ao nosso <code>undefined is not a function</code>).</li>
</ul>
</li>
<li><p><strong>Capítulo 7: Data and Sealed Classes</strong></p>
<ul>
<li><em>A conexão Angular:</em> Sabe aquelas interfaces ou tipos que criamos para representar nossos modelos de dados no front? As <em>Data Classes</em> do Kotlin são a versão turbinada disso para a JVM, com métodos como <code>equals</code>, <code>toString</code> e <code>copy</code> gerados automaticamente. Já as <em>Sealed Classes</em> são perfeitas para gerenciamento de estado (pense em NgRx ou Signals), permitindo modelar hierarquias restritas de forma segura.</li>
</ul>
</li>
<li><p><strong>Capítulos 8 e 9: Functional Programming &amp; Lambdas</strong></p>
<ul>
<li><em>A conexão Angular:</em> Quem trabalha com Angular respira programação funcional (RxJS). Aprender como o Kotlin trata funções como "cidadãos de primeira classe" e o uso de Lambdas fará você se sentir em casa. A sintaxe é surpreendentemente similar e poderosa.</li>
</ul>
</li>
<li><p><strong>Capítulo 11: Coroutines</strong></p>
<ul>
<li><em>A conexão Angular:</em> Gerenciar assincronicidade é nosso dia a dia (HTTP requests, eventos). Enquanto no JS usamos Promises e Async/Await, o Kotlin usa Coroutines. Este capítulo é vital para entender como escrever código assíncrono de forma sequencial e leve, sem bloquear a thread principal (algo crítico tanto no Backend quanto no Mobile).</li>
</ul>
</li>
</ol>
<h3 id="heading-a-importancia-estrategica-backend-e-mobile">A Importância Estratégica: Backend e Mobile</h3>
<p>Por que um Dev Angular deveria investir tempo nisso?</p>
<ol>
<li><p><strong>O Backend Moderno</strong>: O ecossistema Spring Boot abraçou o Kotlin como linguagem de primeira classe. Dominar Kotlin permite que você construa BFFs (Backend for Frontend) ou microsserviços robustos usando uma sintaxe que não causa "choque cultural" para quem vem do TypeScript.</p>
</li>
<li><p><strong>Mobile e KMP</strong>: O Kotlin não é apenas para Android nativo. Com o <strong>Kotlin Multiplatform (KMP)</strong>, a lógica de negócios que você escreve pode ser compartilhada entre Android, iOS e até Web. Aprender Kotlin abre a porta para você se tornar um desenvolvedor verdadeiramente multiplataforma.</p>
</li>
</ol>
<h3 id="heading-conclusao">Conclusão</h3>
<p><em>"Kotlin for Java Developers"</em> é um recurso excelente para solidificar sua base na JVM moderna. Para o profissional que deseja ir além do navegador e ter autonomia para construir soluções de ponta a ponta, este livro é um investimento certeiro. Agradeço à Packt pelo envio e recomendo fortemente a leitura.</p>
<p>E você, já pensou em expandir sua stack para o ecossistema Kotlin? Vamos conversar nos comentários!</p>
]]></content:encoded></item><item><title><![CDATA[GitHub Foundations Certification Guide: um aliado para quem já vive o ecossistema e quer elevar o nível]]></title><description><![CDATA[Para quem atua com desenvolvimento Angular em ambientes colaborativos, dominar Git e GitHub vai muito além do versionamento básico. Branching estruturado, pull requests eficientes, automações com segurança, integração com times e, mais recentemente, ...]]></description><link>https://alvarocamillont.dev/github-foundations-certification-guide-um-aliado-para-quem-ja-vive-o-ecossistema-e-quer-elevar-o-nivel</link><guid isPermaLink="true">https://alvarocamillont.dev/github-foundations-certification-guide-um-aliado-para-quem-ja-vive-o-ecossistema-e-quer-elevar-o-nivel</guid><category><![CDATA[GitHub]]></category><category><![CDATA[github-actions]]></category><category><![CDATA[copilot]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Mon, 06 Oct 2025 00:41:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759711277395/ded0c78b-ed86-453d-9f23-36ba0aff9895.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Para quem atua com desenvolvimento Angular em ambientes colaborativos, dominar Git e GitHub vai muito além do versionamento básico. Branching estruturado, pull requests eficientes, automações com segurança, integração com times e, mais recentemente, o uso estratégico de IA e GitHub Copilot fazem parte do dia a dia de quem entrega software com qualidade. O livro <strong>GitHub Foundations Certification Guide</strong>, de Ayodeji Ayodele, publicado pela Packt, reúne esses elementos de forma objetiva, atualizada e com uma proposta prática que conversa diretamente com profissionais experientes.</p>
<p>Embora seja voltado à preparação para a certificação <strong>GitHub Foundations</strong>, ele funciona também como um guia sólido de revisão e aprimoramento. O autor organiza o conteúdo de maneira progressiva, mas sem subestimar o leitor. O material cobre desde fundamentos essenciais até práticas de colaboração, permissões, governança, automação e integração com ferramentas modernas — tudo com base nas exigências reais de equipes técnicas.</p>
<p>A certificação GitHub Foundations, apesar de ser classificada como nível introdutório na trilha da plataforma, tem forte apelo para profissionais que desejam comprovar domínio operacional sobre os recursos mais utilizados em times de desenvolvimento. Ela abrange versionamento, colaboração, gestão de repositórios, fluxo de trabalho com branches, uso de issues e projetos, além de aspectos de governança e segurança — exatamente o tipo de proficiência que empresas esperam de um analista sênior.</p>
<p>O destaque do livro está na forma como ele equilibra teoria, prática e preparação. Os capítulos são estruturados em sprints, com exercícios, revisões e blocos de validação de conhecimento. Em vez de apresentar conceitos isolados, Ayodeji costura os temas com exemplos de uso cotidiano, o que facilita a aplicação imediata no contexto de trabalho. Para quem já atua com Angular ou frontend moderno, isso torna o aprendizado mais conectado com a rotina: criação e revisão de pull requests, fluxo de branches entre times, participação em projetos compartilhados e integração com pipelines e automações.</p>
<p>Outro ponto relevante é a abordagem de IA e Copilot. O autor não trata o tema como um acessório, mas como parte do ecossistema GitHub. Ele explora os diferentes modos de uso do GitHub Copilot — IDE, chat, web, terminal — e discute produtividade, segurança e boas práticas no uso da ferramenta. Para desenvolvedores Angular e outros profissionais que lidam com alta demanda de entrega, essa combinação entre versionamento, automação e IA representa ganho real de velocidade e redução de atrito no desenvolvimento, especialmente em tarefas repetitivas ou na criação de padrões de código.</p>
<p>Mesmo para quem não tem como objetivo imediato prestar a certificação, o livro funciona como uma atualização estratégica. Ele ajuda a consolidar boas práticas, reduz atritos do fluxo diário e eleva o nível de maturidade no uso do GitHub. Para quem já executa atividades de liderança técnica, mentoria de time ou code review, o conteúdo também serve como referência para padronização e melhoria de processos.</p>
<p>Por tudo isso, o livro se posiciona não apenas como material de estudo, mas como ferramenta de evolução profissional contínua. Ele atende quem deseja certificar-se, quem quer revisar fundamentos com profundidade e quem busca integrar IA ao desenvolvimento de forma consciente e útil.</p>
<p>E vale registrar um agradecimento à <strong>Packt Publishing</strong> por disponibilizar a obra. É raro encontrar material tão atual, coerente com as demandas do mercado e alinhado ao cotidiano de equipes de desenvolvimento modernas. Segue o link do livro para quem se interessar: <a target="_blank" href="https://www.packtpub.com/en-us/product/github-foundations-certification-guide-9781836206057"><strong>https://www.packtpub.com/en-us/product/github-foundations-certification-guide-9781836206057</strong></a></p>
<p><a target="_blank" href="https://www.packtpub.com/en-us/product/github-foundations-certification-guide-9781836206057">Se o objetivo é reforçar autoridade técnica, preparar-se para certificação ou simplesment</a>e elevar a qualidade do trabalho com GitHub, esse livro entrega valor real — tanto na prova quanto no dia a dia.</p>
]]></content:encoded></item><item><title><![CDATA[Review do Livro Python Object-Oriented Programming para Desenvolvedores Angular]]></title><description><![CDATA[Introdução
Recebi um exemplar do livro Python Object-Oriented Programming da editora Packet e posso dizer que fiquei muito satisfeito com o conteúdo. O material é bem estruturado e atende desde desenvolvedores iniciantes até avançados, tornando-se um...]]></description><link>https://alvarocamillont.dev/review-do-livro-python-object-oriented-programming-para-desenvolvedores-angular</link><guid isPermaLink="true">https://alvarocamillont.dev/review-do-livro-python-object-oriented-programming-para-desenvolvedores-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 30 Mar 2025 04:01:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743418544827/e2e5eb5d-5101-4ef0-be56-fc61d4a8e87d.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introducao">Introdução</h3>
<p>Recebi um exemplar do livro Python Object-Oriented Programming da editora Packet e posso dizer que fiquei muito satisfeito com o conteúdo. O material é bem estruturado e atende desde desenvolvedores iniciantes até avançados, tornando-se um ótimo recurso para quem quer dominar Python de forma profissional.</p>
<p>Como desenvolvedores, muitas vezes ficamos presos ao nosso stack principal, mas sair da zona de conforto e aprender uma nova linguagem como Python pode agregar muito valor. Além de expandir nossa visão sobre paradigmas de programação, isso nos torna mais versáteis e preparados para diferentes desafios no mercado. No desenvolvimento web moderno, é comum que desenvolvedores Angular se concentrem no frontend, mas entender como o backend funciona pode elevar significativamente a qualidade e a eficiência das aplicações. Este livro sobre Python traz conceitos fundamentais para quem deseja ampliar sua visão full stack e otimizar a integração entre o frontend Angular e APIs em Python. Neste review, vamos explorar como o livro pode agregar valor a quem trabalha com Angular e destacar os capítulos mais úteis.</p>
<h3 id="heading-visao-geral-do-livro">Visão Geral do Livro</h3>
<p>O livro foca no paradigma de programação orientada a objetos em Python, explorando padrões de projeto, princípios SOLID e boas práticas para desenvolvimento de software. Além disso, muitos dos conceitos abordados são aplicáveis não apenas ao backend, mas também ao frontend com JavaScript e TypeScript, tornando-o um excelente material para desenvolvedores que trabalham com Angular e desejam aprofundar sua compreensão sobre arquitetura de software e código reutilizável.</p>
<h3 id="heading-o-que-um-desenvolvedor-angular-pode-aproveitar">O Que um Desenvolvedor Angular Pode Aproveitar</h3>
<ol>
<li><p><strong>Entendendo a Programação Assíncrona</strong><br /> No mundo do Angular, lidamos o tempo todo com RxJS e assincronismo. O livro explora como Python implementa async/await e corrotinas, permitindo que desenvolvedores Angular compreendam melhor como o backend gerencia requisições concorrentes.</p>
</li>
<li><p><strong>A Importância dos Design Patterns</strong><br /> Independente da stack utilizada, compreender padrões de projeto é essencial para escrever código escalável, reutilizável e de fácil manutenção. O livro explora diversos design patterns que podem ser aplicados tanto no backend em Python quanto no frontend com Angular, ajudando desenvolvedores a estruturar melhor suas aplicações e resolver problemas comuns de forma eficiente.</p>
</li>
<li><p><strong>Integração com Frontend</strong><br /> Muitos desenvolvedores Angular trabalham em times onde o backend é feito em Python. O livro ensina padrões de comunicação entre frontend e backend, o que pode melhorar a qualidade da integração e evitar problemas como CORS, autenticação e versionamento de APIs.</p>
</li>
<li><p><strong>Manipulação de Dados e Automação</strong><br /> Aplicações Angular frequentemente interagem com grandes volumes de dados. Python oferece bibliotecas poderosas para processamento e transformação desses dados antes de serem enviados ao frontend. Isso pode ser um diferencial para quem precisa lidar com dashboards dinâmicos, gráficos ou relatórios interativos.</p>
</li>
</ol>
<h3 id="heading-conclusao">Conclusão</h3>
<p>Você pode adquirir o livro no seguinte link: <a target="_blank" href="https://www.packtpub.com/en-gb/product/python-object-oriented-programming-9781801075237?utm_medium=affiliate&amp;utm_campaign=b2548d32-4cb9-096b-ec76-6130c77d075c&amp;utm_term=b95101dc-e7b4-0ab9-b47f-63087f960e00&amp;utm_content=B17070">Python Object-Oriented Programming - Packt</a>. Este livro é um excelente recurso para desenvolvedores Angular que querem ir além do frontend e entender melhor a lógica por trás do backend em Python. Ele ajuda a criar uma ponte entre as duas tecnologias, permitindo um desenvolvimento mais eficiente, organizado e com maior controle sobre a comunicação entre cliente e servidor.</p>
<p>Se você trabalha com Angular e deseja aprimorar suas habilidades full stack ou melhorar a integração das suas aplicações com APIs Python, esse livro é uma ótima escolha. Vale a pena conferir!</p>
]]></content:encoded></item><item><title><![CDATA[Desmistificando IA para uma pessoa desenvolvedora web - Introdução]]></title><description><![CDATA[A Inteligência Artificial (IA) transcendeu o mundo das pessoas desenvolvedoras e se tornou um tópico de interesse geral. O público em geral está descobrindo o poder dessa ferramenta e como ela pode otimizar nossas atividades.
A democratização da IA é...]]></description><link>https://alvarocamillont.dev/desmistificando-ia-para-uma-pessoa-desenvolvedora-web-introducao</link><guid isPermaLink="true">https://alvarocamillont.dev/desmistificando-ia-para-uma-pessoa-desenvolvedora-web-introducao</guid><category><![CDATA[AI]]></category><category><![CDATA[gemini]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 25 Feb 2024 02:24:19 GMT</pubDate><content:encoded><![CDATA[<p>A Inteligência Artificial (IA) transcendeu o mundo das pessoas desenvolvedoras e se tornou um tópico de interesse geral. O público em geral está descobrindo o poder dessa ferramenta e como ela pode otimizar nossas atividades.</p>
<p>A democratização da IA é um dos seus aspectos mais empolgantes. O acesso a modelos poderosos se tornou mais simples, permitindo a integração da IA através de serviços de chat e até mesmo na barra de endereço do navegador.</p>
<p>Para pessoas desenvolvedoras web, essa mudança representa uma oportunidade incrível. Sem a necessidade de montar infraestruturas complexas, é possível criar aplicativos com capacidades de IA, impulsionando a inovação e a produtividade.</p>
<p>O Google criou o serviço Gemini (<a target="_blank" href="https://gemini.google.com/">https://gemini.google.com/</a>) que disponibiliza um serviço de IA poderoso já pronto para consumir em nossas aplicações e nessa série de tutorial vamos montar uma aplicação com capacidades que somente a IA pode prover.</p>
<p>A arquitetura dessa aplicação será bastante simples e comum para uma pessoa desenvolvedora web:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708811521813/99f535a8-6045-408a-b333-13eb4923d7fc.jpeg" alt class="image--center mx-auto" /></p>
<p>Teremos os seguinte elementos:</p>
<ol>
<li><p>Aplicação Web desenvolvida em Angular(<a target="_blank" href="https://angular.dev/">https://angular.dev/</a>)</p>
</li>
<li><p>Serviço de Back End desenvolvido em NestJS(<a target="_blank" href="https://nestjs.com/">https://nestjs.com/</a>)</p>
</li>
<li><p>A API do serviço do Gemini (<a target="_blank" href="https://ai.google.dev/">https://ai.google.dev/</a>)</p>
</li>
</ol>
<p>Aqui vale a pena uma explicação, o serviço do Gemini possui capacidade de ser consumido diretamente da aplicação web, porém esse tipo de arquitetura não é muito segura pois iria expor sua API Key caso você decida publicar sua aplicação.</p>
<p>Essa informação é <strong>muito sensível</strong> pois caso ela seja vazada uma pessoa mal intencionada poderá realizar requisições indevidas e comprometer significativamente a sua fatura com a Google Cloud...</p>
<p>Nesse tutorial começaremos pelo item 3 e vamos configurar nossa conta para consumir a API do Gemini.</p>
<p>O primeiro requisito que você precisa é uma conta no serviço do Google Cloud Platform (<a target="_blank" href="https://console.cloud.google.com">https://console.cloud.google.com</a>)</p>
<p>Uma vez autenticado, é preciso criar um projeto que consumirá o Gemini.</p>
<p>Na barra de pesquisa, busque por ("criar projeto") escolha um nome e confirme.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708812561176/e27c989b-4d03-440b-82cb-0bdd2c26931e.jpeg" alt class="image--center mx-auto" /></p>
<p>Vamos então ao site "Build with Gemini"(<a target="_blank" href="https://ai.google.dev/">https://ai.google.dev/</a>) e pedir a nossa API Key:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708812878995/05a615a1-3f7c-4080-9955-94ccbeb34007.jpeg" alt class="image--center mx-auto" /></p>
<p>Selecione o projeto que você criou e você terá o código da sua API Key</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708813128306/f0446455-5af7-48d6-b9f2-aeede2eaa1cf.jpeg" alt class="image--center mx-auto" /></p>
<p>Com essa configuração estamos prontos para criar o nosso serviço de back end no próximo artigo, até lá!</p>
<p>#GeminiSprint</p>
<p><strong>Google Cloud credits are provided for this project.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Angular v15 já está disponível!]]></title><description><![CDATA[Tradução livre do artigo original: https://blog.angular.io/angular-v15-is-now-available-df7be7f2f4c8
No ano passado, foi removido o compilador legado e o pipeline de renderização do Angular, que permitiu o desenvolvimento de uma série de melhorias na...]]></description><link>https://alvarocamillont.dev/angular-v15-ja-esta-disponivel</link><guid isPermaLink="true">https://alvarocamillont.dev/angular-v15-ja-esta-disponivel</guid><category><![CDATA[Angular]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Thu, 17 Nov 2022 04:41:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/lUaaKCUANVI/upload/v1668659992607/SJKr9rBYD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tradução livre do artigo original: https://blog.angular.io/angular-v15-is-now-available-df7be7f2f4c8</p>
<p>No ano passado, foi removido o compilador legado e o pipeline de renderização do Angular, que permitiu o desenvolvimento de uma série de melhorias na experiência do desenvolvedor nos últimos meses. Angular v15 é o resultado disso com dezenas de refinamentos que levam a uma melhor experiência e desempenho do desenvolvedor.</p>
<h2 id="heading-standalone-api-agora-esta-estavel-e-pronta-para-producao">Standalone API agora está estável e pronta para produção!</h2>
<p>Na v14, foram introduzidas novas standalone APIs que permitem aos desenvolvedores criarem aplicativos sem usar NgModules. A equipe do Angular está feliz em compartilhar que essas APIs saíram da fase de preview e agora fazem parte da API estável do framework. A partir de agora ela será evoluída gradualmente seguindo o versionamento semântico.</p>
<p>Como parte de garantir que as standalone APIs estivessem prontas para serem utilizadas em produção, foram garantidos que os componentes standalone funcionem em todo ecosistema Angular e agora funcionem completamente com as APIs <code>HttpClient</code>, Angular Elements, router e mais.</p>
<p>As APIs standalone permitem que você inicialize um aplicativo usando um único componente:</p>
<pre><code><span class="hljs-keyword">import</span> {bootstrapApplication} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/platform-browser'</span>;
<span class="hljs-keyword">import</span> {ImageGridComponent} <span class="hljs-keyword">from</span><span class="hljs-string">'./image-grid'</span>;

@Component({
  <span class="hljs-attr">standalone</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">selector</span>: <span class="hljs-string">'photo-gallery'</span>,
  <span class="hljs-attr">imports</span>: [ImageGridComponent],
  <span class="hljs-attr">template</span>: <span class="hljs-string">`
    … &lt;image-grid [images]="imageList"&gt;&lt;/image-grid&gt;
  `</span>,
})
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PhotoGalleryComponent</span> </span>{
  <span class="hljs-comment">// component logic</span>
}
bootstrapApplication(PhotoAppComponent);
</code></pre><h2 id="heading-router-and-httpclient-tree-shakable-standalone-apis">Router and HttpClient tree-shakable standalone APIs</h2>
<p>Você pode criar um aplicativo de multi-rotas usando as novas APIs standalone do router! Para declarar a rota raiz, você pode usar o seguinte exemplo:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> appRoutes: Routes = [{
  <span class="hljs-attr">path</span>: <span class="hljs-string">'lazy'</span>,
  <span class="hljs-attr">loadChildren</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./lazy/lazy.routes'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">routes</span> =&gt;</span> routes.lazyRoutes)
}];
</code></pre><p>Onde lazyRoutes são declarados em:</p>
<pre><code><span class="hljs-keyword">import</span> {Routes} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/router'</span>;

<span class="hljs-keyword">import</span> {LazyComponent} <span class="hljs-keyword">from</span> <span class="hljs-string">'./lazy.component'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> lazyRoutes: Routes = [{<span class="hljs-attr">path</span>: <span class="hljs-string">''</span>, <span class="hljs-attr">component</span>: LazyComponent}];
</code></pre><p>e finalmente, registre o <code>appRoutes</code> na chamada <code>bootstrapApplication</code>:</p>
<pre><code>bootstrapApplication(AppComponent, {
  <span class="hljs-attr">providers</span>: [
    provideRouter(appRoutes)
  ]
});
</code></pre><p>Outro benefício da API <code>ProvideRouter</code> é que ela pode ser tree-shakable! Os Bundlers podem remover recursos não utilizados do roteador em tempo de compilação. Em testes com a nova API, foi descoberto que a remoção desses recursos não utilizados do pacote resultou em uma redução de 11% no tamanho do código do router no bundle do aplicativo.</p>
<h2 id="heading-api-de-composicao-de-diretivas">API de composição de diretivas</h2>
<p>A API de composição de diretivas traz a reutilização de código para outro nível! Esse recurso foi inspirado pela <a target="_blank" href="https://github.com/angular/angular/issues/8785">solicitação</a> de recurso mais popular no GitHub, solicitando a funcionalidade de adicionar diretivas a um elemento host.</p>
<p>A API de composição de diretivas permite que os desenvolvedores aprimorem os elementos do host com diretivas e adiciona ao Angular com uma poderosa estratégia de reutilização de código, que só é possível graças ao compilador do Angular. A API de composição de diretivas funciona apenas com diretivas independentes.</p>
<p>Vejamos um exemplo rápido:</p>
<pre><code>@Component({
  <span class="hljs-attr">selector</span>: <span class="hljs-string">'mat-menu'</span>,
  <span class="hljs-attr">hostDirectives</span>: [HasColor, {
    <span class="hljs-attr">directive</span>: CdkMenu,
    <span class="hljs-attr">inputs</span>: [<span class="hljs-string">'cdkMenuDisabled: disabled'</span>],
    <span class="hljs-attr">outputs</span>: [<span class="hljs-string">'cdkMenuClosed: closed'</span>]
  }]
})
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MatMenu</span> </span>{}
</code></pre><p>No trecho de código acima, aprimoramos <code>MatMenu</code> com duas diretivas: <code>HasColor</code> e <code>CdkMenu</code>. <code>MatMenu</code> reutiliza todas as entradas, saídas e lógica associada com <code>HasColors</code> e apenas a lógica e as entradas selecionadas do <code>CdkMenu</code>.</p>
<p>Esta técnica pode lembrá-lo de herança múltipla ou traços em algumas linguagens de programação, com a diferença de que temos um mecanismo para resolução de conflitos de nomes e é aplicável a primitivas de interface de usuário.</p>
<h2 id="heading-a-diretiva-de-imagem-agora-esta-estavel">A diretiva de imagem agora está estável!</h2>
<p>Foi anunciada a preview da <a target="_blank" href="https://developer.chrome.com/blog/angular-image-directive/">diretiva de imagem Angular</a> que foi desenvolvida em colaboração com o <a target="_blank" href="https://developer.chrome.com/blog/introducing-aurora/">Chrome Aurora</a> na v14.2.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668652713148/3knOwKfOn.png" alt="image.png" /></p>
<p>Agora ela está estável! A <a target="_blank" href="https://www.landsend.com">Land's End</a> experimentou esse recurso e observou 75% de melhoria no LCP em um teste no <a target="_blank" href="https://philipwalton.com/articles/my-challenge-to-the-web-performance-community/">lighthouse</a>.</p>
<p>A versão v15 também inclui alguns novos recursos para a diretiva de imagem:</p>
<ul>
<li><p><strong>Geração automática de srcset</strong>: a diretiva garante que uma imagem de tamanho apropriado seja solicitada gerando o atributo srcset para você. Isso pode reduzir o tempo de download de suas imagens.</p>
</li>
<li><p><strong>Modo de preenchimento [experimental]</strong>: este modo faz com que a imagem preencha seu contêiner pai, eliminando a necessidade de declarar a largura e a altura da imagem. É uma ferramenta útil se você não souber os tamanhos de suas imagens ou se quiser migrar imagens de plano de fundo CSS para usar a diretiva.</p>
</li>
</ul>
<p>Você pode usar a diretiva <code>NgOptimizedImage</code> diretamente em seu componente ou <code>NgModule</code>:</p>
<pre><code><span class="hljs-keyword">import</span> { NgOptimizedImage } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;

<span class="hljs-comment">// Include it into the necessary NgModule</span>
@NgModule({
  <span class="hljs-attr">imports</span>: [NgOptimizedImage],
})
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppModule</span> </span>{}

<span class="hljs-comment">// ... or a standalone Component</span>
@Component({
  <span class="hljs-attr">standalone</span>: <span class="hljs-literal">true</span>
  <span class="hljs-attr">imports</span>: [NgOptimizedImage],
})
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyStandaloneComponent</span> </span>{}
</code></pre><p>Para usá-lo em um componente, basta substituir o atributo src da imagem por ngSrc e certifique-se de especificar o atributo de prioridade para suas imagens LCP.</p>
<p>Você pode encontrar mais informações na <a target="_blank" href="https://angular.io/guide/image-directive">documentação</a>.</p>
<h2 id="heading-guarda-de-rotas-funcionais">Guarda de rotas funcionais</h2>
<p>Junto com as APIs de router independentes e tree-shakable, foi trabalhado o boilerplate das guardas de rota. Vejamos um exemplo onde definimos uma guarda que verifica se o usuário está logado:</p>
<pre><code>@Injectable({ <span class="hljs-attr">providedIn</span>: <span class="hljs-string">'root'</span> })
<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyGuardWithDependency</span> <span class="hljs-title">implements</span> <span class="hljs-title">CanActivate</span> </span>{
  <span class="hljs-keyword">constructor</span>(private loginService: LoginService) {}

  canActivate() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.loginService.isLoggedIn();
  }
}

<span class="hljs-keyword">const</span> route = {
  <span class="hljs-attr">path</span>: <span class="hljs-string">'somePath'</span>,
  <span class="hljs-attr">canActivate</span>: [MyGuardWithDependency]
};
</code></pre><p>LoginService implementa a maior parte da lógica e na guarda só invocamos isLoggedIn(). Mesmo que o guard seja bem simples, temos muito boilerplate.</p>
<p>Com as novas guarda de rotas funcionais, você pode refatorar esse código para:</p>
<pre><code><span class="hljs-keyword">const</span> route = {
  <span class="hljs-attr">path</span>: <span class="hljs-string">'admin'</span>,
  <span class="hljs-attr">canActivate</span>: [<span class="hljs-function">() =&gt;</span> inject(LoginService).isLoggedIn()]
};
</code></pre><p>Expressamos toda a guarda dentro da sua declaração. As guardas funcionais também podem ser compostas — você pode criar funções do tipo factory que aceitam uma configuração e retornam uma função de guarda ou resolver. Você pode encontrar um exemplo para executar proteções de roteador em série no <a target="_blank" href="https://github.com/angular/angular/blob/8546b17adec01de69bf314a959ef2d12f6638eb9/packages/router/test/integration.spec.ts#L5157-L5194">GitHub</a>.</p>
<h2 id="heading-o-roteador-desempacota-as-importacoes-padrao">O roteador desempacota as importações padrão</h2>
<p>Para tornar o roteador mais simples e reduzir ainda mais o boilerplate, o roteador agora desempacota automaticamente as exportações padrão durante o carregamento lazy.</p>
<p>Vamos supor que você tenha o seguinte <code>LazyComponent</code>:</p>
<pre><code>@Component({
  <span class="hljs-attr">standalone</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">template</span>: <span class="hljs-string">'...'</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LazyComponent</span> </span>{ ... }
</code></pre><p>Antes dessa alteração, para fazer o carregamento lazy de um componente independente , você precisava:</p>
<pre><code>{
  <span class="hljs-attr">path</span>: <span class="hljs-string">'lazy'</span>,
  <span class="hljs-attr">loadComponent</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./lazy-file'</span>).then(<span class="hljs-function"><span class="hljs-params">m</span> =&gt;</span> m.LazyComponent),
}
</code></pre><p>Agora o roteador irá procurar por uma exportação padrão e se encontrar, usará automaticamente, o que simplifica a declaração de rota para:</p>
<pre><code>{
  <span class="hljs-attr">path</span>: <span class="hljs-string">'lazy'</span>,
  <span class="hljs-attr">loadComponent</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./lazy-file'</span>),
}
</code></pre><h2 id="heading-melhores-stack-traces">Melhores stack traces</h2>
<p>A equipe do Angular recebe muitos insights das pesquisas anuais com desenvolvedores, por isso queremos agradecer a você por dedicar um tempo para compartilhar seus pensamentos! Entramos de cabeça nas dificuldades com a experiência de depuração que os desenvolvedores enfrentam, descobrimos que as mensagens de erro poderiam ser melhoradas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668654216207/dmINmKWJt.png" alt="image.png" /></p>
<p>Problemas de depuração para desenvolvedores Angular</p>
<p>Foi feita uma parceria com o Chrome DevTools para corrigir isso! Veja um exemplo de stack trace que você pode trabalhar em um aplicativo Angular:</p>
<pre><code>ERROR <span class="hljs-built_in">Error</span>: Uncaught (<span class="hljs-keyword">in</span> promise): <span class="hljs-built_in">Error</span>
<span class="hljs-built_in">Error</span>
    at app.component.ts:<span class="hljs-number">18</span>:<span class="hljs-number">11</span>
    at Generator.next (<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">anonymous</span>&gt;</span>)
    at asyncGeneratorStep (asyncToGenerator.js:3:1)
    at _next (asyncToGenerator.js:25:1)
    at _ZoneDelegate.invoke (zone.js:372:26)
    at Object.onInvoke (core.mjs:26378:33)
    at _ZoneDelegate.invoke (zone.js:371:52)
    at Zone.run (zone.js:134:43)
    at zone.js:1275:36
    at _ZoneDelegate.invokeTask (zone.js:406:31)
    at resolvePromise (zone.js:1211:31)
    at zone.js:1118:17
    at zone.js:1134:33</span>
</code></pre><p>Este snippet sofre de dois problemas:</p>
<ul>
<li>Há apenas uma linha correspondente ao código que o desenvolvedor criou. Todo o resto vem de dependências de terceiros (framework Angular, Zone.js, RxJS)</li>
<li>Não há informações sobre qual interação do usuário causou o erro</li>
</ul>
<p>Não há informações sobre qual interação do usuário causou o erro</p>
<p>A equipe do Chrome DevTools criou um mecanismo para ignorar scripts provenientes de node_modules anotando source maps por meio da CLI do Angular. Também foi criada uma API de marcação de pilha assíncrona que nos permitiu concatenar tarefas assíncronas agendadas e independentes em um único stack trace. Jia Li integrou o Zone.js com a API de marcação de pilha assíncrona, o que permitiu fornecer stack traces vinculados.</p>
<p>Essas duas mudanças melhoram drasticamente o stack trace que os desenvolvedores veem no Chrome DevTools:</p>
<pre><code>ERROR <span class="hljs-built_in">Error</span>: Uncaught (<span class="hljs-keyword">in</span> promise): <span class="hljs-built_in">Error</span>
<span class="hljs-built_in">Error</span>
    at app.component.ts:<span class="hljs-number">18</span>:<span class="hljs-number">11</span>
    at fetch (<span class="hljs-keyword">async</span>)  
    at (anonymous) (app.component.ts:<span class="hljs-number">4</span>)
    at request (app.component.ts:<span class="hljs-number">4</span>)
    at (anonymous) (app.component.ts:<span class="hljs-number">17</span>)
    at submit (app.component.ts:<span class="hljs-number">15</span>)
    at AppComponent_click_3_listener (app.component.html:<span class="hljs-number">4</span>)
</code></pre><p>Aqui você pode acompanhar a execução do botão pressionado no AppComponent até o erro. Você pode ler mais sobre as melhorias <a target="_blank" href="https://developer.chrome.com/blog/devtools-modern-web-debugging/">aqui</a>.</p>
<h2 id="heading-lancamento-de-componentes-baseados-em-mdc-para-producao">Lançamento de componentes baseados em MDC para produção</h2>
<p>Estamos felizes em anunciar que a refatoração dos componentes de material Angular com base no Material Design Components for Web (MDC) está concluída! Essa mudança permite que o Angular se alinhe ainda mais com a especificação do Material Design, reutilize código de primitivas desenvolvidas pela equipe do Material Design e nos permite adotar o Material 3 assim que finalizado os tokens de estilo.</p>
<p>Para muitos dos componentes, atualizamos os estilos e a estrutura DOM e outros reescrevemos do zero. Mantivemos a maioria das APIs TypeScript e seletores de componentes/diretivas para os novos componentes idênticos à implementação antiga.</p>
<p>Migramos milhares de projetos do Google, o que nos permitiu facilitar o caminho da migração externa e documentar uma lista abrangente das alterações em todos os componentes.</p>
<p>Devido ao novo DOM e CSS, você provavelmente descobrirá que alguns estilos em seu aplicativo precisam ser ajustados, principalmente se seu CSS estiver substituindo estilos em elementos internos em qualquer um dos componentes migrados.</p>
<p>A implementação antiga de cada novo componente agora está obsoleta, mas ainda está disponível a partir de uma importação “herdada”. Por exemplo, você pode importar a implementação do botão mat antigo importando o módulo de botão legado.</p>
<pre><code><span class="hljs-keyword">import</span> {MatLegacyButtonModule} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/material/legacy-button'</span>;
</code></pre><p>Visite o <a target="_blank" href="https://github.com/angular/components/blob/main/guides/v15-mdc-migration.md#how-to-migrate">guia de migração</a> para obter mais informações.</p>
<p>Mudamos muitos dos componentes para usar tokens de design e variáveis CSS internamente, o que fornecerá um caminho mais tranquilo para os aplicativos adotarem os estilos de componentes do Material 3.</p>
<h2 id="heading-mais-melhorias-nos-componentes">Mais melhorias nos componentes</h2>
<p>Resolvemos o 4º problema mais votado - <a target="_blank" href="https://github.com/angular/components/issues/1331">suporte à seleção de intervalo no controle slider</a>.</p>
<p>Para obter uma entrada de intervalo, use:</p>
<pre><code>&lt;mat-slider&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">matSliderStartThumb</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">matSliderEndThumb</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mat-slider</span>&gt;</span></span>
</code></pre><p>Além disso, todos os componentes agora têm uma API para personalizar a densidade que resolveu outro <a target="_blank" href="https://github.com/angular/components/issues/4597">problema popular do GitHub</a>.</p>
<p>Agora você pode especificar a densidade padrão em todos os seus componentes personalizando seu tema:</p>
<pre><code>@use <span class="hljs-string">'@angular/material'</span> <span class="hljs-keyword">as</span> mat;

$theme: mat.define-light-theme((
  color: (
    primary: mat.define-palette(mat.$red-palette),
    <span class="hljs-attr">accent</span>: mat.define-palette(mat.$blue-palette),
  ),
  <span class="hljs-attr">typography</span>: mat.define-typography-config(),
  <span class="hljs-attr">density</span>: <span class="hljs-number">-2</span>,
));

@include mat.all-component-themes($theme);
</code></pre><p>As novas versões dos componentes incluem uma ampla gama de melhorias de acessibilidade, incluindo melhores taxas de contraste, tamanhos de alvo de toque aumentados e semântica ARIA refinada.</p>
<h2 id="heading-cdk-listbox">CDK Listbox</h2>
<p>O Component Dev Kit (CDK) oferece um conjunto de primitivas de comportamento para a construção de componentes de interface do usuário. Na v15, introduzimos outra primitiva que você pode personalizar para seu caso de uso — a listbox CDK:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668655180702/lkJArZktV.png" alt="image.png" /></p>
<p>O módulo <code>@angular/cdk/listbox</code> fornece diretivas para ajudar a criar interações de caixa de listagem personalizadas com base no padrão de caixa de listagem WAI ARIA.</p>
<p>Ao usar <code>@angular/cdk/listbox</code>, você obtém todos os comportamentos esperados para uma experiência acessível, incluindo suporte a layout bidi, interação com teclado e gerenciamento de foco. Todas as diretivas aplicam suas funções ARIA associadas ao elemento host.</p>
<h2 id="heading-melhorias-no-suporte-de-esbuild-experimental">Melhorias no suporte de esbuild experimental</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668655319783/jz_kU9A-9.png" alt="image.png" /></p>
<p>Na v14, anunciamos o suporte experimental para <a target="_blank" href="https://esbuild.github.io/">esbuild</a> em <code>ng build</code> para permitir tempos de compilação mais rápidos e simplificar nosso pipeline.</p>
<p>Na v15, agora temos Sass experimental, modelo SVG, substituição de arquivo e <code>ng build --watchsupport</code> ! Por favor, tente esbuild atualizando os builder <code>angular.json</code> de:</p>
<pre><code><span class="hljs-string">"builder"</span>: <span class="hljs-string">"@angular-devkit/build-angular:browser"</span>
</code></pre><p>para </p>
<pre><code><span class="hljs-string">"builder"</span>: <span class="hljs-string">"@angular-devkit/build-angular:browser-esbuild"</span>
</code></pre><p>Se você encontrar algum problema com suas compilações de produção, informe-nos registrando um problema no <a target="_blank" href="https://github.com/angular/angular-cli/issues/new?assignees=&amp;labels=&amp;template=1-bug-report.yml">GitHub</a>.</p>
<h2 id="heading-importacoes-automaticas-no-language-service">Importações automáticas no language service</h2>
<p>O  language service agora pode importar automaticamente os componentes que você está usando em um template, mas não adicionou a um componente independente ou a um <code>NgModule</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668655657430/yn-m-sXMM.png" alt="image.png" /></p>
<h2 id="heading-melhorias-na-cli">Melhorias na CLI</h2>
<p>Na CLI Angular, introduzimos suporte para APIs estáveis independentes. Agora você pode gerar um novo componente independente via <code>ng g component --standalone</code>.</p>
<p>Também temos a missão de simplificar a saída de <code>ng new</code>. Como primeiro passo, reduzimos a configuração removendo test.ts, polyfills.ts e ambientes. Agora você pode especificar seus polyfills diretamente em <code>angular.json</code> na seção <code>polyfills</code>:</p>
<pre><code><span class="hljs-string">"polyfills"</span>: [
  <span class="hljs-string">"zone.js"</span>
]
</code></pre><p>Para reduzir ainda mais os arquivos de configuração, agora usamos <code>.browserlist</code> para permitir que você defina a versão de destino do ECMAScript.</p>
<h2 id="heading-destaques-da-contribuicao-da-comunidade">Destaques da contribuição da comunidade</h2>
<p>Estamos gratos em compartilhar que, desde o lançamento da v14, recebemos contribuições de mais de 210 pessoas em framework, componentes e CLI! Nesta seção, gostaria de destacar dois deles.</p>
<h3 id="heading-fornecida-a-capacidade-de-configurar-opcoes-padrao-para-datepipehttpsgithubcomangularangularpull47157"><a target="_blank" href="https://github.com/angular/angular/pull/47157">Fornecida a capacidade de configurar opções padrão para DatePipe</a></h3>
<p>Esse recurso permite que você altere globalmente a configuração de formatação padrão para DatePipe. Aqui está um exemplo com a nova API bootstrapApplication:</p>
<pre><code>bootstrapApplication(AppComponent, {
  <span class="hljs-attr">providers</span>: [
    {
      <span class="hljs-attr">provide</span>: DATE_PIPE_DEFAULT_OPTIONS,
      <span class="hljs-attr">useValue</span>: { <span class="hljs-attr">dateFormat</span>: <span class="hljs-string">'shortDate'</span> }
    }
  ]
});
</code></pre><p>A configuração acima habilitará o formato <code>shortDate</code> para todos os locais em que você usa <code>DatePipe</code> em seu aplicativo.</p>
<h3 id="heading-adicionada-a-tag-de-pre-carregamento-para-imagens-prioritarias-durante-o-ssrhttpsgithubcomangularangularpull47343"><a target="_blank" href="https://github.com/angular/angular/pull/47343">Adicionada a tag de pré-carregamento  para imagens prioritárias durante o SSR</a></h3>
<p>Para garantir que as imagens prioritárias sejam carregadas o mais rápido possível, Jay Bell adicionou uma funcionalidade à diretiva de imagem para incluir uma tag <code>&lt;link rel="preload"&gt;</code> para elas ao usar o Angular Universal.</p>
<p>Não há necessidade de ação do seu lado se você já ativou a diretiva de imagem. Se você especificou uma imagem como prioridade, a diretiva irá pré-carregá-la automaticamente.</p>
<h2 id="heading-descontinuacoes">Descontinuações</h2>
<p>Os lançamentos major nos permitem evoluir a estrutura em direção à simplicidade, melhor experiência do desenvolvedor e alinhamento com a plataforma da web.</p>
<p>Depois de analisar milhares de projetos no Google, encontramos alguns padrões raramente usados que, na maioria dos casos, são mal utilizados. Como resultado, estamos descontinuando o <code>providedIn: 'any'</code> é uma opção que tem uso muito limitado, além de um punhado de casos esotéricos internos ao framework.</p>
<p>Também estamos descontinuando o <code>providedIn: NgModule</code> . Ele não tem amplo uso e, na maioria dos casos, é usado incorretamente, em circunstâncias em que você deve preferir <code>providedIn: 'root'</code>. Se você deve realmente definir o escopo de provedores para um NgModule específico, use <code>NgModule.providers</code>.</p>
<p>Com o layout em evolução em CSS, a equipe deixará de publicar novos lançamentos de <code>@angular/flex-layout</code>. Continuaremos fornecendo correções de segurança e compatibilidade de navegador para o próximo ano. Você pode aprender mais sobre isso na <a target="_blank" href="https://blog.angular.io/modern-css-in-angular-layouts-4a259dca9127">primeira postagem do blog</a> da nossa série “CSS moderno”.</p>
<h2 id="heading-animado-com-o-que-vem-por-ai">Animado com o que vem por aí!</h2>
<p>O lançamento do Ivy em 2020 permitiu muitas melhorias em geral que você pode encontrar já sendo lançadas. O NgModules opcional é um ótimo exemplo. Ele ajuda na redução dos conceitos com os quais os iniciantes precisam lidar como parte de sua jornada de aprendizado básica e também suporta recursos avançados, como API de composição de diretivas por meio de diretivas independentes.</p>
<p>Em seguida, estamos abordando melhorias em nosso pipeline de renderização do lado do servidor e reatividade, trazendo melhorias de qualidade de vida em geral!</p>
<p>Mal posso esperar para compartilhar com vocês o que está por vir!</p>
]]></content:encoded></item><item><title><![CDATA[Podcasts para pessoas desenvolvedoras]]></title><description><![CDATA[Um dos recursos mais valiosos que eu utilizo no dia a dia é o podcast.
A brincadeira é que todo o ano será o ano do podcast, mas eu ouso dizer que estamos chegando nesse ponto!
Aqui estão os podcasts que eu escuto no dia a dia para me atualizar e est...]]></description><link>https://alvarocamillont.dev/podcasts-para-pessoas-desenvolvedoras</link><guid isPermaLink="true">https://alvarocamillont.dev/podcasts-para-pessoas-desenvolvedoras</guid><category><![CDATA[podcast]]></category><category><![CDATA[podcasts]]></category><category><![CDATA[technology]]></category><category><![CDATA[Games]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Fri, 25 Oct 2019 22:51:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1572043546564/ZaCIIN1tt.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Um dos recursos mais valiosos que eu utilizo no dia a dia é o podcast.</p>
<p>A brincadeira é que todo o ano será o ano do podcast, mas eu ouso dizer que estamos chegando nesse ponto!</p>
<p>Aqui estão os podcasts que eu escuto no dia a dia para me atualizar e estudar</p>
<h2 id="podcast-de-desenvolvimento-e-ti">Podcast de desenvolvimento e TI</h2>
<p><a target="_blank" href="https://www.buzzsprout.com/219128">Totvs Developers</a> - Podcast de tecnologia da Totvs que fala de vários assuntos sobre desenvolvimento, carreira em TI e mais. <strong>Alerta auto jabá, mas assina lá é feito com amor :) </strong></p>
<p><a target="_blank" href="https://devchat.tv/adv-in-angular/">Adventures in Angular</a> - Podcast em inglês semanal focado no framework Angular.</p>
<p><a target="_blank" href="https://devchat.tv/js-jabber/">JavaScript Jabber</a> - Podcast em inglês semanal focado em JavaScript e todo o seu ecossistema.</p>
<p><a target="_blank" href="https://thedeepdive.simplecast.com">The Deep Dive</a> - Podcast em inglês focado em tópicoas avançados de desenvolvimento web.</p>
<p><a target="_blank" href="https://podtail.com/en/podcast/the-angular-show/">The Angular Show</a> - Podcast do pessoal que organiza a ngconf sobre Angular e seu ecossitema.</p>
<p><a target="_blank" href="https://angularair.com/">Angular Air</a> - Podcast em inglês focado em Angular, o seu lançamento é irregular mas os assuntos são muito interessantes.</p>
<p><a target="_blank" href="https://braziljs.org/artigos/category/podcast/">BrazilJS</a> - Podcast em português do pessoal da BrazilJS. Além dos programas no formato de podcast, tem notícias rápidas que não necessariamente foram para o Youtube.</p>
<p><a target="_blank" href="https://castalio.info/">Castalio Podcast</a> - Podcast em português focado em Python e em todo ecossistema.</p>
<p><a target="_blank" href="https://devshow.com.br/">DevShow</a> - Podcast em português focado em desenvolvimento, e ecossistema Microsoft.</p>
<p><a target="_blank" href="https://djangochat.com/">Django Chat</a> - Podcast em inglês focado no framework web Django.</p>
<p><a target="_blank" href="https://elemencast.github.io/">ElemenCast</a> - Podcast em português que cobre temas de FrontEnd.</p>
<p><a target="_blank" href="http://falaneto.com">Faaala, Neto</a> - Podcast em português que discute temas de desenvolvimento de aplicativos móveis e desenvolvimento em geral.</p>
<p><a target="_blank" href="https://hipsters.tech/">Hipsters.tech</a> - Podcast em português referência para diversos temas na área de TI.</p>
<p><a target="_blank" href="https://www.lambda3.com.br/tag/podcast/">Lambda3</a> - Podcast em português de tecnologia com excelentes discussões. Recomendo a série sobre Microserviços.</p>
<p><a target="_blank" href="https://modernweb.podbean.com/">Modern Web podcast</a> - Podcast em inglês sobre desenvolvimento Web e JavaScript</p>
<p><a target="_blank" href="https://pythonbytes.fm/">Python Bytes</a> - Podcast em inglês sobre as últimas notícias do ecossistema Python.</p>
<p><a target="_blank" href="https://realtalkjavascript.simplecast.fm/">Real Talk JS</a> - Podcast em inglês sobre o ecossistema JavaScript.</p>
<p><a target="_blank" href="https://shoptalkshow.com/">Shop Talk</a> - Podcast em inglês que fala sobre desenvolvimento web e aspectos de negócio e do dia a dia de gestão de startups</p>
<p><a target="_blank" href="https://www.pythonpodcast.com/">Podcast.<strong>init</strong></a> - Podcast em inglês sobre o ecossistema Python.</p>
<h2 id="carreira-e-negocios">Carreira e Negócios</h2>
<p><a target="_blank" href="https://www.carreirasemfronteiras.com.br/">Carreira sem fronteiras</a> - Podcast da família do Hipsters.tech focado em carreira profissional, não apenas em tecnologia.</p>
<p><a target="_blank" href="https://www.b9.com.br/shows/codigoaberto/">Código Aberto</a> - Podcast em português de entrevistas com líderes de TI das maiores empresas do país.</p>
<p><a target="_blank" href="http://devcommunity.cc/">Dev and Community Cast</a> - Podcast em português focado em comunidades de tecnologia</p>
<h2 id="noticias-politica-e-diversidade">Notícias, Política e Diversidade</h2>
<p><a target="_blank" href="https://anticast.com.br/podcast/anticast/">AntiCast</a> - Podcast sobre política e atualidades com muito conteúdo.</p>
<p><a target="_blank" href="http://www.boanoiteinternet.com.br/">Boa Noite Internet</a> - Podcast Good Vibes do Cris Dias, bem curtinho mas muito bem produzido.</p>
<p><a target="_blank" href="https://hqdavida.com.br/">HQ da Vida</a> - Podcast focado sobre diversidade com temas muito importantes e interessantes para nosso momento atual.</p>
<p><a target="_blank" href="http://maremo.to/2019/10/05/minha-primeira-vez-01-angel-attack/#podcast">Minha primeira vez</a> - Podcast em português onde o Caio pega uma obra de entretenimento que nunca viu e descreve a sua reação. </p>
<p><a target="_blank" href="https://www.b9.com.br/shows/naruhodo/">Naruhodo</a> - Podcast sobre ciência onde toda semana uma pergunta é respondida com muito embasamento e fontes científicas, mas com um discurso leve e simples.</p>
<p><a target="_blank" href="https://www.buzzsprout.com/262153">Necton</a> - Podcast sobre economia, investimentos e finanças pessoais da Necton corretora.</p>
<p><a target="_blank" href="https://g1.globo.com/podcast/o-assunto/">O Assunto</a> - Podcast da Globo que fala sobre as últimas notícias com comentários com especialistas.</p>
<p><a target="_blank" href="https://anchor.fm/poucas">Poucas</a> - Podcast de entrevistas com diversas personalidades da internet comentando assuntos do momento.</p>
<p><a target="_blank" href="https://www.projetohumanos.com.br/temporada/o-caso-evandro/">Projeto Humanos</a> - Podcast de storytelling onde o Ivan destrincha em um trabalho muito cuidadoso histórias brasileiras. <strong>Cuidado pode acionar alguns gatilhos psicológicos.</strong></p>
<p><a target="_blank" href="https://podtail.com/pt-BR/podcast/segunda-chamada/">Segunda Chamada</a> - Podcast sobre política e atualidade realizado pelo pessoal do <a target="_blank" href="https://www.youtube.com/channel/UCUM4-KGZEXC2pk6zRDL9jMQ">MyNews</a>, canal de notícias que recomendo muito também. </p>
<h2 id="games">Games</h2>
<p><a target="_blank" href="http://jogabilida.de/">Jogabilidade</a> - Podcast sobre games, trazendo as últimas notícias da indústria e críticas de lançamentos. Além disso eles têm programas sobre filmes, animes e franguinho!</p>
]]></content:encoded></item><item><title><![CDATA[Apresentação TDC - Melhore a produtividade do seu time com o Angular Schematics]]></title><description><![CDATA[Nesse sábado dia 20/07/2019 eu tive a honra de palestrar no  TDC São Paulo  na trilha de Modern Web para conversar sobre Angular Schematic
Seguem os slides da palestra:
https://slides.com/alvarocamillont/schematics]]></description><link>https://alvarocamillont.dev/apresentacao-tdc-melhore-a-produtividade-do-seu-time-com-o-angular-schematics</link><guid isPermaLink="true">https://alvarocamillont.dev/apresentacao-tdc-melhore-a-produtividade-do-seu-time-com-o-angular-schematics</guid><category><![CDATA[Angular]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 21 Jul 2019 02:29:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1563676092268/NOMep-65l.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nesse sábado dia 20/07/2019 eu tive a honra de palestrar no  <a target='_blank' rel='noopener noreferrer'  href="http://www.thedevelopersconference.com.br/tdc/2019/saopaulo/trilhas">TDC São Paulo</a>  na trilha de Modern Web para conversar sobre Angular Schematic</p>
<p>Seguem os slides da palestra:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" href="https://slides.com/alvarocamillont/schematics" data-card-controls="0" data-card-theme="light">https://slides.com/alvarocamillont/schematics</a></div>
]]></content:encoded></item><item><title><![CDATA[Apresentação TDC -  A primeira muralha! Segurança no front end!]]></title><description><![CDATA[Nessa sexta-feira dia 19/07/2019 eu tive a honra de palestrar no  TDC São Paulo  na trilha de Software Security para conversar sobre segurança no front-end.
Seguem os slides da palestra:
https://slides.com/alvarocamillont/frontendsec]]></description><link>https://alvarocamillont.dev/apresentacao-tdc-a-primeira-muralha-seguranca-no-front-end</link><guid isPermaLink="true">https://alvarocamillont.dev/apresentacao-tdc-a-primeira-muralha-seguranca-no-front-end</guid><category><![CDATA[Angular]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 21 Jul 2019 02:23:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1563675786053/1y10KCzm1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nessa sexta-feira dia 19/07/2019 eu tive a honra de palestrar no  <a target='_blank' rel='noopener noreferrer'  href="http://www.thedevelopersconference.com.br/tdc/2019/saopaulo/trilhas">TDC São Paulo</a>  na trilha de Software Security para conversar sobre segurança no front-end.</p>
<p>Seguem os slides da palestra:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" href="https://slides.com/alvarocamillont/frontendsec" data-card-controls="0" data-card-theme="light">https://slides.com/alvarocamillont/frontendsec</a></div>
]]></content:encoded></item><item><title><![CDATA[Newsletters técnicos para pessoas desenvolvedoras.]]></title><description><![CDATA[A única constante no desenvolvimento de software é que nada é constante. Enquanto você lê essa frase, 150 novos frameworks e linguagens foram criados e já estão sendo cobrados por nossos clientes e empresas.
Para se manter atualizado sem precisar fic...]]></description><link>https://alvarocamillont.dev/newsletters-tecnicos-para-pessoas-desenvolvedoras</link><guid isPermaLink="true">https://alvarocamillont.dev/newsletters-tecnicos-para-pessoas-desenvolvedoras</guid><category><![CDATA[Angular]]></category><category><![CDATA[React]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Sun, 16 Jun 2019 03:38:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1560656265188/4N4JFSZMw.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A única constante no desenvolvimento de software é que nada é constante. Enquanto você lê essa frase, 150 novos frameworks e linguagens foram criados e já estão sendo cobrados por nossos clientes e empresas.</p>
<p>Para se manter atualizado sem precisar ficar a manhã inteira buscando blogs e portais, segue uma lista de newsletters que entregam essas novidades fresquinhas na sua caixa de entrada.</p>
<p>Esse texto é um complemento ao post do Idexo (link) que divulgou excelentes listas sobre negócios e ideias inovadoras. Esse post é para você que precisa colocar essas ideias no ar. 😃</p>
<h1 id="newsletters-front-end">Newsletters Front-End</h1>
<p>O ditado diz que a primeira impressão é a que fica, por isso é fundamental que a interface da sua aplicação seja bonita e rápida, sem esquecer nunca da acessibilidade. Aqui estão algumas listas interessantes:</p>
<h2 id="-braziljs-weekly-https-braziljs-org-weekly-"><a target='_blank' rel='noopener noreferrer'  href="https://braziljs.org/weekly/">BrazilJS Weekly</a></h2>
<p>A BrazilJS é atualmente uma das maiores comunidades não apenas de JavaScript, como desenvolvimento em geral. Sua lista tem excelentes artigos da comunidades brasileiras e internacionais.</p>
<h2 id="-angular-weekly-http-www-angular-weekly-com-"><a target='_blank' rel='noopener noreferrer'  href="http://www.angular-weekly.com/">Angular Weekly</a></h2>
<p>Esse é um newsletter com MUITO conteúdo para quem utiliza o framework Angular e as tecnologias do seu ecossistema (TypeScript/RXJS).</p>
<h2 id="-ponyfoo-https-ponyfoo-com-weekly-"><a target='_blank' rel='noopener noreferrer'  href="https://ponyfoo.com/weekly">Ponyfoo</a></h2>
<p>O Ponyfoo é um site com conteúdo focado em desenvolvimento web em geral, com bastante recursos sobre React e JavaScript.</p>
<h2 id="-alligator-io-https-www-getrevue-co-profile-alligatorio-"><a target='_blank' rel='noopener noreferrer'  href="https://www.getrevue.co/profile/alligatorio/">Alligator.io</a></h2>
<p>Site com treinamentos online que possui um newsletter quinzenal com as últimas notícias em desenvolvimento web no front-end e back-end.</p>
<h2 id="-angular-top-5-http-angulartop5-com-"><a target='_blank' rel='noopener noreferrer'  href="http://angulartop5.com/">Angular Top 5</a></h2>
<p>Toda sexta feira, esse newsletter traz as 5 maiores notícias do mundo Angular.</p>
<h2 id="-react-weekly-http-reactjsnewsletter-com-"><a target='_blank' rel='noopener noreferrer'  href="http://reactjsnewsletter.com/">React Weekly</a></h2>
<p>Excelente lista para o pessoal do React e seu ecossistema (Redux, React Native).</p>
<h2 id="-web-design-weekly-https-web-design-weekly-com-"><a target='_blank' rel='noopener noreferrer'  href="https://web-design-weekly.com/">Web Design Weekly</a></h2>
<p>Newsletter com foco em design e experiência de usuário (UX).</p>
<h1 id="newsletters-back-end">Newsletters Back-End</h1>
<p>Além da fachada e do salão, um restaurante precisa ter uma cozinha muito bem organizada e eficiente para atender os clientes. Abaixo, temos listas que podem ajudar no desenvolvimento do back-end da sua aplicação:</p>
<h2 id="-python-weekly-https-www-pythonweekly-com-"><a target='_blank' rel='noopener noreferrer'  href="https://www.pythonweekly.com/">Python Weekly</a></h2>
<p>Esse newsletter tem foco em tutoriais e novidades da linguagem Python.</p>
<h2 id="-o-reilly-programming-https-www-oreilly-com-programming-newsletter-html-"><a target='_blank' rel='noopener noreferrer'  href="https://www.oreilly.com/programming/newsletter.html">O’Reilly Programming</a></h2>
<p>Lista de e-mail da editora O’Reilly (aquela dos livros com capas de bicho) que tem muitos artigos sobre Devops, Go, Java e outras linguagens.</p>
<h2 id="-awesome-python-https-python-libhunt-com-newsletter-f-es-top-d-"><a target='_blank' rel='noopener noreferrer'  href="https://python.libhunt.com/newsletter?f=es-top-d">Awesome Python</a></h2>
<p>Esse newsletter nasceu de um repositório com os melhores recursos para desenvolvimento Python (link) e possui artigos interessantes sobre Data Science e desenvolvimento web.</p>
<h2 id="-pycoders-https-pycoders-com-"><a target='_blank' rel='noopener noreferrer'  href="https://pycoders.com/">Pycoders</a></h2>
<p>Lista de artigos com foco em Python, desenvolvimento web e Machine Learning.</p>
<h1 id="newsletters-de-cloud">Newsletters de Cloud</h1>
<p>Se você construir, eles virão, como dito no filme Campo dos sonhos (que fez 30 anos 👴🏻 👵🏻). E qual melhor lugar para construir do que a nuvem?!</p>
<h2 id="-azure-https-azureweekly-info-"><a target='_blank' rel='noopener noreferrer'  href="https://azureweekly.info/">Azure</a></h2>
<p>Esse newsletter é feito pela comunidade que utiliza a nuvem da Microsoft e cria conteúdos e tutoriais sobre a plataforma.</p>
<h2 id="-aws-https-aws-amazon-com-pt-subscribe-to-aws-announcements-"><a target='_blank' rel='noopener noreferrer'  href="https://aws.amazon.com/pt/subscribe-to-aws-announcements/">AWS</a></h2>
<p>Lista de e-mail da própria Amazon com novidades e dicas de uso dos serviços.</p>
<h1 id="b-nus">Bônus</h1>
<h2 id="-totvs-developers-https-developers-totvs-com-"><a target='_blank' rel='noopener noreferrer'  href="https://developers.totvs.com/">Totvs Developers</a></h2>
<p>Lista de e-mail com todas as novidades do desenvolvimento na plataforma da TOTVS, com tutoriais sobre o Design System (THF), dicas de desenvolvimento para o Protheus, RM e todos os produtos TOTVS. Além disso, tem muitas dicas de desenvolvimento em geral que podem ser úteis, mesmo se você não utiliza a plataforma.</p>
<p>Espero que esse post seja útil e te ajude no seu trabalho e estudos! Compartilhe com pessoal !</p>
]]></content:encoded></item><item><title><![CDATA[Tratando vazamento de memória em aplicações Angular.]]></title><description><![CDATA[Quando começamos o aprendizado de uma aplicação Angular, aprendemos o básico de RxJS para criar nossos componentes, principalmente quando temos que realizar alguma requisição HTTP. 
( link )
O conceito de Observable implementado no RxJS é poderoso e ...]]></description><link>https://alvarocamillont.dev/tratando-vazamento-de-memoria-em-aplicacoes-angular</link><guid isPermaLink="true">https://alvarocamillont.dev/tratando-vazamento-de-memoria-em-aplicacoes-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[RxJS]]></category><dc:creator><![CDATA[Alvaro Camillo Neto]]></dc:creator><pubDate>Fri, 14 Jun 2019 03:18:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1560482202953/M3JkFtJax.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Quando começamos o aprendizado de uma aplicação Angular, aprendemos o básico de RxJS para criar nossos componentes, principalmente quando temos que realizar alguma requisição HTTP. 
( <a target='_blank' rel='noopener noreferrer'  href="https://medium.com/tableless/entendendo-rxjs-observable-com-angular-6f607a9a6a00">link</a> )</p>
<p>O conceito de Observable implementado no RxJS é poderoso e nos permite acessar um fluxo de dados (como uma requisição Http) de uma maneira fluída e organizada.</p>
<p>Nesse exemplo eu estou fazendo uma requisição na API e me inscrevendo (subscribe) no retorno para atribuir a um objeto que usarei na minha interface.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="ed98552e15c0efb45fe31dfc6170507f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/ed98552e15c0efb45fe31dfc6170507f" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/ed98552e15c0efb45fe31dfc6170507f</a></div><p>Porém, nesse simples exemplo mora um perigo não muito claro, a ameaça silenciosa do vazamento de memória.</p>
<p>Quando esse componente não for mais utilizado, como por exemplo se o usuário ir para outra página, o Observable gerado por essa requisição HTTP ainda estará ativo pois o componente não se desinscreveu nele.</p>
<p>Como o componente já foi destruído, esse Observable ainda ativo virou um vazamento de memória(memory leak).</p>
<p>Isso causa uma degradação do desempenho, aumento do consumo de recursos da máquina e principalmente, perda de tempo do desenvolvedor, pois em uma aplicação grande esse tipo de erro é bem complicado de se localizar.</p>
<p>Então, o que podemos fazer ? Simples: garantir que meu componente se desinscreva sempre que ele não precisar mais do Observable!</p>
<p>OK, mas como fazer isso? Ah! Para isso temos algumas maneiras…</p>
<h2 id="a-b-sica-">A Básica.</h2>
<p>Para se desinscrever de um Observable basta você seguir dois passos:</p>
<ul>
<li><p>Guardar a inscrição: O método subscribe tem como retorno um objeto do tipo subscription que representa a inscrição realizada.</p>
</li>
<li><p>Chamar o método unsubscribe do objeto subscription.</p>
</li>
</ul>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6b647b229a9ac1b10b172ee10dda1e8b"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/6b647b229a9ac1b10b172ee10dda1e8b" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/6b647b229a9ac1b10b172ee10dda1e8b</a></div><p>Isso é simples, porém a questão é <strong>quando </strong>chamar o unsubscribe.</p>
<p>No Angular os componentes possuem métodos de ciclo de vida ( <a target='_blank' rel='noopener noreferrer'  href="https://angular.io/guide/lifecycle-hooks">Lifecycle Hooks</a> ), normalmente quando criamos via cli (ng g c) ele já vem de fábrica com o método OnInit.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="acb2b1af65b7d2590c7701fb32b54fba"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/acb2b1af65b7d2590c7701fb32b54fba" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/acb2b1af65b7d2590c7701fb32b54fba</a></div><p>Para desinscrever o componente do Observable antes dele ser destruído, podemos então utilizar o método OnDestroy.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="d7f6cee0dd18349f661e50c6627c5185"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/d7f6cee0dd18349f661e50c6627c5185" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/d7f6cee0dd18349f661e50c6627c5185</a></div><p>Pronto vazamento eliminado!</p>
<p>Porém nem sempre nossos componentes terão apenas um Observable,assim essa solução simples pode ficar um pouco feia …</p>
<p>Veja que adicionamos mais um Observable e tivemos que guardar mais uma Subscription e realizar mais uma condição no método onDestroy.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="b91817d12dc3f31140f59db5b2776a7c"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/b91817d12dc3f31140f59db5b2776a7c" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/b91817d12dc3f31140f59db5b2776a7c</a></div><p>Podemos melhorar?</p>
<h2 id="o-subsink">O SubSink</h2>
<p>Entra a biblioteca  <a target='_blank' rel='noopener noreferrer'  href="https://github.com/wardbell/subsink">SubSink </a> focada em facilitar a coleta e a desinscrição nos Observables.</p>
<p>Ela é muito simples e tem apenas um método e um atributo:</p>
<ul>
<li><p>O atributo <strong>sink </strong>onde você adiciona a inscrição em uma lista que fica implícita.</p>
</li>
<li><p>O método <strong>unsubscribe </strong>que realiza a desinscrição de toda a lista do atributo sink.</p>
</li>
</ul>
<p>Vamos ao exemplo anterior verificar como fica mais simples a administração dos Observables do componente.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="acb506eda3d9dc188a966d94136dd58b"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/acb506eda3d9dc188a966d94136dd58b" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/acb506eda3d9dc188a966d94136dd58b</a></div><p>Ainda temos mais uma alternativa. E essa já vem por padrão no Angular.</p>
<h2 id="o-pipe-async-">O pipe async.</h2>
<p>Quando componentes utilizam Observables em seus templates HTML uma alternativa muito interessante é o pipe async ( | async).</p>
<p>Com ele o componente apenas passa para o template o observable. E o motor de renderização do Angular faz o trabalho de realizar a inscrição (subscribe) e atribuir o retorno a um objeto.</p>
<p>A melhor parte é que o Angular cuida da desinscrição para você!</p>
<p>Vamos ver como ficam o template e o componente:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="16b243ce9fcda1c4a485162aef7bc095"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/16b243ce9fcda1c4a485162aef7bc095" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/16b243ce9fcda1c4a485162aef7bc095</a></div><div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="78a92ebabea640f32773f1fd3ee08c3a"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/alvarocamillont/78a92ebabea640f32773f1fd3ee08c3a" class="embed-card" data-card-width="600px" data-card-key="2e4d628b39a64b99917c73956a16b477" data-card-controls="0" data-card-theme="light">https://gist.github.com/alvarocamillont/78a92ebabea640f32773f1fd3ee08c3a</a></div><p>Veja que não temos que chamar o OnDestroy, o framework faz isso para você!</p>
<p>Para mais informações, segue o vídeo da Loiane sobre o tema( <a target='_blank' rel='noopener noreferrer'  href="https://www.youtube.com/watch?v=dKFeXl96nsA">vídeo</a> ).</p>
<h2 id="conclus-o">Conclusão</h2>
<p>Nesse artigo vimos os cuidados que temos que ter para evitar vazamento de memória (memory leaks) nas nossa aplicações Angular.</p>
<p>Resumindo:</p>
<ul>
<li><p>Se seu componente utiliza observables para apresentar informações no template, utilize o pipe async.</p>
</li>
<li><p>Se você tem apenas um observable onde você precise fazer a inscrição(subscribe), guarde o objeto Subscription em uma variável e se desinscreva no método OnDestroy do componente.</p>
</li>
<li><p>Caso seu componente tenha vários observables, utilize a bibiloteca SubSink para seu código ficar mais limpo.</p>
</li>
</ul>
<p>Código fonte do exemplo( <a target='_blank' rel='noopener noreferrer'  href="https://github.com/alvarocamillont/example_sink">link</a> ).</p>
<p>Obrigado e compartilhe esse artigo com seus colegas para eles conhecerem esses cuidados na construção de componentes Angular.</p>
]]></content:encoded></item></channel></rss>