<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Woovi</title>
    <description>The latest articles on DEV Community by Woovi (woovi).</description>
    <link>https://dev.to/woovi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F6093%2Febdfab16-778c-4fd7-8302-36924ce6f889.png</url>
      <title>DEV Community: Woovi</title>
      <link>https://dev.to/woovi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/woovi"/>
    <language>en</language>
    <item>
      <title>MED 2.0 for devs: entities, fields and the implementation flow</title>
      <dc:creator>Lucas Aguiar</dc:creator>
      <pubDate>Mon, 24 Aug 2026 19:23:08 +0000</pubDate>
      <link>https://dev.to/woovi/med-20-for-devs-entities-fields-and-the-implementation-flow-51i5</link>
      <guid>https://dev.to/woovi/med-20-for-devs-entities-fields-and-the-implementation-flow-51i5</guid>
      <description>&lt;p&gt;If you work with Pix at a fintech, one thing is certain: sooner or later you'll have to deal with fraud. And the bar the Central Bank sets for that just went up. In August 2025 the &lt;strong&gt;MED 2.0&lt;/strong&gt; rules came out (starting with &lt;strong&gt;Resolution BCB nº 493&lt;/strong&gt;), the new version of Pix's Special Refund Mechanism — optional to adopt from &lt;strong&gt;Nov 23, 2025&lt;/strong&gt; and with a mandatory rollout scheduled for 2026.&lt;/p&gt;

&lt;p&gt;In this article I want to explain, in a simple and technical way, &lt;strong&gt;what the MED entities are&lt;/strong&gt;, &lt;strong&gt;the fields that matter in each one&lt;/strong&gt; and &lt;strong&gt;how the flow works end to end&lt;/strong&gt; — with a focus on whoever is going to write the code.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🧩 First: what MED is (and why it exists)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MED (Mecanismo Especial de Devolução — Special Refund Mechanism)&lt;/strong&gt; is a regulatory obligation from the Central Bank for &lt;strong&gt;every&lt;/strong&gt; Pix participant — banks, payment institutions, fintechs, anyone who does Pix.&lt;/p&gt;

&lt;p&gt;The idea is simple: when &lt;strong&gt;fraud&lt;/strong&gt; or an &lt;strong&gt;operational failure&lt;/strong&gt; happens, there must be a &lt;strong&gt;standardized and auditable&lt;/strong&gt; path to return the victim's money. Without MED, each institution would solve it its own way (or not at all).&lt;/p&gt;

&lt;p&gt;Important: MED is &lt;strong&gt;not&lt;/strong&gt; for commercial disputes, buyer's remorse, or "I sent a Pix to the wrong person because I wasn't paying attention." It's for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scam / fraud&lt;/strong&gt; (phishing, social engineering, coercion)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Account takeover&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fraudulent access&lt;/strong&gt; to channels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Institution's operational error&lt;/strong&gt; (duplicate Pix, wrong amount from a system failure)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Rule of thumb: MED = proven fraud or an error &lt;strong&gt;by the institution&lt;/strong&gt;. It's not a "cancel my Pix" channel.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;h2&gt;
  
  
  🚀 What changes in MED 2.0
&lt;/h2&gt;

&lt;p&gt;MED 1.0 had an Achilles' heel: it only blocked and refunded at the &lt;strong&gt;first receiving account&lt;/strong&gt; of the fraudulent Pix. So the scammer pulled the classic move — received the money and &lt;strong&gt;scattered it&lt;/strong&gt; in a cascade across many accounts in seconds. By the time the block arrived, the money had already evaporated. According to the BCB, in 2025 only &lt;strong&gt;9.3%&lt;/strong&gt; of the disputed amount was recovered on average.&lt;/p&gt;

&lt;p&gt;MED 2.0 tackles exactly that: it now &lt;strong&gt;traces the money's path beyond the first account&lt;/strong&gt;. The big highlights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Multi-layer tracing.&lt;/strong&gt; DICT follows the money through the transaction graph and picks the transactions most likely to be on the drain path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeted blocking.&lt;/strong&gt; The amount is blocked at each node of the path — only what matters, not the whole account (more on this below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refund in its own name.&lt;/strong&gt; The receiver's institution &lt;strong&gt;debits the mule account and refunds the victim directly&lt;/strong&gt;, appearing as the payer on the statement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Digital self-service.&lt;/strong&gt; The harmed customer triggers the process &lt;strong&gt;from the app&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized deadlines and UX&lt;/strong&gt; (Timing Manual and Minimum UX Requirements).&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h2&gt;
  
  
  🧱 The MED entities (and how they connect)
&lt;/h2&gt;

&lt;p&gt;Before diving in, the most important thing is to understand the &lt;strong&gt;end-to-end flow&lt;/strong&gt;. It's what gives meaning to each entity:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;harmed customer&lt;/strong&gt; contacts their PSP, which opens a &lt;strong&gt;Funds Recovery&lt;/strong&gt; (&lt;code&gt;FundsRecovery&lt;/code&gt;). This is the starting point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DICT traces&lt;/strong&gt; the transactions from the root transaction and sends &lt;strong&gt;Infraction Reports&lt;/strong&gt; (&lt;code&gt;InfractionReport&lt;/code&gt;) to the PSPs of the accounts along the money's path.&lt;/li&gt;
&lt;li&gt;Each receiving PSP &lt;strong&gt;blocks the balance&lt;/strong&gt; (only the indicated amount) and &lt;strong&gt;analyzes&lt;/strong&gt; the Infraction Report.&lt;/li&gt;
&lt;li&gt;Once the infractions are analyzed, the paying PSP triggers the start of the &lt;strong&gt;Refund Requests&lt;/strong&gt; — and the money goes back to the victim, layer by layer.&lt;/li&gt;
&lt;li&gt;Along the way, &lt;strong&gt;fraud markers&lt;/strong&gt; are recorded in DICT, feeding prevention.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So there are &lt;strong&gt;four entities&lt;/strong&gt;. Understand these four and you understand MED:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity&lt;/th&gt;
&lt;th&gt;Base endpoint&lt;/th&gt;
&lt;th&gt;Role in the flow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Funds Recovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/funds-recoveries/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opens the case. The harmed customer starts it; it traces and orchestrates everything (the 2.0 highlight).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infraction Report&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/infraction-reports/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What each PSP in the chain receives. Triggers the &lt;strong&gt;block&lt;/strong&gt; and the analysis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Refund Request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/refunds/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the refund of the money to the victim, layer by layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fraud Marker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;(automatic on agreement)&lt;/td&gt;
&lt;td&gt;Flags receivers as fraudsters in DICT, feeding prevention.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's go through them one by one, in the order they appear in the flow.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🕸️ Funds Recovery (&lt;code&gt;FundsRecovery&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;This is &lt;strong&gt;the big novelty&lt;/strong&gt; of MED 2.0 — and where everything begins. When the customer is a fraud victim, the paying PSP &lt;strong&gt;opens a Funds Recovery&lt;/strong&gt; (&lt;code&gt;POST /funds-recoveries/&lt;/code&gt;). From there, DICT traces the money and orchestrates blocks and refunds.&lt;/p&gt;

&lt;h3&gt;
  
  
  The stages (this is where the "several statuses" live)
&lt;/h3&gt;

&lt;p&gt;Funds Recovery isn't a single step — it moves through &lt;strong&gt;stages with their own statuses&lt;/strong&gt;, and your backend needs to react to each transition. Today the flow is &lt;strong&gt;fully automated&lt;/strong&gt;: DICT does the tracing, prioritization and dispatch of the Infraction Reports with no manual step from the PSP.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CREATED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Funds Recovery created over the root transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TRACKED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Transaction tracking graph created&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AWAITING_ANALYSIS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Infraction Reports generated; receiving PSPs analyzing (up to 7 days)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ANALYSED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Infraction Reports analyzed and closed; the paying PSP can trigger the refund&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After &lt;code&gt;ANALYSED&lt;/code&gt; comes the &lt;strong&gt;refund&lt;/strong&gt; (requests run sequentially) and, at the end, DICT signals completion through the &lt;code&gt;FUNDS_RECOVERY_COMPLETED&lt;/code&gt; event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking graph parameters
&lt;/h3&gt;

&lt;p&gt;Parameters that bound the graph tracing (applied by DICT's algorithm):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;What it controls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MinTransactionAmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimum amount of each transaction considered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MaxTransactions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum number of transactions in the graph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HopWindow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Time window between money entering and leaving an account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MaxHops&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum graph depth (how many layers to go down)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Main endpoints
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method + route&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /funds-recoveries/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create a Funds Recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /funds-recoveries/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Query a Funds Recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /funds-recoveries/{id}/tracking-graph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create a tracking graph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /funds-recoveries/{id}/tracking-graph&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Query the graph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /funds-recoveries/{id}/block&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Request the transaction blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /funds-recoveries/{id}/infraction-reports&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List the Infraction Reports of the recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /funds-recoveries/{id}/refund&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Request a refund within the recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /funds-recoveries/{id}/refunds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List the refunds of the recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /funds-recoveries/{id}/cancel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cancel the recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;🔔 &lt;strong&gt;Don't sit there polling.&lt;/strong&gt; DICT has an events endpoint (&lt;code&gt;GET /event-notifications&lt;/code&gt;) with two key signals for the recovery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FUNDS_RECOVERY_ANALYSED&lt;/code&gt; → the Infraction Reports were analyzed; you evaluate the result and &lt;strong&gt;trigger (or not) the start of the refund&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FUNDS_RECOVERY_COMPLETED&lt;/code&gt; → the refund phase is over; anyone still holding blocked funds &lt;strong&gt;can release them&lt;/strong&gt; (if there's no other basis to keep the block).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

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

&lt;h2&gt;
  
  
  📢 Infraction Report (&lt;code&gt;InfractionReport&lt;/code&gt;) — the block
&lt;/h2&gt;

&lt;p&gt;If Funds Recovery is the customer pulling the trigger, the &lt;strong&gt;Infraction Report&lt;/strong&gt; is what lands on the &lt;strong&gt;PSPs&lt;/strong&gt; of the accounts along the money's path. Each prioritized transaction generates an Infraction Report for the PSP of that node, which then &lt;strong&gt;blocks the balance&lt;/strong&gt; and analyzes the case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main fields
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransactionId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EndToEndId of the suspicious transaction (e.g., &lt;code&gt;E999990101234...&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InfractionType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Type: &lt;code&gt;FRAUD&lt;/code&gt;, &lt;code&gt;REFUND_REQUEST&lt;/code&gt;, &lt;code&gt;REFUND_CANCELLED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FundsRecoveryId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; links the report to the Funds Recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InfractionAmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; the amount that must be blocked from that transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;InfractionData.DebitedParticipant&lt;/code&gt; / &lt;code&gt;CreditedParticipant&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;ISPBs of the payer and the receiver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InfractionData.ReportedBy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DEBITED_PARTICIPANT&lt;/code&gt; or &lt;code&gt;CREDITED_PARTICIPANT&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InfractionData.TransactionDate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Transaction date-time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InfractionData.InfractingAccountData&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Branch + account involved at the node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransactionDepth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(latest)&lt;/strong&gt; position of the transaction in the money-movement chain — how far it is from the initial fraud (DICT Manual v8.5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;OPEN&lt;/code&gt;, &lt;code&gt;ACKNOWLEDGED&lt;/code&gt;, &lt;code&gt;CLOSED&lt;/code&gt;, &lt;code&gt;CANCELLED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AnalysisResult&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AGREED&lt;/code&gt; or &lt;code&gt;DISAGREED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The block: only the &lt;code&gt;InfractionAmount&lt;/code&gt;, not the whole account
&lt;/h3&gt;

&lt;p&gt;This is &lt;strong&gt;the part that causes the most bugs&lt;/strong&gt; if you're not careful. What you block is &lt;strong&gt;not&lt;/strong&gt; the account's entire balance, &lt;strong&gt;nor&lt;/strong&gt; the full amount of the original transaction — it's exactly the &lt;strong&gt;&lt;code&gt;InfractionAmount&lt;/code&gt;&lt;/strong&gt;: the amount that node received and that needs to be held on that specific transaction.&lt;/p&gt;

&lt;p&gt;Why? Because the money spreads out. A mule account may have received R$ 800 from one branch and R$ 200 from another; each Infraction Report carries the right amount to block on each transaction. Blocking too much holds the customer's legitimate money; blocking too little lets funds slip away. &lt;strong&gt;Block the &lt;code&gt;InfractionAmount&lt;/code&gt;, no more, no less.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⏱️ The receiving PSP has &lt;strong&gt;up to 7 days&lt;/strong&gt; to analyze and close the report (&lt;code&gt;.../acknowledge&lt;/code&gt; on receipt, &lt;code&gt;.../close&lt;/code&gt; with &lt;code&gt;AGREED&lt;/code&gt;/&lt;code&gt;DISAGREED&lt;/code&gt;). Every agreement generates a &lt;strong&gt;fraud marker&lt;/strong&gt; for that receiver — even if they never end up receiving a refund request.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  💸 Refund Request (&lt;code&gt;Refund&lt;/code&gt;) — bringing the money back
&lt;/h2&gt;

&lt;p&gt;Once the Infraction Reports are analyzed (&lt;code&gt;FUNDS_RECOVERY_ANALYSED&lt;/code&gt; event), the paying PSP &lt;strong&gt;triggers the start of the refund&lt;/strong&gt;. From there DICT fires the &lt;strong&gt;Refund Requests sequentially&lt;/strong&gt;, without you having to orchestrate them one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  The key point: each refund goes to the harmed customer, only for the missing amount
&lt;/h3&gt;

&lt;p&gt;Here lies the biggest mindset shift of 2.0. &lt;strong&gt;Every refund request is destined to the harmed customer&lt;/strong&gt; (the user of the paying PSP who opened the recovery), and the goal is to &lt;strong&gt;return the money wherever it is&lt;/strong&gt; in the chain. Rules that show up on the test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;1st request&lt;/strong&gt; always goes to the receiver of the &lt;strong&gt;root transaction&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;subsequent ones&lt;/strong&gt; follow the &lt;strong&gt;priority&lt;/strong&gt; defined in the blocking stage.&lt;/li&gt;
&lt;li&gt;Each PSP &lt;strong&gt;debits the mule account&lt;/strong&gt; and refunds &lt;strong&gt;directly to the harmed customer&lt;/strong&gt;, appearing as the &lt;strong&gt;payer&lt;/strong&gt; on the statement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only the missing amount is requested&lt;/strong&gt; to complete the total — never the full initial amount again. BCB's own example: even with &lt;strong&gt;R$ 800 blocked&lt;/strong&gt; at a node, if R$ 250 was already recovered, the refund is requested &lt;strong&gt;for the remaining R$ 750 only&lt;/strong&gt;. The amounts are &lt;strong&gt;updated automatically&lt;/strong&gt; with each new refund.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: the system keeps "scraping" whatever it can from each account until the total is met, never refunding more than owed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main fields
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransactionId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Transaction being refunded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RefundReason&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;FRAUD&lt;/code&gt;, &lt;code&gt;OPERATIONAL_FLAW&lt;/code&gt;, &lt;code&gt;REFUND_CANCELLED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RefundAmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Requested amount — &lt;strong&gt;the remainder&lt;/strong&gt;, not the full value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FundsRecoveryId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; links the refund to the recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RefundAccount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; destination account for the payment (the harmed customer's)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MonitorAccount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; whether the account should be &lt;strong&gt;monitored&lt;/strong&gt; for future blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EffectiveRefundedAmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(MED 2.0)&lt;/strong&gt; on closure, the amount &lt;strong&gt;actually&lt;/strong&gt; refunded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;OPEN&lt;/code&gt;, &lt;code&gt;CLOSED&lt;/code&gt;, &lt;code&gt;CANCELLED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AnalysisResult&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;TOTALLY_ACCEPTED&lt;/code&gt;, &lt;code&gt;PARTIALLY_ACCEPTED&lt;/code&gt;, &lt;code&gt;REJECTED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RefundRejectionReason&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NO_BALANCE&lt;/code&gt;, &lt;code&gt;ACCOUNT_CLOSURE&lt;/code&gt;, &lt;code&gt;CANNOT_REFUND&lt;/code&gt;, &lt;code&gt;OTHER&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Partial refund + monitoring is the nastiest real-world case.&lt;/strong&gt; If the account doesn't have the full balance at the moment (&lt;code&gt;PARTIALLY_ACCEPTED&lt;/code&gt; / &lt;code&gt;NO_BALANCE&lt;/code&gt;), you accept what you can, report the &lt;code&gt;EffectiveRefundedAmount&lt;/code&gt; and, with &lt;code&gt;MonitorAccount&lt;/code&gt; on, &lt;strong&gt;monitor the account&lt;/strong&gt; to keep blocking and refunding in parts as money comes in. Model this from the start — it's not an exception, it's routine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🚩 Fraud Marker (prevention)
&lt;/h2&gt;

&lt;p&gt;MED isn't only about putting out fires — it &lt;strong&gt;feeds prevention&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When an Infraction Report is &lt;strong&gt;agreed&lt;/strong&gt; (&lt;code&gt;AGREED&lt;/code&gt;), the receiver is &lt;strong&gt;flagged as a fraudster in DICT&lt;/strong&gt;, automatically. And there's an important 2.0 detail: &lt;strong&gt;all&lt;/strong&gt; receivers of transactions with an agreed report get flagged — &lt;strong&gt;even the ones that never receive&lt;/strong&gt; a refund request (e.g., a node that fell outside the continuous path of the graph).&lt;/p&gt;

&lt;p&gt;These markers feed DICT's anti-fraud data (counters of settlements, reported frauds and confirmed frauds, by key, by owner and by account).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🎯 &lt;strong&gt;Where this becomes gold:&lt;/strong&gt; query that anti-fraud data for the destination key/account &lt;strong&gt;before releasing a cash-out&lt;/strong&gt;. A recent fraud signal? You hold, ask for a double-check or add friction. Preventing is far cheaper than running the whole recovery flow.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;h2&gt;
  
  
  📅 The deadlines you CAN'T miss
&lt;/h2&gt;

&lt;p&gt;A blown deadline in MED = money lost or a regulatory fine. Nail these into your scheduler (the definitive source is the &lt;strong&gt;Pix Timing Manual&lt;/strong&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Deadline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Maximum transaction age to open a case&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;80 days&lt;/strong&gt; after the Pix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infraction Report analysis by the receiving PSP&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;up to 7 days&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start the refund after the reports are analyzed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;up to 72 hours&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Strong recommendation: model each deadline as a &lt;strong&gt;scheduled job&lt;/strong&gt; with alerts. Don't rely on someone watching a spreadsheet. A due SLA is a system event.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ✅ When to use (and NOT use) MED
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You can use it for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proven scam/fraud&lt;/li&gt;
&lt;li&gt;Account takeover / coercion / fraudulent access&lt;/li&gt;
&lt;li&gt;The institution's own operational error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You can't use it for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commercial disputes ("the product never arrived")&lt;/li&gt;
&lt;li&gt;Buyer's remorse&lt;/li&gt;
&lt;li&gt;A Pix sent to the wrong person by the &lt;strong&gt;payer's own mistake&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Disputes between good-faith third parties&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏁 Wrapping up
&lt;/h2&gt;

&lt;p&gt;MED 2.0 changes the game of fraud recovery on Pix: gone is the focus on a single account, in comes &lt;strong&gt;tracing the money's path&lt;/strong&gt;, with targeted blocking and layer-by-layer refunds. For your fintech, the summary is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧭 &lt;strong&gt;The flow starts with the customer&lt;/strong&gt;: they open the Funds Recovery, which traces and fires the Infraction Reports.&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Block the &lt;code&gt;InfractionAmount&lt;/code&gt;&lt;/strong&gt;, not the whole account — that's the detail that bites the most.&lt;/li&gt;
&lt;li&gt;💸 &lt;strong&gt;Each refund goes to the harmed customer and only for the missing amount&lt;/strong&gt; — the goal is to bring the money back wherever it is.&lt;/li&gt;
&lt;li&gt;🔔 &lt;strong&gt;Use events, not polling&lt;/strong&gt; (&lt;code&gt;FUNDS_RECOVERY_ANALYSED&lt;/code&gt;, &lt;code&gt;FUNDS_RECOVERY_COMPLETED&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;📚 The &lt;strong&gt;source of truth&lt;/strong&gt; is always the DICT API spec and the BCB rules — check the current version before coding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Official sources (BCB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.bcb.gov.br/estabilidadefinanceira/pix-normas" rel="noopener noreferrer"&gt;Pix rules — Central Bank of Brazil&lt;/a&gt; and &lt;strong&gt;Resolution BCB nº 493/2025&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.bcb.gov.br/content/estabilidadefinanceira/pix/MED/MED_2-0_Circuito_Pix-Dia_1.pdf" rel="noopener noreferrer"&gt;Circuito Pix — MED 2.0, Day 1&lt;/a&gt; and &lt;a href="https://www.bcb.gov.br/content/estabilidadefinanceira/pix/MED/MED_2-0_Circuito_Pix-Dia_2.pdf" rel="noopener noreferrer"&gt;Day 2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bcb.gov.br/content/estabilidadefinanceira/pix/Guia_MED.pdf" rel="noopener noreferrer"&gt;Refund procedures implementation guide (MED)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bacen/pix-dict-api" rel="noopener noreferrer"&gt;DICT API — official repository &lt;code&gt;bacen/pix-dict-api&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it! If you're implementing MED 2.0 at your fintech and hit a wall, drop a comment and let's talk it through. 🚀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating a Certificate X.509 expiration Dashboard using Grafana</title>
      <dc:creator>Sibelius Seraphini</dc:creator>
      <pubDate>Mon, 05 Jan 2026 12:49:08 +0000</pubDate>
      <link>https://dev.to/woovi/creating-a-certificate-x509-expiration-dashboard-using-grafana-211k</link>
      <guid>https://dev.to/woovi/creating-a-certificate-x509-expiration-dashboard-using-grafana-211k</guid>
      <description>&lt;p&gt;At Woovi, we need to manage many X.509 certificates that are not only related to site domains. We have certificates that enable mTLS connections, allow us to sign ISO 20022 XML messages, and provide some A1 and A3 certificates to emit electronic invoices (notas fiscais) and access certain Central Bank and government systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current state of certificate expiration tools
&lt;/h2&gt;

&lt;p&gt;Most certificate expiration tools are focused on renewing site domain certificates. My problem is just to check the expiration of X.509 without auto-renew, as the renewal process requires a real person verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  x509-certificate-exporter + Grafana Dashboard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/enix/x509-certificate-exporter" rel="noopener noreferrer"&gt;x509-certificate-exporter&lt;/a&gt; is a Prometheus exporter that can read X.509 certificates from many sources, like files, Kubernetes configs, and secrets.&lt;/p&gt;

&lt;p&gt;Here is a basic deployment to watch files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;enix/x509-certificate-exporter:latest&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9793&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;certs&lt;/span&gt;
              &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/certs&lt;/span&gt;
              &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--debug&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--watch-dir=/etc/certs&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;certs&lt;/span&gt;
          &lt;span class="na"&gt;configMap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to use Kustomization to generate the configmaps from X.509 files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kustomize.config.k8s.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Kustomization&lt;/span&gt;

&lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificate-exporter&lt;/span&gt;

&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;deployment.yaml&lt;/span&gt;

&lt;span class="na"&gt;configMapGenerator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x509-certificates&lt;/span&gt;
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./certs/cert-a.crt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./certs/cert-b.crt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply this kustomization like this &lt;code&gt;kubectl apply -k /deployments/x509-certificate-exporter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add this Grafana dashboard &lt;a href="https://grafana.com/grafana/dashboards/13922-certificates-expiration-x509-certificate-exporter/" rel="noopener noreferrer"&gt;Certificates Expiration (X509 Certificate Exporter)&lt;/a&gt; and you are all set.&lt;/p&gt;

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

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

&lt;p&gt;Kubernetes, Prometheus, and Grafana are versatile tools that enable you to build a custom dashboard to solve common problems in many companies.&lt;br&gt;
Set this up in your company and avoid having certificate expiration issues forever.&lt;br&gt;
The next step would be to set up alerts to renew certificates before the expiration date.&lt;/p&gt;

&lt;p&gt;What monitoring solutions are you using in your company?&lt;/p&gt;




&lt;p&gt;Woovi&lt;br&gt;
&lt;a href="https://www.woovi.com" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.&lt;/p&gt;

&lt;p&gt;If you want to work with us, we are &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>x509</category>
      <category>certificate</category>
      <category>grafana</category>
      <category>devops</category>
    </item>
    <item>
      <title>Saving Terraform State in S3</title>
      <dc:creator>Sibelius Seraphini</dc:creator>
      <pubDate>Thu, 04 Dec 2025 12:55:08 +0000</pubDate>
      <link>https://dev.to/woovi/saving-terraform-state-in-s3-4ja7</link>
      <guid>https://dev.to/woovi/saving-terraform-state-in-s3-4ja7</guid>
      <description>&lt;p&gt;Terraform is a solution to provision infrastructure using code (IaC).&lt;br&gt;
Terraform stores the infrastructure generated in a state.&lt;br&gt;
This state maps the real world and metadata to Terraform.&lt;br&gt;
This ensures that you won't duplicate or recreate existing resources.&lt;/p&gt;
&lt;h2&gt;
  
  
  Storing Terraform State in an S3 bucket
&lt;/h2&gt;

&lt;p&gt;You can use S3 as the backend of the state like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 4.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0"&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-state-dev"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-key"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
    &lt;span class="nx"&gt;shared_credentials_file&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~/.aws/credentials"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can have a single key to store all your Terraform state, or you can have one key for each Terraform state.&lt;/p&gt;

&lt;p&gt;You can start your Terraform using &lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After any &lt;code&gt;terraform apply&lt;/code&gt; or &lt;code&gt;terraform apply&lt;/code&gt; the state in your S3 will be updated.&lt;/p&gt;

&lt;p&gt;At Woovi, we decided to have one key per Terraform provision.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to migrate existing local state?
&lt;/h2&gt;

&lt;p&gt;You can use this command to migrate existing local or another backend state to your S3 bucket&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init &lt;span class="nt"&gt;-migrate-state&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In Resume
&lt;/h2&gt;

&lt;p&gt;If you lose your Terraform state, this can cause significant trouble.&lt;br&gt;
Keeping them in an S3 bucket can make it shareable across your team.&lt;/p&gt;




&lt;p&gt;Woovi&lt;br&gt;
&lt;a href="https://www.woovi.com" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.&lt;/p&gt;

&lt;p&gt;If you want to work with us, we are &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>s3</category>
    </item>
    <item>
      <title>Creating a S3 bucket using Terraform</title>
      <dc:creator>Sibelius Seraphini</dc:creator>
      <pubDate>Wed, 03 Dec 2025 10:17:55 +0000</pubDate>
      <link>https://dev.to/woovi/creating-a-s3-bucket-using-terraform-4kgb</link>
      <guid>https://dev.to/woovi/creating-a-s3-bucket-using-terraform-4kgb</guid>
      <description>&lt;p&gt;S3 is the de facto and most well-known solution for object storage.&lt;br&gt;
Object storage allows you to store files in a specific bucket and key.&lt;/p&gt;

&lt;p&gt;When your application is small, you just need to manage a few S3 buckets, and you can manage them using the AWS UI.&lt;/p&gt;

&lt;p&gt;The problem is how to reproduce the same S3 bucket configuration over and over again, and from staging to production. &lt;br&gt;
Each S3 bucket has specific needs.&lt;/p&gt;

&lt;p&gt;It is also hard to see how all the S3 buckets are configured or how to change some configurations.&lt;/p&gt;
&lt;h2&gt;
  
  
  S3 using Terraform
&lt;/h2&gt;

&lt;p&gt;Terraform enables you to declare your infrastructure as code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 4.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Create S3 bucket for Terraform state&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"mybucket"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mybucket"&lt;/span&gt;

  &lt;span class="nx"&gt;force_destroy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mybucket"&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev"&lt;/span&gt;
    &lt;span class="nx"&gt;ManagedBy&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Enable versioning (so you can roll back state if needed)&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_versioning"&lt;/span&gt; &lt;span class="s2"&gt;"versioning"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mybucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;versioning_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Enabled"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Enable server-side encryption by default&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_server_side_encryption_configuration"&lt;/span&gt; &lt;span class="s2"&gt;"sse"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mybucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;apply_server_side_encryption_by_default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sse_algorithm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AES256"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Block public access&lt;/span&gt;
&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket_public_access_block"&lt;/span&gt; &lt;span class="s2"&gt;"block"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_s3_bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mybucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;

  &lt;span class="nx"&gt;block_public_acls&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;block_public_policy&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;ignore_public_acls&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;restrict_public_buckets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You just need to type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And your S3 bucket is created.&lt;/p&gt;

&lt;p&gt;If you modify your Terraform file and run &lt;code&gt;terraform apply&lt;/code&gt; , it will show what changed and only apply the modifications.&lt;/p&gt;

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

&lt;p&gt;Using Terraform to provision your infrastructure can help you go from simple S3 buckets to very complex applications.&lt;/p&gt;




&lt;p&gt;Woovi&lt;br&gt;
&lt;a href="https://www.woovi.com" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.&lt;/p&gt;

&lt;p&gt;If you want to work with us, we are &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>s3</category>
      <category>objectstorage</category>
      <category>devops</category>
    </item>
    <item>
      <title>Copy and Paste on Proxmox VM</title>
      <dc:creator>Sibelius Seraphini</dc:creator>
      <pubDate>Tue, 02 Dec 2025 10:52:48 +0000</pubDate>
      <link>https://dev.to/woovi/copy-and-paste-on-proxmox-vm-15il</link>
      <guid>https://dev.to/woovi/copy-and-paste-on-proxmox-vm-15il</guid>
      <description>&lt;p&gt;Copy and paste does not work well on Proxmox KVM on the UI.&lt;br&gt;
You can try to connect using a serial port to enable copy and paste over the UI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using a Script
&lt;/h2&gt;

&lt;p&gt;We created a script to simulate keyboard typing and paste data over KVM when using the UI.&lt;/p&gt;

&lt;p&gt;Open your Chrome Dev Tools, and paste this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;capsLockOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SHIFT_NEEDED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z!@#$%^&amp;amp;*()_+{}:"&amp;lt;&amp;gt;?~|&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;needsShift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SHIFT_NEEDED&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isUpperCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needsShift&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shift&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUpperCase&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;capsLockOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needsShift&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;simulateKeyEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shift&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CapsLock&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;capsLockOn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;capsLockOn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Caps Lock state changed:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;capsLockOn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;cp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;typeChar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;sendKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeChar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Adjust delay as needed&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;typeChar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To paste something, you first need to focus on the UI, and then type &lt;code&gt;cp('mydata')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can use this when you don't have access to the VM over SSH.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summary
&lt;/h2&gt;

&lt;p&gt;If you are creative enough, you can solve these limitations.&lt;/p&gt;




&lt;p&gt;Woovi&lt;br&gt;
&lt;a href="https://www.woovi.com" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.&lt;/p&gt;

&lt;p&gt;If you want to work with us, we are &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>proxmox</category>
      <category>canvas</category>
      <category>script</category>
    </item>
    <item>
      <title>Using Terraform to create LXC in Proxmox</title>
      <dc:creator>Sibelius Seraphini</dc:creator>
      <pubDate>Mon, 01 Dec 2025 11:40:44 +0000</pubDate>
      <link>https://dev.to/woovi/using-terraform-to-create-lxc-in-proxmox-496h</link>
      <guid>https://dev.to/woovi/using-terraform-to-create-lxc-in-proxmox-496h</guid>
      <description>&lt;p&gt;Terraform is a well-known solution for defining, provisioning, and managing Infrastructure as Code (IaC).&lt;br&gt;
Most of the content out there focuses on major clouds as AWS, GCP, and Azure.&lt;br&gt;
I'd like to focus on Proxmox, an open source hypervisor used in a lot of home labs and also in production for companies that follow the baremetal approach, like Woovi.&lt;/p&gt;
&lt;h2&gt;
  
  
  Proxmox Infrastructure
&lt;/h2&gt;

&lt;p&gt;Proxmox is a virtualization platform. You can create VMs and LXC (Linux Containers) using the UI, but when your team grows, and you want to be able to reproduce the same staging environment at production, you need to use IaC.&lt;br&gt;
IaC is also great to make sure something is reproducible.&lt;/p&gt;
&lt;h2&gt;
  
  
  VMs vs LXC
&lt;/h2&gt;

&lt;p&gt;You can think of LXC as simpler and lighter VMs.&lt;br&gt;
LXC provides less isolation, and some software can't run on top of it easily, like microk8s nodes.&lt;br&gt;
We are going to focus on LXC to make this article simpler.&lt;/p&gt;
&lt;h2&gt;
  
  
  Provisioning using Terraform
&lt;/h2&gt;

&lt;p&gt;You can have the whole definition in the same file or split it into many files in the same folder.&lt;/p&gt;

&lt;p&gt;First, define the provider Proxmox from Telmate.&lt;/p&gt;

&lt;p&gt;Also, define the Proxmox provider variable like api_url, token ID, and token secret.&lt;br&gt;
You can follow this documentation &lt;a href="https://registry.terraform.io/providers/Terraform-for-Proxmox/proxmox/latest/docs" rel="noopener noreferrer"&gt;terraform for proxmox&lt;/a&gt; to generate the token ID and token secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxmox&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"telmate/proxmox"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3.0.2-rc04"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"proxmox"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pm_api_url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://myproxmoxnode:8006/api2/json"&lt;/span&gt;
  &lt;span class="nx"&gt;pm_tls_insecure&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;pm_log_enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;pm_debug&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;pm_api_token_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PM_API_TOKEN_ID&lt;/span&gt;
  &lt;span class="nx"&gt;pm_api_token_secret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PM_API_TOKEN_SECRET&lt;/span&gt;
  &lt;span class="nx"&gt;pm_log_levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;_default&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"debug"&lt;/span&gt;
    &lt;span class="nx"&gt;_capturelog&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"PM_API_TOKEN_ID"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"PM_API_TOKEN_SECRET"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;define the LXC resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"proxmox_lxc"&lt;/span&gt; &lt;span class="s2"&gt;"mongo-1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;target_node&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dev1"&lt;/span&gt;
  &lt;span class="nx"&gt;hostname&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mongo1"&lt;/span&gt;
  &lt;span class="nx"&gt;ostemplate&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst"&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LXC_PASSWORD&lt;/span&gt;

  &lt;span class="nx"&gt;unprivileged&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;cores&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="nx"&gt;memory&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;
  &lt;span class="nx"&gt;swap&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;

  &lt;span class="nx"&gt;rootfs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"local-lvm"&lt;/span&gt;
    &lt;span class="nx"&gt;size&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"50G"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eth0"&lt;/span&gt;
    &lt;span class="nx"&gt;bridge&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vmbr0"&lt;/span&gt;
    &lt;span class="nx"&gt;ip&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.99.90.2/16"&lt;/span&gt;
    &lt;span class="nx"&gt;gw&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.99.0.3"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ssh_public_keys&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"~/.ssh/id_ansible.pub"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;ini&lt;/code&gt; to initialize Terraform&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;apply&lt;/code&gt; to provision the lxc resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run destroy to destroy everything&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, you need to save the local Terraform files to avoid recreating the resources. For production, the best approach is to keep  Terraform state in an S3 bucket&lt;/p&gt;

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

&lt;p&gt;You don't need to start your MVP Startup using Terraform to provision everything in your Proxmox. &lt;br&gt;
My recommendation is to keep improving automation as you and your team grow.&lt;br&gt;
After you get the first Terraform working, the rest gets easier.&lt;/p&gt;

&lt;p&gt;How are you using Terraform in your company?&lt;/p&gt;




&lt;p&gt;Woovi&lt;br&gt;
&lt;a href="https://www.woovi.com" rel="noopener noreferrer"&gt;Woovi&lt;/a&gt; is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.&lt;/p&gt;

&lt;p&gt;If you want to work with us, we are &lt;a href="https://woovi.com/jobs/" rel="noopener noreferrer"&gt;hiring&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>proxmox</category>
      <category>baremetal</category>
      <category>iac</category>
    </item>
    <item>
      <title>Understanding IMAP and SMTP Mail Protocols</title>
      <dc:creator>Lucas Aguiar</dc:creator>
      <pubDate>Sat, 26 Jul 2025 01:48:38 +0000</pubDate>
      <link>https://dev.to/woovi/understanding-imap-and-smtp-mail-protocols-1bch</link>
      <guid>https://dev.to/woovi/understanding-imap-and-smtp-mail-protocols-1bch</guid>
      <description>&lt;p&gt;During a recent implementation of a customer service platform, I encountered several configuration challenges related to email communication protocols. This experience prompted me to conduct thorough research into SMTP and IMAP protocols, their interactions, and best implementation practices. The knowledge gained proved invaluable for resolving our technical issues, and I'm sharing these insights to benefit others facing similar challenges in their systems architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  📮 Introduction
&lt;/h2&gt;

&lt;p&gt;In the digital world, sending and receiving emails are fundamental communication processes. During my recent experience, I realized that understanding how these protocols work behind the scenes can make all the difference, especially when configuring or troubleshooting customer service systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Overview of Email Protocols
&lt;/h2&gt;

&lt;p&gt;Emails travel between computers using standardized protocols. The most common ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP (Simple Mail Transfer Protocol)&lt;/strong&gt;: Used for sending messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IMAP (Internet Message Access Protocol)&lt;/strong&gt;: Used for accessing and managing messages stored on the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While POP3 also exists, this article focuses on SMTP and IMAP, which offer advantages for synchronization and email management across multiple devices.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  📤 SMTP - Simple Mail Transfer Protocol
&lt;/h2&gt;

&lt;p&gt;SMTP is the "engine" that sends emails. Here's a summary of what I learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Function&lt;/strong&gt;: SMTP is responsible for sending messages from the sender to the server, and between servers, ensuring the email reaches its recipient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How It Works&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The process begins with the email client sending the message to the SMTP server&lt;/li&gt;
&lt;li&gt;Commands like EHLO/HELO, MAIL FROM, RCPT TO, and DATA structure this communication&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Ports and Security&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Common ports include 25 (traditional) and 587 (for authenticated sending)&lt;/li&gt;
&lt;li&gt;Using TLS or SSL encryption is highly recommended to protect data during transmission&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  📥 IMAP - Internet Message Access Protocol
&lt;/h2&gt;

&lt;p&gt;While SMTP handles sending, IMAP is the "manager" of received emails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Function&lt;/strong&gt;: IMAP allows you to access and manage emails directly on the server. This means that regardless of which device you use—smartphone, tablet, or computer—your messages remain synchronized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advantages over POP3&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Messages remain stored on the server, allowing viewing and organization from any device&lt;/li&gt;
&lt;li&gt;You can create, move, and delete folders directly on the server without downloading emails&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;How It Works&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;IMAP synchronizes message status (e.g., read/unread) and organizes emails into folders&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Ports and Security&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Port 143 is used for unencrypted connections, while port 993 is for secure connections via SSL/TLS&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  ⚖️ Comparison Between SMTP and IMAP
&lt;/h2&gt;

&lt;p&gt;Although both protocols are part of email communication, they have distinct, complementary roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Responsible for sending emails&lt;/li&gt;
&lt;li&gt;Functions as the "digital mail carrier" distributing messages between servers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;IMAP&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Responsible for accessing and managing stored messages&lt;/li&gt;
&lt;li&gt;Allows you to track your emails in a synchronized manner across multiple devices&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  ⚙️ Technical Aspects and Implementation
&lt;/h2&gt;

&lt;p&gt;During my experience, I found that visualizing the email flow helps better understand how these protocols interact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sending and Receiving Flow&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The email leaves the client and goes to the SMTP server&lt;/li&gt;
&lt;li&gt;From there, it may be forwarded to other servers until it reaches the recipient's server&lt;/li&gt;
&lt;li&gt;Finally, the email client uses IMAP to access and manage this message on the server&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Configuration and Authentication&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Correctly configuring ports and authentication methods (such as TLS/SSL) is essential to ensure everything works smoothly&lt;/li&gt;
&lt;li&gt;In many situations, the challenge lies precisely in aligning these configurations for efficient and secure customer service operation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  🔒 Security and Best Practices
&lt;/h2&gt;

&lt;p&gt;To avoid headaches (like the one I faced), it's important to pay attention to these points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Common Threats&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Without proper security, data can be intercepted during transmission&lt;/li&gt;
&lt;li&gt;Configuration errors can create vulnerabilities for spam or even more serious attacks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Security Measures&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Always use encryption (SSL/TLS) in communications&lt;/li&gt;
&lt;li&gt;Regularly verify and update server authentication configurations&lt;/li&gt;
&lt;li&gt;Follow recommended best practices for both administrators and end users&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Understanding SMTP and IMAP protocols was essential to solving the problem I encountered when configuring the customer service system. With SMTP handling sending and IMAP enabling access and message management, both complement each other to make email communication fluid and secure.&lt;/p&gt;

&lt;p&gt;I hope this article, written simply and based on my experience, helps you better understand how these protocols work. After all, sharing knowledge is a way to grow and make life easier for those who also need to deal with these configurations daily.&lt;/p&gt;




&lt;p&gt;If you have questions or want to explore any topic in greater depth, feel free to comment. We're all learning together!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My second week on Woovi: Getting into the swing of things (or almost there)</title>
      <dc:creator>Adam Neves</dc:creator>
      <pubDate>Tue, 15 Jul 2025 23:36:37 +0000</pubDate>
      <link>https://dev.to/woovi/my-second-week-on-woovi-getting-into-the-swing-of-things-or-almost-there-h1p</link>
      <guid>https://dev.to/woovi/my-second-week-on-woovi-getting-into-the-swing-of-things-or-almost-there-h1p</guid>
      <description>&lt;h3&gt;
  
  
  A False Sense of Comfort
&lt;/h3&gt;

&lt;p&gt;My second week at Woovi felt calmer. I started delivering more and understood the codebase better, although honestly, I probably understand only 1 percent of what I need.&lt;/p&gt;

&lt;p&gt;What’s interesting is that even as things started to fall into place, I realized how much context and depth are still missing. Each day exposes new gaps, unexpected architectural decisions, and subtle product nuances that force you to slow down and truly think.&lt;/p&gt;

&lt;h3&gt;
  
  
  Growth Beyond Code
&lt;/h3&gt;

&lt;p&gt;A clear pattern emerged: every day, someone taught me something, whether technical or related to soft skills.&lt;/p&gt;

&lt;p&gt;At Woovi, everyone seems to have a superpower. Some are masters of communication, others have exceptional technical depth, and some have sharp product instincts that guide big decisions. You start to see how each strength blends into the culture and how these traits build an environment where questioning and debating ideas is not just allowed but expected.&lt;/p&gt;

&lt;p&gt;One of the most interesting cultural lessons this week was about how learning is shared. For example, today I learned about &lt;strong&gt;eventual consistency&lt;/strong&gt;, a fundamental concept in distributed systems. It means that while data updates might not be immediately visible everywhere, the system will eventually reach a consistent state. In practice, this forces you to think differently about user experience, error handling, and how to communicate system states clearly to users.&lt;/p&gt;

&lt;p&gt;These small technical insights are passed around naturally, in PR comments, quick chats, or even casual messages. They aren't pushed in forced "knowledge sharing" sessions; they emerge as part of daily work.&lt;/p&gt;

&lt;p&gt;This also reinforces a crucial point: growth here depends on you actively engaging. If you stay passive, you risk missing valuable lessons hidden in daily interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow Maturity
&lt;/h3&gt;

&lt;p&gt;I noticed a significant evolution in our workflow. In the first few days, things felt a bit chaotic, with processes and responsibilities less defined. By the second week, communication aligned, priorities became clearer, and deliveries started to feel more predictable.&lt;/p&gt;

&lt;p&gt;This transition from initial chaos to controlled speed shows that Woovi is constantly iterating. There is no static mindset of “we’ve solved everything.” The culture is shaped around continuous improvement, even in internal processes. Everyone is expected to contribute to refining how we work, not just what we build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Motivation and Expectation
&lt;/h3&gt;

&lt;p&gt;Watching the team operate at this level is energizing. It pushes you to deliver more, keep improving, and constantly challenge your own limits.&lt;/p&gt;

&lt;p&gt;Are we moving toward excellence? For me, the answer is yes. But it’s not the kind of excellence that comes from rigid structure or strict guidelines. It’s an evolving, living excellence that requires self-drive, curiosity, and a willingness to get uncomfortable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Progress can feel fast, but there is always deeper context to uncover.&lt;/li&gt;
&lt;li&gt;Learning here is organic and requires proactive behavior.&lt;/li&gt;
&lt;li&gt;Process improvements are constant and collective, not accidental.&lt;/li&gt;
&lt;li&gt;The culture values questioning and sees discomfort as a growth catalyst.&lt;/li&gt;
&lt;li&gt;Technical lessons like eventual consistency show how deep the rabbit hole goes, even in seemingly "simple" features.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The second week was not about settling in. It was about realizing how much there still is to learn, both technically and personally.&lt;/p&gt;




&lt;p&gt;The main lesson? Onboarding never truly ends here, and that might be exactly the point.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>My First 7 Days at Woovi: Learnings, Surprises, and Open Questions</title>
      <dc:creator>Adam Neves</dc:creator>
      <pubDate>Wed, 09 Jul 2025 01:54:54 +0000</pubDate>
      <link>https://dev.to/woovi/my-first-7-days-at-woovi-learnings-surprises-and-open-questions-3mb3</link>
      <guid>https://dev.to/woovi/my-first-7-days-at-woovi-learnings-surprises-and-open-questions-3mb3</guid>
      <description>&lt;p&gt;Starting at a new company is often romanticized: welcome coffees, a nicely packaged onboarding plan, and a slow ramp-up. My first week at Woovi turned out to be quite the opposite: a fast-paced, pragmatic environment where questioning is not only allowed but expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  First Impressions
&lt;/h2&gt;

&lt;p&gt;On day one, I realized the culture is heavily biased towards fast delivery and technical autonomy. Instead of following step-by-step tutorials, I was encouraged to explore real repositories, understand actual deployment flows, and challenge architectural decisions.&lt;/p&gt;

&lt;p&gt;This breaks the common assumption that onboarding must be 100% guided and “hand-holding.” Here, you’re treated as someone who should contribute from day one, not just passively consume information.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fear of Not Being Enough
&lt;/h2&gt;

&lt;p&gt;A hidden part of this experience was the fear of not being enough for the role. I came in wondering if I could really match the expectations, whether I would deliver fast enough, and whether I would truly add value.&lt;/p&gt;

&lt;p&gt;Very quickly, I realized there was no way to simply "meet expectations" here. Woovi feels more like a high-level engineering school than a typical company. You could be the most senior engineer out there, and you would still get overwhelmed by the codebase. It’s the result of years of creation, iteration, and continuous learning.&lt;/p&gt;

&lt;p&gt;This realization actually eased my anxiety. Instead of obsessing over "being enough," I shifted focus to learning fast and contributing incrementally. The expectation is not perfection on day one. The expectation is to keep moving, questioning, improving, and growing as part of the team.&lt;/p&gt;

&lt;p&gt;The codebase will push you out of your comfort zone. But in return, it turns you into a better engineer, faster than any comfortable environment ever could.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Challenges
&lt;/h2&gt;

&lt;p&gt;During the week, I dived into the main stack, Node.js, Koa, TypeScript, GraphQL, Relay and integrations with financial systems like Pix and payment gateways. One surprise was how modular yet unopinionated the architecture is: there’s more room for customization, and fewer rigid patterns.&lt;/p&gt;

&lt;p&gt;This requires critical thinking: you can’t just “do it like Google.” You have to weigh real trade-offs, performance vs readability, coupling vs delivery speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team Integration
&lt;/h2&gt;

&lt;p&gt;Most interactions happened asynchronously. Far fewer meetings than I expected. This forces you to write better,&amp;nbsp;whether it’s commits, pull requests, or internal docs, and not rely on endless live clarifications.&lt;/p&gt;

&lt;p&gt;Interestingly, this exposed a personal flaw: I underestimated how much poor written communication can slow down a project. If you don’t document well, everyone stops to answer your basic questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Still Question
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Does a loose, self-guided onboarding work for everyone?&lt;/li&gt;
&lt;li&gt;How much does full autonomy from day one increase the risk of mistakes or rework?&lt;/li&gt;
&lt;li&gt;Does async culture, while efficient, alienate those who prefer real-time discussions?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions stuck with me all week. I don’t have final answers yet, but I’m watching closely how this affects long-term alignment and productivity.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Writing good documentation is as critical as writing good code.&lt;/li&gt;
&lt;li&gt;Questioning architecture is not just tolerated, it’s actively encouraged.&lt;/li&gt;
&lt;li&gt;Onboarding doesn’t need to be paternalistic to be effective.&lt;/li&gt;
&lt;li&gt;Organizational performance is deeply tied to clear written communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My First 2 Days: Building a Centralized Onboarding Flow
&lt;/h2&gt;

&lt;p&gt;During my first two days, I noticed something that might sound paradoxical: &lt;em&gt;everything was documented, yet no one knew exactly how to navigate it&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;The documentation was thorough, covering internal APIs, deployment workflows, local setup, and architectural decisions. But each piece was isolated, like having a pile of puzzle pieces with no reference picture.  &lt;/p&gt;

&lt;p&gt;New engineers often found themselves constantly asking, &lt;em&gt;"In what order should I read these docs?"&lt;/em&gt; or &lt;em&gt;"What’s the first thing I should run locally before touching feature X?"&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;Instead of just consuming the scattered docs and pinging people repeatedly, I decided to start drafting a &lt;strong&gt;centralized onboarding flow&lt;/strong&gt;. The goal was to connect all these pieces into a clear sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What to clone first.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Which scripts to run and in which order.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What services need to be up before running the app.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Where to look for environment configuration and secrets.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key architectural diagrams to understand before jumping into PRs.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This initiative not only helped me get up to speed faster but also turned into a reusable asset for future newcomers.  &lt;/p&gt;

&lt;p&gt;It challenged the assumption that "more docs = better onboarding." In reality, &lt;em&gt;structured narrative beats raw volume every time&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;By proactively organizing this flow, I ended up learning the system more deeply and reduced the dependency on constant Slack or chat questions. And perhaps more importantly, I started contributing real value on day two instead of just passively absorbing information.&lt;/p&gt;




&lt;h2&gt;
  
  
  Special Thanks to the Woovi Engineering Team
&lt;/h2&gt;

&lt;p&gt;One thing that stood out immediately and deserves a special mention is the quality of the people here. It genuinely feels like every developer was handpicked, and after experiencing it firsthand, I now understand why the selection process is so demanding and sometimes lengthy.&lt;/p&gt;

&lt;p&gt;Everyone I've interacted with acted with an impressive sense of honor and strength, always pushing to help each other, no matter how busy they were. They deeply remember what it felt like to be new in the company, and they step up to assist with patience, without sarcasm or condescension.&lt;/p&gt;

&lt;p&gt;I won’t mention names, but to all of you who joined calls with me during this first week, consider this a public tribute. You turned what could have been a chaotic start into an empowering, fast-learning experience.&lt;/p&gt;

&lt;p&gt;This reinforced for me that a strong engineering culture isn't just about code quality or architecture; it's built on people who genuinely want each other to succeed.&lt;/p&gt;




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

&lt;p&gt;My first week at Woovi was less about a “cute onboarding” and more about a pragmatic deep dive. I realized that in a team focused on speed and autonomy, the worst mistake is waiting passively for instructions.&lt;/p&gt;

&lt;p&gt;If you’re about to join a fast-moving team, here’s a provocation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are you ready to swim without a float? Or are you still sitting on the edge, waiting for the manual?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;p&gt;Have you gone through an ultra-fast or hyper-structured onboarding before? What worked best for you? Share your thoughts in the comments.&lt;/p&gt;

</description>
      <category>career</category>
      <category>onboarding</category>
      <category>workplace</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>How MDX can accelerates document creation in websites</title>
      <dc:creator>Hállex da Silva Costa</dc:creator>
      <pubDate>Mon, 05 May 2025 14:39:54 +0000</pubDate>
      <link>https://dev.to/woovi/how-mdx-can-accelerates-document-creation-in-websites-2lm3</link>
      <guid>https://dev.to/woovi/how-mdx-can-accelerates-document-creation-in-websites-2lm3</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;See how MDX solves the problem of writing extremely long pages or articles.&lt;/p&gt;

&lt;p&gt;In this article, we will show you how MDX can be a powerful solution to speed up the documentation creation process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever seen a very common problem in many companies, such as outdated documents? Well, in a world where maintaining documents such as policies and privacy, terms and security is crucial.&lt;/p&gt;

&lt;p&gt;At the same time, having to deal with the fact that you will have to spend precious time writing &lt;strong&gt;N&lt;/strong&gt; pages that have already been written in a document like Word or PDF to an HTML, JSX or TSX page does not seem very pleasant or very smart.&lt;/p&gt;

&lt;p&gt;Finding efficient ways to create and maintain documents becomes essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Articles/Documentation
&lt;/h2&gt;

&lt;p&gt;One of the biggest challenges in creating documentation is the time spent retyping content. Often, we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewrite texts that already exist in other formats&lt;/li&gt;
&lt;li&gt;Maintain consistency between different versions of the same document&lt;/li&gt;
&lt;li&gt;Update multiple formats when changes occur&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process not only consumes time but also increases the chance of errors and inconsistencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: MDX
&lt;/h2&gt;

&lt;p&gt;MDX (Markdown + JSX) emerges as an elegant solution to these problems. It combines the simplicity of Markdown with the power of JSX, allowing the creation of interactive and dynamic documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy Conversion from DOCX to MD/MDX
&lt;/h3&gt;

&lt;p&gt;One of the biggest advantages of using MDX is the ease with which you can convert an existing document from docx to markdown and from markdown to MDX&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Follow This Approach?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Productivity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Less time spent on formatting&lt;/li&gt;
&lt;li&gt;Component reuse&lt;/li&gt;
&lt;li&gt;Faster updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Maintenance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Code and documentation together&lt;/li&gt;
&lt;li&gt;Simpler versioning&lt;/li&gt;
&lt;li&gt;Less content duplication&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Interactivity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Interactive components&lt;/li&gt;
&lt;li&gt;Executable code examples&lt;/li&gt;
&lt;li&gt;Better reader experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Flexibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy integration with modern tools&lt;/li&gt;
&lt;li&gt;Support for different output formats&lt;/li&gt;
&lt;li&gt;Compatibility with popular documentation systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Here's an example of a &lt;code&gt;DocumentPage.tsx&lt;/code&gt; created using the tsx syntax for another page using the &lt;code&gt;DocumentPage.mdx&lt;/code&gt; syntax&lt;/p&gt;

&lt;h3&gt;
  
  
  DocumentPage.tsx
&lt;/h3&gt;



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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DocumentPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"document-page max-w-4xl mx-auto py-8 px-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-3xl font-bold mb-8 text-center"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Terms of Service and Privacy Policy&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;1. Introduction&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Welcome to our Terms of Service and Privacy Policy. 
          This document establishes the rules and guidelines for using our services.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          By accessing and using our platform, you agree to the terms set forth herein.
          We recommend reading this document carefully before proceeding.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;2. Definitions&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;For the purposes of this document, the following terms shall have the meanings below:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list-decimal pl-6 space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Platform:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Refers to the set of services and features provided
            through our website and applications.
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;User:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Any person who accesses or uses the Platform.
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Content:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Information, data, text, images, and other materials provided
            through the Platform.
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;3. Platform Usage&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;By using our Platform, you agree to:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list-disc pl-6 space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Provide accurate and up-to-date information&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Maintain the confidentiality of your account&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Not use the Platform for illegal purposes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Respect intellectual property rights&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;4. Privacy and Data Protection&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          Our privacy policy describes how we collect, use, and protect your personal information.
          For more details, please refer to our&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/privacy"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-blue-600 hover:underline"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            complete Privacy Policy
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-50 p-4 rounded-lg"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-lg font-semibold mb-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Collected Data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list-disc pl-6 space-y-1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Registration information&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Platform usage data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Device information&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cookies and similar technologies&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;5. Responsibilities&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Our responsibilities include:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"list-decimal pl-6 space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Maintaining the Platform available and functioning properly
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Protecting user data in accordance with data protection laws
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Providing technical support when needed
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-semibold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;6. Contact&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          For questions regarding these terms, please contact us via email at&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mailto:legal@company.com"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-blue-600 hover:underline"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            legal@company.com
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;or by phone at (555) 123-4567.
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-gray-600 mt-8 pt-4 border-t"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Last updated: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DocumentPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DocumentPage.mdx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Terms&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Privacy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Policy"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Terms&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;conditions&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;using&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;platform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;privacy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;policy"&lt;/span&gt;
&lt;span class="na"&gt;creationAt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2025-05-04"&lt;/span&gt;
&lt;span class="na"&gt;lastUpdated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2025-05-04"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

export const meta = {
  title: "Terms of Service and Privacy Policy",
  creationAt: "2025-05-04",
  lastUpdated: "2025-05-04"
};

&lt;span class="gh"&gt;# {meta.title}&lt;/span&gt;

{frontmatter.description}

&lt;span class="gu"&gt;## 1. Introduction&lt;/span&gt;

Welcome to our Terms of Service and Privacy Policy. 
This document establishes the rules and guidelines for using our services.

By accessing and using our platform, you agree to the terms set forth herein.
We recommend reading this document carefully before proceeding.

&lt;span class="gu"&gt;## 2. Definitions&lt;/span&gt;

For the purposes of this document, the following terms shall have the meanings below:
&lt;span class="p"&gt;
1.&lt;/span&gt; &lt;span class="gs"&gt;**Platform:**&lt;/span&gt; Refers to the set of services and features provided
   through our website and applications.
&lt;span class="p"&gt;
2.&lt;/span&gt; &lt;span class="gs"&gt;**User:**&lt;/span&gt; Any person who accesses or uses the Platform.
&lt;span class="p"&gt;
3.&lt;/span&gt; &lt;span class="gs"&gt;**Content:**&lt;/span&gt; Information, data, text, images, and other materials provided
   through the Platform.

&lt;span class="gu"&gt;## 3. Platform Usage&lt;/span&gt;

By using our Platform, you agree to:
&lt;span class="p"&gt;
*&lt;/span&gt; Provide accurate and up-to-date information
&lt;span class="p"&gt;*&lt;/span&gt; Maintain the confidentiality of your account
&lt;span class="p"&gt;*&lt;/span&gt; Not use the Platform for illegal purposes
&lt;span class="p"&gt;*&lt;/span&gt; Respect intellectual property rights

&lt;span class="gu"&gt;## 4. Privacy and Data Protection&lt;/span&gt;

Our privacy policy describes how we collect, use, and protect your personal information.
For more details, please refer to our &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;complete Privacy Policy&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/privacy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;.

&lt;span class="nt"&gt;&amp;lt;InfoBox&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"info"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ### Collected Data
&lt;span class="p"&gt;
  *&lt;/span&gt; Registration information
&lt;span class="p"&gt;  *&lt;/span&gt; Platform usage data
&lt;span class="p"&gt;  *&lt;/span&gt; Device information
&lt;span class="p"&gt;  *&lt;/span&gt; Cookies and similar technologies
&lt;span class="nt"&gt;&amp;lt;/InfoBox&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## 5. Responsibilities&lt;/span&gt;

Our responsibilities include:
&lt;span class="p"&gt;
1.&lt;/span&gt; Maintaining the Platform available and functioning properly
&lt;span class="p"&gt;2.&lt;/span&gt; Protecting user data in accordance with data protection laws
&lt;span class="p"&gt;3.&lt;/span&gt; Providing technical support when needed

&lt;span class="gu"&gt;## 6. Contact&lt;/span&gt;

For questions regarding these terms, please contact us via email at &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;legal@company.com&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;mailto:legal@company.com&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
or by phone at (555) 123-4567.

&lt;span class="nt"&gt;&amp;lt;LegalNotice&amp;gt;&lt;/span&gt;
  This document was last updated on {meta.lastUpdated}.
  We recommend checking periodically for updates.
&lt;span class="nt"&gt;&amp;lt;/LegalNotice&amp;gt;&lt;/span&gt;

{/&lt;span class="ge"&gt;* Custom components for legal elements *&lt;/span&gt;/}
&lt;span class="nt"&gt;&amp;lt;LegalSection&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Final Provisions&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    These terms are governed by the laws of the United States and any dispute shall be
    submitted to the jurisdiction of the courts of New York, NY.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/LegalSection&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;TableOfContents&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Table of Contents&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ol&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#introduction"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Introduction&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#definitions"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Definitions&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#usage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Platform Usage&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#privacy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Privacy and Data Protection&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#responsibilities"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Responsibilities&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#contact"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/TableOfContents&amp;gt;&lt;/span&gt;
&lt;span class="gt"&gt;
&amp;gt; Documente created at {meta.creationAt}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This MDX example demonstrates how we can create complex legal documents in a more structured and interactive way. Notice how:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The frontmatter organizes the document metadata. Use it or export a new &lt;code&gt;meta&lt;/code&gt; variable to use in your markdown and communicate with external layer like the MDXProvider&lt;/li&gt;
&lt;li&gt;Markdown syntax keeps the content readable and well-formatted&lt;/li&gt;
&lt;li&gt;Custom components (&lt;code&gt;&amp;lt;InfoBox&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;LegalNotice&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;LegalSection&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;TableOfContents&amp;gt;&lt;/code&gt;) add specific functionality&lt;/li&gt;
&lt;li&gt;Custom styles for common elements as h1, h2, h3, h4, h5, p, a, li, ol, etc... Allows you to dynamically style markdown syntax elements such as &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;##&lt;/code&gt;, &lt;code&gt;###&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;JavaScript code can be embedded for dynamic features (like the update date)&lt;/li&gt;
&lt;li&gt;The document structure is clear and well-organized&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach makes it much easier to maintain and update extensive legal documents, while also significantly improving the end-user experience.&lt;/p&gt;

&lt;p&gt;You can visit a repository with a simple example comparing TSX and MDX &lt;a href="https://github.com/HallexCosta/example-tsx-mdx" rel="noopener noreferrer"&gt;here&lt;/a&gt; and visit &lt;a href="https://mdxjs.com/playground/" rel="noopener noreferrer"&gt;here&lt;/a&gt; to play a little with mdx playground&lt;/p&gt;

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

&lt;p&gt;MDX is an excellent tool for saving time, maintaining code consistency, and improving efficiency. By combining the simplicity of Markdown with the power of JSX, it offers a robust solution to modern documentation challenges.&lt;/p&gt;

&lt;p&gt;The approach of converting existing documents to MDX not only speeds up the creation process but also improves the quality and maintainability of documentation. In a world where documentation is crucial, MDX presents itself as an essential tool for teams seeking efficiency, quality and save time.&lt;/p&gt;

</description>
      <category>mdx</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Prometheus + Redis: Simple Guide to Monitor Redis Instances</title>
      <dc:creator>Lucas Aguiar</dc:creator>
      <pubDate>Mon, 21 Apr 2025 22:26:33 +0000</pubDate>
      <link>https://dev.to/woovi/prometheus-redis-simple-guide-to-monitor-redis-instances-n1f</link>
      <guid>https://dev.to/woovi/prometheus-redis-simple-guide-to-monitor-redis-instances-n1f</guid>
      <description>&lt;p&gt;Redis is often a critical part of modern infrastructure — whether used as a cache, message broker, or ephemeral store. Monitoring it properly helps you detect issues early and ensure system stability.&lt;/p&gt;

&lt;p&gt;In this guide, you’ll learn how to build a Redis monitoring dashboard with Prometheus and Grafana to quickly identify issues and improve system reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Installing Prometheus (Quick Setup)
&lt;/h2&gt;

&lt;p&gt;We’ll start by deploying Prometheus using Helm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install kube-prometheus prometheus-community/kube-prometheus-stack \
  --namespace prometheus --create-namespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This will install Prometheus, Grafana, and some built-in exporters.&lt;br&gt;
To access Grafana:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward svc/kube-prometheus-grafana -n prometheus 3000:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access here -&amp;gt; &lt;a href="http://localhost:3000/login" rel="noopener noreferrer"&gt;http://localhost:3000/login&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Default login: admin / prom-operator&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🧱 Installing Redis
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

helm install redis bitnami/redis \
  --namespace app-stg \
  --set architecture=standalone \
  --set auth.enabled=false \
  --create-namespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This installs a standalone Redis with no password, perfect for testing.&lt;br&gt;
After this, you can point the Redis Exporter and your application to the correct Redis service. The hostname will be:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redis-master.app-stg.svc.cluster.local:6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📦 Installing Redis Exporter
&lt;/h2&gt;

&lt;p&gt;Now let’s deploy the Redis Exporter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install redis-exporter prometheus-community/prometheus-redis-exporter \
  --namespace prometheus \
  --set serviceMonitor.enabled=true \
  --set serviceMonitor.namespace=prometheus \
  --set serviceMonitor.interval=15s \
  --set serviceMonitor.labels.release=kube-prometheus \
  --set redisAddress=redis://redis-master.app-stg.svc.cluster.local:6379 \
  --create-namespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Redis Exporter exposes metrics at a Prometheus-compatible /metrics endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward svc/redis-exporter-prometheus-redis-exporter -n prometheus 9121:9121
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open: &lt;a href="http://localhost:9121/metrics" rel="noopener noreferrer"&gt;http://localhost:9121/metrics&lt;/a&gt;&lt;br&gt;
You should see a long list of metrics like this:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;✅ redis_up 1 means the exporter is connected to a Redis instance and it’s healthy.&lt;br&gt;
🚫 redis_up 0 means the exporter failed to connect — check the Redis address or service availability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If everything is working, you’ll also see metrics like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;redis_connected_clients&lt;/li&gt;
&lt;li&gt;redis_memory_used_bytes&lt;/li&gt;
&lt;li&gt;redis_total_commands_processed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🔍 Checking in Prometheus
&lt;/h2&gt;

&lt;p&gt;To validate that Prometheus is collecting Redis metrics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward svc/kube-prometheus-kube-prome-prometheus -n prometheus 9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:9090" rel="noopener noreferrer"&gt;http://localhost:9090&lt;/a&gt;, go to &lt;a href="http://localhost:9090/targets" rel="noopener noreferrer"&gt;Status &amp;gt; Targets&lt;/a&gt;, and check that Redis Exporter is listed and UP.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7s4xgevvwa2crwfv43b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7s4xgevvwa2crwfv43b.png" alt="Prometheus target debuging" width="799" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything is working right!&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Importing the Redis Dashboard on Grafana
&lt;/h2&gt;

&lt;p&gt;To visualize your Redis metrics in a clean and ready-to-use panel, you can import a community-maintained dashboard from Grafana Labs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://grafana.com/grafana/dashboards/14091-redis-dashboard-for-prometheus-redis-exporter-1-x/" rel="noopener noreferrer"&gt;https://grafana.com/grafana/dashboards/14091-redis-dashboard-for-prometheus-redis-exporter-1-x/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧭 How to Import
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Access Grafana by establishing port forwarding and navigating to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in your browser&lt;/li&gt;
&lt;li&gt;Navigate to the "+" icon in the left sidebar and select "Import"&lt;/li&gt;
&lt;li&gt;Enter the dashboard ID or URL in the provided field and click "Load"&lt;/li&gt;
&lt;li&gt;Click "Import" to finalize the installation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Allow a few moments for the system to process your request as the metrics populate on your dashboard&lt;/p&gt;

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

&lt;p&gt;Thats it!&lt;br&gt;
⎈Happy Helming!⎈&lt;/p&gt;

</description>
      <category>redis</category>
      <category>prometheus</category>
      <category>grafana</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Resilient Node.js servers without using docker</title>
      <dc:creator>Hállex da Silva Costa</dc:creator>
      <pubDate>Tue, 04 Mar 2025 01:55:09 +0000</pubDate>
      <link>https://dev.to/woovi/resilient-nodejs-servers-without-using-docker-43kb</link>
      <guid>https://dev.to/woovi/resilient-nodejs-servers-without-using-docker-43kb</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Now you will learn how we create resilient services without interrupting the main SSH connection or without the need to create N SSH connections with N open terminals while developing our services in our remote development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Requirements&lt;/li&gt;
&lt;li&gt;What is PM2?&lt;/li&gt;
&lt;li&gt;Installing PM2&lt;/li&gt;
&lt;li&gt;Persisting Processes&lt;/li&gt;
&lt;li&gt;Check Processes&lt;/li&gt;
&lt;li&gt;In Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is PM2?
&lt;/h2&gt;

&lt;p&gt;PM2 is a daemon process manager that will help you manage and keep your application online 24/7&lt;/p&gt;

&lt;p&gt;The services running through it become resilient. A similar analogy is comparing PM2 with NGINX&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing PM2
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Persisting Processes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Explanation: pm2 start &amp;lt;package-manager&amp;gt; --name &amp;lt;app-name&amp;gt; -- &amp;lt;script-name&amp;gt;&lt;/span&gt;
pm2 start pnpm &lt;span class="nt"&gt;--name&lt;/span&gt; woovi-front &lt;span class="nt"&gt;--&lt;/span&gt; woovi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your server is launched in daemon mode, meaning it runs as a detached background process. &lt;/p&gt;

&lt;p&gt;Under the hood, PM2 spawns a new process for your service that is independent of the initial terminal session. &lt;/p&gt;

&lt;p&gt;This decoupling ensures that the server continues to run even if you close the terminal, while PM2 monitors, logs, and automatically restarts the process if it encounters any issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Processes
&lt;/h2&gt;



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

&lt;/div&gt;



&lt;p&gt;You can view the daemon processes that PM2 spawns for your services, and check the following information&lt;/p&gt;

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

&lt;p&gt;If the status is "online", your service already be up, then you can test using the command curl&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I already know that my service may be running on port 3000, you must change the port to your application's port&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# use this for test in your VPS&lt;/span&gt;
curl http://localhost:3000

&lt;span class="c"&gt;# or this, if want to test in the machine host&lt;/span&gt;
curl http://yourmachineip:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PM2 is powerful when it comes to process management it has many other commands like &lt;code&gt;pm2 delete&lt;/code&gt; to delete an unused daemon process, &lt;code&gt;pm2 restart&lt;/code&gt; to restart a process, and &lt;code&gt;pm2 stop&lt;/code&gt; to end a process execution&lt;/p&gt;

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

&lt;p&gt;Integrating PM2 into remote development environments is an effective strategy to ensure that your services or applications remain running continuously and stably so that you can move freely without worrying about tying up the main process of your SSH connection and ending up interrupting the service at some point.&lt;/p&gt;

</description>
      <category>node</category>
      <category>docker</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
