<?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: Henrique Marques Fernandes</title>
    <description>The latest articles on DEV Community by Henrique Marques Fernandes (@shadowlik).</description>
    <link>https://dev.to/shadowlik</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F151755%2F1146072d-b147-4025-b89d-9fc9cdf8223b.png</url>
      <title>DEV Community: Henrique Marques Fernandes</title>
      <link>https://dev.to/shadowlik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shadowlik"/>
    <language>en</language>
    <item>
      <title>1. How I Stopped Building Random Features and Found a Product Direction</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Wed, 22 Jul 2026 00:25:49 +0000</pubDate>
      <link>https://dev.to/shadowlik/1-how-i-stopped-building-random-features-and-found-a-product-direction-3c2h</link>
      <guid>https://dev.to/shadowlik/1-how-i-stopped-building-random-features-and-found-a-product-direction-3c2h</guid>
      <description>&lt;p&gt;&lt;em&gt;This is part two of my &lt;a href="https://haid.app/" rel="noopener noreferrer"&gt;Growing HAID in Public&lt;/a&gt; series. In &lt;a href="https://marquesfernandes.com/en/why-im-growing-haid-in-public-not-building-in-public/" rel="noopener noreferrer"&gt;part one&lt;/a&gt;, I wrote about building a fitness app, failing at distribution, and realizing that my product still lacked a clear reason to exist. This is what happened next: turning a pile of ideas into an actual roadmap.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem after the problem
&lt;/h2&gt;

&lt;p&gt;I had finally figured out what HAID should be.&lt;/p&gt;

&lt;p&gt;Not just another fitness data aggregator, but a system that uses the context of your life to help you understand &lt;em&gt;how you are actually doing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Great. Clear direction. Finally.&lt;/p&gt;

&lt;p&gt;Now what?&lt;/p&gt;

&lt;p&gt;I had a Notion workspace that would make Sheldon from &lt;em&gt;The Big Bang Theory&lt;/em&gt; proud. Tasks everywhere, feature ideas piling up, integrations I wanted to build, and interface redesigns I had been sketching.&lt;/p&gt;

&lt;p&gt;Everything was organized in the sense that it was written down. It was not organized in the sense that mattered: I had no idea what to build &lt;em&gt;first&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I have owned features and contributed to roadmaps at every company I have worked for. I have sat in prioritization meetings, talked to product managers, and debated scope.&lt;/p&gt;

&lt;p&gt;But I had never been the person responsible for building everything from scratch. The person who decides not only what goes in, but also what stays out and in what order.&lt;/p&gt;

&lt;p&gt;That was a different kind of problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I thought product thinking was
&lt;/h2&gt;

&lt;p&gt;As an engineer, I used to think product thinking looked something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  List the features.&lt;/li&gt;
&lt;li&gt;  Estimate the effort.&lt;/li&gt;
&lt;li&gt;  Sort everything by impact and effort.&lt;/li&gt;
&lt;li&gt;  Start with high-impact, low-effort work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not exactly wrong. But it is incomplete.&lt;/p&gt;

&lt;p&gt;It is the spreadsheet version of product thinking. It skips the harder questions.&lt;/p&gt;

&lt;p&gt;What is the first version of this product that can make someone care? Not the version with every feature, but the one that delivers the core promise well enough for a stranger to keep using it.&lt;/p&gt;

&lt;p&gt;That question changed the way I looked at everything.&lt;/p&gt;

&lt;p&gt;And, honestly, an MVP is rarely truly minimal anymore, especially when you enter a category full of large, established companies. Users will compare your product with the incumbents immediately. There is no way around it.&lt;/p&gt;

&lt;p&gt;You need enough familiar functionality to feel like a serious alternative from day one. At the same time, you need to give people a clear reason to switch from what they already use.&lt;/p&gt;

&lt;p&gt;That was the real shock for me: HAID could not feel like one more app layered on top of Garmin, Strava, Apple Health, and everything else. It needed to start replacing at least one of them while pointing toward a larger vision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining what HAID actually is on paper
&lt;/h2&gt;

&lt;p&gt;I forced myself to write.&lt;/p&gt;

&lt;p&gt;No code, Figma, or tasks. Just words.&lt;/p&gt;

&lt;p&gt;What problem does HAID solve? Who is it for? Why do existing apps fail to solve that problem? What would make someone leave their current setup?&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%2Fozapgnrk6pwl5kl38xm6.webp" 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%2Fozapgnrk6pwl5kl38xm6.webp" alt="HAID product document in Notion explaining that fitness data needs to account for stress, travel, injuries, and other life context" width="800" height="1450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The document I used to turn the idea behind HAID into a product direction.&lt;/p&gt;

&lt;p&gt;Putting everything on paper gave me more clarity than I expected. Ideas that seemed obvious in my head became questionable once I wrote them down. Things I had been avoiding became clearly important.&lt;/p&gt;

&lt;p&gt;And some features I was excited to build revealed themselves for what they were: nice ideas that had no place in the first version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing what goes into the MVP
&lt;/h2&gt;

&lt;p&gt;This is where it became difficult. My definition of an MVP had to change.&lt;/p&gt;

&lt;p&gt;At first, “MVP” meant the smallest thing I could release. Basic data ingestion, a simple dashboard, and perhaps one social feature.&lt;/p&gt;

&lt;p&gt;The classic developer instinct: ship something quickly and iterate.&lt;/p&gt;

&lt;p&gt;But after the Reddit experience, someone asked, “Why would I download this?” and I did not have a good answer. I realized that an MVP that was too minimal would simply repeat the same problem.&lt;/p&gt;

&lt;p&gt;If the first version does not deliver the core promise, it does not matter how quickly you release it. You will receive the same feedback again.&lt;/p&gt;

&lt;p&gt;My new definition became: the minimum version capable of answering &lt;em&gt;“How am I doing?”&lt;/em&gt; with enough depth to deliver real value.&lt;/p&gt;

&lt;p&gt;That completely changed the order of the roadmap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Life context moved to the top
&lt;/h3&gt;

&lt;p&gt;The context feature was already in the backlog. The problem was that it was buried in the fourth quarter, behind several things I wanted to build because they looked more exciting and easier.&lt;/p&gt;

&lt;p&gt;It needed to become the priority.&lt;/p&gt;

&lt;p&gt;Travel, stress, injuries, and recovery could not be a distant add-on. They were precisely what separated HAID from another dashboard full of training charts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The experience needed to adapt to the person
&lt;/h3&gt;

&lt;p&gt;I hate opening an app and seeing empty spaces every day for data I will never produce.&lt;/p&gt;

&lt;p&gt;That meant defining personas and designing an adaptable experience. A casual user and a professional athlete should not see exactly the same thing or feel judged or overwhelmed by the app.&lt;/p&gt;

&lt;p&gt;Their experiences can be different, but they need to share the same core principle: use data and context to help each person understand how they are doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some ideas had to go
&lt;/h3&gt;

&lt;p&gt;I also cut things I wanted to build simply because they would be fun.&lt;/p&gt;

&lt;p&gt;Achievements and route segments, for example. They are enjoyable features, but do they create a meaningful difference? Would an AI bot actually help, or would it make people reject the product before trying it?&lt;/p&gt;

&lt;p&gt;“Not now” is a frustrating answer when you know you can build something. But it became a necessary part of the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I organized the work
&lt;/h2&gt;

&lt;p&gt;I am not going to pretend I discovered a brilliant framework. I did not.&lt;/p&gt;

&lt;p&gt;This is what I actually did.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everything lives in Notion
&lt;/h3&gt;

&lt;p&gt;I have a product backlog, a screen inventory, and PRDs for the main features. Every screen in the app has a corresponding Notion page with requirements, edge cases, and design decisions.&lt;/p&gt;

&lt;p&gt;It is probably too much engineering for a one-person project. But it keeps my head in order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prioritization is simple
&lt;/h3&gt;

&lt;p&gt;For every feature or task, I ask: does this move me closer to a version of HAID that answers “How am I doing?” in a way someone genuinely values?&lt;/p&gt;

&lt;p&gt;If the answer is yes, it enters the roadmap. If it is interesting but tangential, it goes onto the “later” list.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time is also part of the product
&lt;/h3&gt;

&lt;p&gt;This was the hardest shift.&lt;/p&gt;

&lt;p&gt;I am a solo developer with a full-time job. HAID is a side project. I cannot simply enter an endless sprint.&lt;/p&gt;

&lt;p&gt;I had to accept that things take time and that I cannot rush the product just because I am excited. Setting realistic timelines, and not tearing myself apart when I miss them, was a skill I had to develop.&lt;/p&gt;

&lt;p&gt;Life context was one of those cases.&lt;/p&gt;

&lt;p&gt;The idea sounded simple, but it hid several decisions. How do you record a trip without turning it into an annoying form? How do you represent periods of travel, stress, injury, or recovery in a structured way? And how do you carry that context through the rest of the app instead of trapping it on one screen?&lt;/p&gt;

&lt;p&gt;I estimated two weeks.&lt;/p&gt;

&lt;p&gt;I was very wrong.&lt;/p&gt;

&lt;p&gt;The first version felt clumsy. Once I started testing it, both the input flow and the way context appeared throughout the app felt wrong. The result was not what I had imagined.&lt;/p&gt;

&lt;p&gt;So I tore it down and started again.&lt;/p&gt;

&lt;p&gt;It took five weeks to reach something that made me think: yes, this works.&lt;/p&gt;

&lt;p&gt;I had also overcomplicated the first interaction. My original idea was a chatbot-style field where someone could send a message and the app would infer the context from natural language.&lt;/p&gt;

&lt;p&gt;I still like the idea. I still want to build it. Just not now.&lt;/p&gt;

&lt;p&gt;To validate the flow, a simple form, a few emojis, and a date picker were more than enough. &lt;a href="https://en.wikipedia.org/wiki/KISS_principle" rel="noopener noreferrer"&gt;KISS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What “minimum” actually means
&lt;/h2&gt;

&lt;p&gt;The definition that stayed&lt;/p&gt;

&lt;p&gt;Minimum does not mean small. It means &lt;strong&gt;focused&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My MVP is not a weekend project. It represents months of work. But every part serves the same goal: provide enough context around fitness data to make someone return the next day.&lt;/p&gt;

&lt;p&gt;That is the bar.&lt;/p&gt;

&lt;p&gt;Not “How many features does it have?” but “Does this make someone open the app again?”&lt;/p&gt;

&lt;p&gt;In the first draft of this article, I estimated that I was about a month away from that version. After missing a two-week estimate by a considerable margin, I would rather not turn another estimate into a promise.&lt;/p&gt;

&lt;p&gt;Once it is ready, the focus shifts to bugs, experience refinements, and then the big unknown: getting people to try it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned about product as a developer
&lt;/h2&gt;

&lt;p&gt;If I had to summarize what I have learned so far, it would be this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functionality is not value
&lt;/h3&gt;

&lt;p&gt;I could build every feature perfectly and still end up with a product nobody wants.&lt;/p&gt;

&lt;p&gt;The “what” matters less than “Why should I care?”&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing forces clarity
&lt;/h3&gt;

&lt;p&gt;Whenever I felt confused about the direction, putting things into words instead of code helped me see what I was actually trying to do.&lt;/p&gt;

&lt;p&gt;PRDs are not bureaucracy when you are building alone. They are thinking tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cutting is harder than building
&lt;/h3&gt;

&lt;p&gt;Saying “not yet” to a feature that excites me is genuinely painful. But a focused product beats a product stuffed with features, especially when you do not have enough users to tell you what truly matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product thinking is a skill
&lt;/h3&gt;

&lt;p&gt;I was not born knowing how to prioritize or define scope. I am learning it the same way I learned engineering: by doing, making mistakes, and adjusting.&lt;/p&gt;

&lt;p&gt;It is uncomfortable, but it can be learned.&lt;/p&gt;

&lt;p&gt;Being able to build quickly can even become a trap. When you are an engineer who enjoys building, it is very easy to confuse “This would be fun to build” with “This would make a difference.”&lt;/p&gt;

&lt;p&gt;For me, a large part of product thinking has been learning to distrust that instinct a little and ask a harder question: does this solve a real problem, or does it merely satisfy my own taste?&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next
&lt;/h2&gt;

&lt;p&gt;First, finish the MVP. Then comes the part I am least prepared for: growth.&lt;/p&gt;

&lt;p&gt;The goal I set was to reach 500 users, but the number alone does not answer the harder question: how do the right people discover the product and find enough value to keep using it?&lt;/p&gt;

&lt;p&gt;The next article will be about that attempt: how a developer with no marketing experience tries to earn attention in a market flooded with apps that promise to solve everything with AI.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to follow what I am building: &lt;a href="https://haid.app/" rel="noopener noreferrer"&gt;haid.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI Will Take My Job, but First I Need to Review Its PR</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Wed, 22 Jul 2026 00:25:14 +0000</pubDate>
      <link>https://dev.to/shadowlik/ai-will-take-my-job-but-first-i-need-to-review-its-pr-4fdn</link>
      <guid>https://dev.to/shadowlik/ai-will-take-my-job-but-first-i-need-to-review-its-pr-4fdn</guid>
      <description>&lt;p&gt;At the beginning of the year, I was certain artificial intelligence was going to end the world.&lt;/p&gt;

&lt;p&gt;Not in the metaphorical “this tool will change the market” sense. In my head, the whole script was already written: AI would take every job, money would become meaningless, humans would become obsolete, and we engineers would be the first to go. The ironic twist would be getting replaced by the very systems we helped build and maintain.&lt;/p&gt;

&lt;p&gt;I am not usually drawn to paranoia or conspiracy theories. The problem is that I have a vivid imagination, and every now and then it decides to drive without a license.&lt;/p&gt;

&lt;p&gt;When I wrote about &lt;a href="https://marquesfernandes.com/en/development/why-im-growing-haid-in-public-not-building-in-public/" rel="noopener noreferrer"&gt;why I am growing HAID in public&lt;/a&gt;, I mentioned that AI scared the hell out of me and that I feared what it would do to my job. This is the post I promised back then.&lt;/p&gt;

&lt;p&gt;Or at least my view today. A new model could launch tomorrow and I might come back here pretending I never said any of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The panic faded. The amount of stuff to learn did not
&lt;/h2&gt;

&lt;p&gt;After a while, the dust settled. At least a little.&lt;/p&gt;

&lt;p&gt;Developers already work in one of the most dynamic markets around. Every week brings a framework, language, library, or tool that, according to someone on X, makes everything you learned before yesterday completely useless.&lt;/p&gt;

&lt;p&gt;We are used to studying. It is part of the job.&lt;/p&gt;

&lt;p&gt;AI did not simplify that treadmill, though. It placed another treadmill on top of it. Now we need to understand how to work with agents, provide context, organize tasks, compare models, learn what each one is good at, and decide which one to use. By the time you finish comparing them, another has probably launched.&lt;/p&gt;

&lt;p&gt;It was supposed to make things easier. Somehow, it made them easier and harder at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  My first strategy was to assume I was special
&lt;/h2&gt;

&lt;p&gt;I kept using AI heavily and started noticing that some engineers around me had barely tried these tools.&lt;/p&gt;

&lt;p&gt;My reaction was deeply human and not especially noble: “Okay, maybe I still have a job.”&lt;/p&gt;

&lt;p&gt;I consider myself a good engineer. I study, I try to keep up, and I was already using AI extensively. For a while, I imagined that advantage would protect me. If someone had to be cut, it would be the others, not me.&lt;/p&gt;

&lt;p&gt;It is a comforting line of thought. It also has an expiration date.&lt;/p&gt;

&lt;p&gt;Knowing how to use the tool may create an advantage today, but the tool keeps getting easier to use. The differentiator cannot simply be talking to it better than the person at the next desk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Product and engineering are starting to become the same job
&lt;/h2&gt;

&lt;p&gt;Then I began noticing another shift: the boundary between product and engineering was getting less clear.&lt;/p&gt;

&lt;p&gt;That part excited me. I love product. I have built plenty of side projects, attempted startups, and more recently had to &lt;a href="https://marquesfernandes.com/en/1-how-i-stopped-building-random-features-and-found-a-product-direction/" rel="noopener noreferrer"&gt;stop piling random features into HAID and find an actual direction&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If writing code has become cheaper and faster, choosing &lt;strong&gt;what&lt;/strong&gt; to build matters even more. Understanding the problem, talking to people, setting priorities, seeing tradeoffs, and making architecture decisions increasingly belong in the same package.&lt;/p&gt;

&lt;p&gt;Maybe the engineer will not disappear tomorrow. Maybe the role will become an even stranger mix of engineer, product manager, architect, researcher, and robot babysitter.&lt;/p&gt;

&lt;p&gt;I can picture myself in that role. The uncomfortable question is: how long will it remain a human role?&lt;/p&gt;

&lt;h2&gt;
  
  
  What if programming languages are just a phase?
&lt;/h2&gt;

&lt;p&gt;I have a slightly wild idea, and it is not exactly a future I am rooting for: if we keep programming with AI, high-level languages may stop being necessary for a large part of the work.&lt;/p&gt;

&lt;p&gt;I am not saying that understanding code has become less important. I think the opposite is true. Reading code, spotting bad abstractions, anticipating problems, and validating behavior matter more than ever. What may matter less is manually writing every line.&lt;/p&gt;

&lt;p&gt;Today, we use languages designed so humans can express instructions and machines can execute them. But vibe coders and even experienced developers are already submitting PRs without looking at their own code. If that behavior continues, it feels inevitable that someone will ask: why keep a representation designed for humans who are no longer reading it?&lt;/p&gt;

&lt;p&gt;I do not want that to happen. I want us to keep understanding what we put into production. I can simply imagine a future where machines create most code and, as a consequence, representations optimized for them emerge while we move further away from the implementation.&lt;/p&gt;

&lt;p&gt;That future still feels far away. To trust that level of abstraction, we need much better tools, environments, tests, observability, and verification mechanisms.&lt;/p&gt;

&lt;p&gt;Until then, please review your PR. Run the project locally. Check that the application at least starts before asking someone else to review it. And if you do not understand the code you are submitting, ask for help.&lt;/p&gt;

&lt;p&gt;We are all learning, but production does not need to learn alongside us.&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%2Fowkp9pff49jt63lxrtw7.webp" 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%2Fowkp9pff49jt63lxrtw7.webp" alt="An engineer in a control room reviews the work while a small robot assembles a system of connected blocks" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The work may move from the keyboard to the control room. The responsibility stays on our side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers still need to add up
&lt;/h2&gt;

&lt;p&gt;There is another huge uncertainty in this story: how much all of this really costs and who ultimately pays the bill.&lt;/p&gt;

&lt;p&gt;We still do not know whether there is a bubble, when it might burst, or how the price of these tools will reach end users. If capital becomes more expensive and services stop absorbing part of the cost, access may become more limited. Adoption could slow down, and a technology sold as democratizing could widen the gap between those who can afford it and those who cannot.&lt;/p&gt;

&lt;p&gt;The opposite could happen. Models may become smaller, more efficient, and cheaper. Infrastructure may improve. Competition may drive prices down.&lt;/p&gt;

&lt;p&gt;I do not know which path wins. Anyone who claims they do probably also has a newsletter to sell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  People starting out may pay most of the bill
&lt;/h2&gt;

&lt;p&gt;This is where my concern moves beyond my own job to the people still trying to enter the field.&lt;/p&gt;

&lt;p&gt;I have spent a long time working mainly with teams of senior engineers. I do not closely follow the current reality of junior positions, so I do not want to invent a picture of the market that I cannot actually see.&lt;/p&gt;

&lt;p&gt;But I can see the risk: if companies expect one person with AI to produce what once required a larger team, where does someone gain the experience needed to become senior?&lt;/p&gt;

&lt;p&gt;The easy answer is that beginners can use AI to learn. They can. But that view did not begin with AI. In April 2020, when I wrote my guide on &lt;a href="https://marquesfernandes.com/en/how-and-where-to-learn-to-program-javascript-courses-and-tutorials-free/" rel="noopener noreferrer"&gt;how to start learning JavaScript&lt;/a&gt;, I was already arguing that the best way to learn was to have a concrete project and get your hands dirty. AI may speed up the journey, but I still have not found a better way to learn than building something real.&lt;/p&gt;

&lt;p&gt;But even learning how to learn requires a foundation. Knowing how to formulate a question, doubt a convincing answer, tell a good explanation from a hallucination, and persist when nothing works are not skills distributed equally.&lt;/p&gt;

&lt;p&gt;If entering tech already depended on time, education, and access, adding a monthly subscription and another layer of knowledge may make that path even more unequal.&lt;/p&gt;

&lt;h2&gt;
  
  
  My temporary conclusion
&lt;/h2&gt;

&lt;p&gt;At the beginning of the year, I saw a race where AI was ahead and we were just trying to catch up.&lt;/p&gt;

&lt;p&gt;Today, I think running faster may be the wrong metric. For now, our value lies less in the speed at which we produce code and more in our ability to decide, connect context, review, take responsibility, and notice when the machine is solving the wrong problem extremely well.&lt;/p&gt;

&lt;p&gt;Product and engineering will probably keep moving closer together. People who can learn the other side may buy themselves some time. I do not know how much.&lt;/p&gt;

&lt;p&gt;I also do not know whether the bubble will burst, whether we will program in a language made for machines, or whether “software engineer” will become a title as old-fashioned as “webmaster.”&lt;/p&gt;

&lt;p&gt;I only know that continuing to learn still seems like a better strategy than pretending nothing is happening. Reviewing the PR before the apocalypse costs nothing, either.&lt;/p&gt;

&lt;p&gt;These are my two Brazilian cents on a subject nobody asked me about. I do not have an answer, only a slightly better-organized paranoia.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. Yes, this article was reviewed by an AI. It would have been rude not to invite the prime suspect.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>0. Why I’m Growing HAID in Public, Not Building in Public</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Sun, 05 Apr 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/shadowlik/0-why-im-growing-haid-in-public-not-building-in-public-1d0l</link>
      <guid>https://dev.to/shadowlik/0-why-im-growing-haid-in-public-not-building-in-public-1d0l</guid>
      <description>&lt;h2&gt;
  
  
  The Hook
&lt;/h2&gt;

&lt;p&gt;Everyone's doing build in public. Twitter (Sorry, X) threads about tech stacks, architecture decisions, deployment pipelines. I love reading those, but that's not what this is.&lt;/p&gt;

&lt;p&gt;I'm a software engineer with over 15 years of experience. I've shipped products used by thousands of users well before AI was part of anyone's vocabulary. Building is my comfort zone. I know how to do that. Yes, I know build in public is also about early feedback, not literally asking people to write your code. But bear with me.&lt;/p&gt;

&lt;p&gt;Growth? Marketing? Getting strangers on the internet to care about something I made? I have no idea how to do that. And that's exactly what this series is about: documenting the honest, messy process of a developer figuring out growth from scratch.&lt;/p&gt;

&lt;p&gt;This is also a return to writing for me. One of my first side projects was &lt;a href="http://marquesfernandes.com/" rel="noopener noreferrer"&gt;marquesfernandes.com&lt;/a&gt;, which nowadays is more of a portfolio than a blog. But back then, writing was good for me. It forced me to think more deeply, learn things properly, and gave me a mindfulness moment doing something I'm not particularly good at. After a couple of years without writing, it felt like time to get back to it.&lt;/p&gt;

&lt;p&gt;So here's the story so far: how &lt;a href="https://haid.app/" rel="noopener noreferrer"&gt;HAID&lt;/a&gt; went from a frustrated athlete's side project to something with a real direction, and why the hard part is only starting now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why HAID Exists
&lt;/h2&gt;

&lt;p&gt;I'm a runner and triathlete, and for years I've been frustrated by the same thing: there's no single place I can call home for my fitness data.&lt;/p&gt;

&lt;p&gt;Strava is great for the social side. Garmin Connect throws a wall of data at you, with a UI that's still rough despite recent redesign attempts. Apple Health is clean and gets a few things right, but misses the social and motivational layer that I think matters. Each app is great at one thing, none at everything, and none of them really talk to each other in a useful way.&lt;/p&gt;

&lt;p&gt;I'd already scratched a similar itch before: I built &lt;a href="https://apuama.com/" rel="noopener noreferrer"&gt;apuama.com&lt;/a&gt; because finding running and triathlon events in Brazil was unnecessarily hard. So I'm the kind of person who, when frustrated by a missing tool, just starts building it.&lt;/p&gt;

&lt;p&gt;And since I love a side project: let's do 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%2Fnjc81z38brrahz7sn1zf.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%2Fnjc81z38brrahz7sn1zf.png" alt="AFA89B37-6CF3-434C-8DD6-D8ECB7883C55_1_105_c.jpeg" width="602" height="1308"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Instinct: Just Build
&lt;/h2&gt;

&lt;p&gt;I started HAID using technology I knew. First POC, structuring the repo, getting data ingestion working from Apple Health and Garmin, it came together fast. That phase is pure dopamine for a developer. Ideas flowing, pieces clicking into place, the feeling that everything is possible.&lt;/p&gt;

&lt;p&gt;I needed a focus point, so I picked one: &lt;strong&gt;challenges&lt;/strong&gt;. Me and a bunch of friends were using Gymrats for group fitness challenges, and I thought I could build something better. It gave me direction and momentum, a concrete feature to rally around instead of drowning in a sea of "wouldn't it be cool if..."&lt;/p&gt;

&lt;p&gt;Good instinct. Wrong timing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Wrong Early Bet
&lt;/h2&gt;

&lt;p&gt;Challenges are a social feature. And social features need people.&lt;/p&gt;

&lt;p&gt;For them to be useful, you need users. But users won't come if no other users are there. Classic chicken-and-egg. Even if I convinced every single person in my network who exercises, that's maybe a few dozen people, and it's not enough for meaningful interaction or useful data.&lt;/p&gt;

&lt;p&gt;The challenges idea wasn't wrong forever. But it was wrong as the first lever, because it depended on solving distribution before the product had earned distribution. I didn't see that at the time.&lt;/p&gt;

&lt;p&gt;I just needed to get some people in there. How hard could it be?&lt;/p&gt;




&lt;h2&gt;
  
  
  Trying Everything I Could Think Of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  My Own Network
&lt;/h3&gt;

&lt;p&gt;Everyone tells you to start with your own network. So I did. I reached out to friends, colleagues, and training partners. Some joined and were genuinely helpful, testing features, reporting bugs, and giving honest feedback. I'm grateful for them.&lt;/p&gt;

&lt;p&gt;But the majority? Read the message, ignored it. Or replied, "yeah for sure, I'll check it out!" and never did.&lt;/p&gt;

&lt;p&gt;And that's okay. People are busy. My side project is not their priority. But I'd be lying if I said it didn't sting a little. It did.&lt;/p&gt;

&lt;p&gt;I had a couple of close friends, people I've helped in the past with their own stuff, who sent me, "Yeah dude, I'll download it for sure." Never did. That one stings differently than a stranger ignoring you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Influencer Outreach
&lt;/h3&gt;

&lt;p&gt;Next: founder-led outreach. I followed a bunch of smaller influencers in the running and endurance space. I sent personalized messages and offered Pro tier for life. Almost no replies and zero downloads.&lt;/p&gt;

&lt;p&gt;And I get it, social platforms nowadays make it hard for random people to reach creators, which is a feature, not a bug. If I were them, I wouldn't want strangers spamming me either. But it leaves you with a question: if not my network and not influencers, then how?&lt;/p&gt;

&lt;h3&gt;
  
  
  Reddit
&lt;/h3&gt;

&lt;p&gt;No budget for ads. No marketing knowledge. Where do people discover new products for free?&lt;/p&gt;

&lt;p&gt;Everyone talks about going viral on Reddit. I'd never really used it, but I figured it was worth a shot. I researched subreddits related to fitness tracking, running, and wearables. The goal was simple: share what I was building and ask for help testing.&lt;/p&gt;

&lt;p&gt;The few posts that weren't immediately banned got... interesting reactions.&lt;/p&gt;

&lt;p&gt;A lot of hate comments. People being harsh for no apparent reason, even when you come with the best intentions. But I get it, this was the internet I always knew existed… I'd just never been on the receiving end before. I'm a private person. I don't like overexposure. So this was new territory.&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%2Fw7p3z1imj7k79lopzz3c.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%2Fw7p3z1imj7k79lopzz3c.png" alt="Screenshot 2026-04-04 at 20.32.26.png" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got that a lot. And damn, it got under my skin. I've been building software professionally for over 15 years. I've shipped products used by thousands of people at real companies, long before GPT existed. And now, because it's 2026, everything a solo developer puts out gets dismissed as AI-generated garbage?&lt;/p&gt;

&lt;p&gt;Don't get me wrong, I use AI. I'm shit scared of it and what it's going to do to my job (but this is a topic for another post), but there's 15 years of caring, learning, understanding tradeoffs, scalability, and security research behind this. How dare user PinkToe1994 say otherwise? hahaha&lt;/p&gt;

&lt;p&gt;I think I handled it reasonably well in the end. I took a step back, understood the dynamics, realized people on the internet are often projecting their own frustrations, and moved on. A few users did actually download the app. It was fun seeing random strangers show up in my database. But the conversion rate versus the emotional cost? Not worth the attempt.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Painful Part Is That People Were Kind of Right
&lt;/h2&gt;

&lt;p&gt;Here's the thing though.&lt;/p&gt;

&lt;p&gt;Buried under all the noise, there was one useful signal. I got two pieces of feedback from Reddit and one from a close friend. All three said essentially the same thing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Why would I download this? What's different here?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And honestly? At that point, there was no good answer.&lt;/p&gt;

&lt;p&gt;My first iteration of HAID was basically Apple Health + Strava + Garmin mashed together. My only pitch was "everything in one place," and even I wasn't fully convinced that was enough.&lt;/p&gt;

&lt;p&gt;I had great plans for the app. I could see the future version in my head. And in my ego, I was thinking: &lt;em&gt;people need to just understand the vision! I just need users to test the data pipeline!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But why would they? Nobody owes me anything.&lt;/p&gt;

&lt;p&gt;It hit me because I probably wouldn't download it either. I scroll past app ads every day. Why should other people be different?&lt;/p&gt;

&lt;p&gt;I was not just missing users. I was missing a reason for users to care.&lt;/p&gt;

&lt;p&gt;That's the lesson.&lt;/p&gt;

&lt;p&gt;I had confused functionality with value.&lt;/p&gt;




&lt;h2&gt;
  
  
  What HAID Actually Became
&lt;/h2&gt;

&lt;p&gt;So I sat down and forced myself to answer the question: what is HAID &lt;em&gt;for&lt;/em&gt;? Not what it could be someday, but what it is for right now that nothing else does.&lt;/p&gt;

&lt;p&gt;HAID stands for &lt;em&gt;How Am I Doing&lt;/em&gt;. And I realized the answer to that question shouldn't come from just wearable data. It should come from &lt;strong&gt;context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's what I mean: I love to travel. When I'm traveling, my training falls off. My training load drops. My step count changes. But I'm not a professional athlete. When I travel, I eat, drink, stay out late, enjoy life. No app knows that. And no app uses that information to actually help me. Something as simple as: "You're traveling, enjoy it, but how about one easy run this week?"&lt;/p&gt;

&lt;p&gt;Same thing with injuries, stress, life changes. These things directly impact training and recovery, but no fitness app accounts for them. Your Garmin doesn't know you pulled a muscle, had a terrible week at work, or just got back from vacation.&lt;/p&gt;

&lt;p&gt;Think about injuries. Apps track training load, TSS, all that, but do they actually warn you to slow down before it's too late? Imagine if the app could see the pattern: three stressful weeks, poor sleep, and a climbing training load. That's a recipe for injury. And with enough users sharing that context, injury prevention gets smarter over time.&lt;/p&gt;

&lt;p&gt;The point of HAID is not just to aggregate data, but to help answer a better question: &lt;em&gt;how am I doing, really?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once I landed on that, things started clicking into place.&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%2Fhdjih9tdvlpz7hzv9iv5.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%2Fhdjih9tdvlpz7hzv9iv5.png" alt="024A4A76-5917-423E-BB49-9A398275D097_1_101_o.jpeg" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Now the Hard Part Starts
&lt;/h2&gt;

&lt;p&gt;I thought I was mostly trying to validate the ingestion pipeline, the UX, and the challenge features. But the real thing I needed to validate was much simpler: did HAID already give people a reason to care?&lt;/p&gt;

&lt;p&gt;At that stage, the answer was no.&lt;/p&gt;

&lt;p&gt;That was hard to hear, but also useful. Because from that point on, HAID stopped being "a bit of Strava, a bit of Garmin, a bit of Apple Health" and started becoming a product with a more specific idea: helping people understand their fitness through life context, not just raw data.&lt;/p&gt;

&lt;p&gt;Building it was the part I already knew how to do.&lt;/p&gt;

&lt;p&gt;Growth is the part I'm learning now.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you want to check out what I'm building: &lt;a href="https://haid.app/" rel="noopener noreferrer"&gt;haid.app&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Next post: how I turned a mess of feature ideas into an actual product roadmap and what I learned about product thinking as an engineer who'd never done it before.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>app</category>
      <category>development</category>
      <category>growth</category>
      <category>product</category>
    </item>
    <item>
      <title>Como encontrar facilmente eventos de corrida, natação, ciclismo e triatlhon no mundo todo</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Mon, 08 May 2023 17:32:26 +0000</pubDate>
      <link>https://dev.to/shadowlik/como-encontrar-facilmente-eventos-de-corrida-natacao-ciclismo-e-triatlhon-no-mundo-todo-14af</link>
      <guid>https://dev.to/shadowlik/como-encontrar-facilmente-eventos-de-corrida-natacao-ciclismo-e-triatlhon-no-mundo-todo-14af</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jzh3wsvfqte1abh7wep.jpg" 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%2F7jzh3wsvfqte1abh7wep.jpg" alt="apuama.app" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você é um entusiasta de esportes, como corrida, triatlhon ou natação, sabe como é importante participar de eventos para melhorar sua performance e se desafiar. No entanto, encontrar os eventos certos pode ser difícil. Felizmente, existe um site que pode ajudar: o &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt; é um site gratuito que permite que você encontre facilmente eventos de corrida, triatlo e natação em sua região ou em qualquer lugar do mundo. Ele fornece informações detalhadas sobre cada evento, como distância, localização, data e hora, e permite que você se inscreva diretamente no site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apuama.app/" rel="noopener noreferrer"&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%2Fydlpt2thy6auwwdnuqon.jpg" alt="apuama.app" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;https://apuama.app/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que faz o &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt; ser tão especial?
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt; se destaca por sua facilidade de uso e pela ampla variedade de eventos esportivos disponíveis. O site é projetado para ajudar atletas de todos os níveis a encontrar eventos que se encaixem em seus objetivos e nível de habilidade.&lt;/p&gt;

&lt;p&gt;Além disso, o Apuama oferece recursos úteis, como filtros de pesquisa avançados, para ajudá-lo a encontrar exatamente o que você está procurando. Você pode filtrar eventos por tipo de esporte, localização, data, distância e muito mais.&lt;/p&gt;

&lt;p&gt;Outra característica que faz o Apuama ser tão especial é a sua comunidade de atletas. O site permite que você se conecte com outros atletas, crie grupos e compartilhe suas experiências e dicas. Você também pode acompanhar a evolução de outros atletas e participar de desafios para manter-se motivado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como usar o &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apuama.app/" rel="noopener noreferrer"&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%2F3876v4hnoknl3rwza43q.jpg" alt="Busca inteligente Apuama" width="800" height="573"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Busca inteligente Apuama&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Usar o Apuama é muito simples. Basta acessar o site, criar uma conta gratuita e começar a pesquisar eventos de corrida, triatlo e natação em sua região ou em qualquer lugar do mundo. Ao encontrar um evento de seu interesse, você pode se inscrever diretamente no site e acompanhar todas as informações relevantes sobre o evento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa49n9ixnwa2kglu9cbau.jpg" 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%2Fa49n9ixnwa2kglu9cbau.jpg" alt="Página de evento - apuama.app" width="800" height="577"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Página de evento&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O site &lt;a href="https://apuama.app/" rel="noopener noreferrer"&gt;Apuama&lt;/a&gt; é uma ferramenta indispensável para qualquer atleta que queira encontrar facilmente eventos de corrida, triatlo e natação em todo o mundo. Com sua ampla variedade de eventos, recursos úteis e comunidade de atletas, o Apuama torna mais fácil do que nunca encontrar e participar de eventos. Então, comece a usar o Apuama hoje mesmo e descubra eventos incríveis para melhorar sua performance.&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/como-encontrar-facilmente-eventos-de-corrida-natacao-ciclismo-e-triatlhon-no-mundo-todo/" rel="noopener noreferrer"&gt;Como encontrar facilmente eventos de corrida, natação, ciclismo e triatlhon no mundo todo&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
    </item>
    <item>
      <title>boringproxy: Como expor serviços locais publicamente na internet</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Mon, 02 Jan 2023 13:56:58 +0000</pubDate>
      <link>https://dev.to/shadowlik/boringproxy-como-expor-servicos-locais-publicamente-na-internet-m5b</link>
      <guid>https://dev.to/shadowlik/boringproxy-como-expor-servicos-locais-publicamente-na-internet-m5b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0zi68lashynh46rs61n.jpg" 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%2Fg0zi68lashynh46rs61n.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você já precisou compartilhar algum serviço, banco de dados, API ou site que está sendo desenvolvido na sua máquina local publicamente na internet com alguém? Existem maneiras de compartilhar seus projetos sem precisar necessariamente subir ela em algum servidor ou cloud.&lt;/p&gt;

&lt;p&gt;Há algum tempo eu escrevi o artigo &lt;a href="https://marquesfernandes.com/desenvolvimento/tunel-encaminhamento-de-portas-com-ssh-ubuntu-debian/" rel="noopener noreferrer"&gt;Túnel/Encaminhamento de Portas com SSH – Ubuntu/Debian&lt;/a&gt; que explica exatamente como fazer isso utilizando apenas o &lt;a href="https://pt.wikipedia.org/wiki/Secure_Shell" rel="noopener noreferrer"&gt;SSH&lt;/a&gt;, porém para muitos isso pode não ser o suficiente ou de difícil gestão/manutenção. Existem alguns serviços pagos, como o &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;, mas seu pacote gratuito é bem limitado e o pacote mais barato acaba sendo caro para simples projetos pessoais (algo em torno de 20 USD mês), mas não se preocupe, existem soluções open source para isso.&lt;/p&gt;

&lt;p&gt;O desenvolvedor Anders Pitman criou um repositório muito legal de &lt;a href="https://github.com/anderspitman/awesome-tunneling" rel="noopener noreferrer"&gt;alternativas para o ngrok&lt;/a&gt;, nesse tutorial vamos focar em um serviço específico, o &lt;a href="https://boringproxy.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;boringproxy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso
&lt;/h2&gt;

&lt;p&gt;Veja abaixo alguns casos de uso para esse tipo de túnel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Você está desenvolvendo uma aplicação local e precisa expor sua API publicamente para compartilhar com alguém ou simplesmente utilizar alguma ferramenta que precise ter acesso a uma URL pública&lt;/li&gt;
&lt;li&gt;Você está estruturando um banco de dados e gostaria de conectar para desenvolver em alguma ferramenta como o &lt;a href="https://retool.com/" rel="noopener noreferrer"&gt;Retool&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Você está criando uma aplicação frontend e gostaria de realizar testes com o &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;Google PageSpeed&lt;/a&gt; ou alguma ferramenta de benchmark e para isso precisa que elas consigam encontrar seu projeto publicamente na internet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses são alguns de inúmeros casos de uso, e o mais legal é que com o boringproxy podemos expor toda nossa infraestrutura de uma vez, banco de dados, API, frontend e qualquer outro serviço que queremos expor na internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://boringproxy.io/" rel="noopener noreferrer"&gt;boringproxy&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://boringproxy.io/" rel="noopener noreferrer"&gt;boringproxy&lt;/a&gt; é uma combinação de um proxy reverso e um gerenciador de túnel.&lt;/p&gt;

&lt;p&gt;O que isso significa é que, se você tiver um serviço auto-hospedado (API, MySQL, Postgres, Redis, Frontend em React, Vue, Angular, …) em execução em uma rede local e privada, o boreproxy visa fornecer a maneira mais fácil para expor com segurança (ou seja, com suporte a HTTPS e até proteção por senha) esse servidor à Internet, para que você possa acessá-lo de qualquer lugar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Começando nossa infraestrutura
&lt;/h2&gt;

&lt;p&gt;Para esse tutorial vamos precisar de basicamente um computador rodando alguns serviços locais, um servidor com IP público para internet e um domínio.&lt;/p&gt;

&lt;h3&gt;
  
  
  Servidor com IP público
&lt;/h3&gt;

&lt;p&gt;Para o servidor com IP público vamos utilizar o Google Cloud Platform pois ela nos oferece uma máquina no &lt;a href="https://cloud.google.com/free/docs/free-cloud-features#compute" rel="noopener noreferrer"&gt;nível gratuito&lt;/a&gt;, ou seja, não vamos precisar gastar um tustão.&lt;/p&gt;

&lt;p&gt;Primeiro você precisa criar uma conta no &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;GCP&lt;/a&gt;. Após a conta criada, vamos criar uma máquina virtual que se enquadre no nível gratuito, que no caso seria uma &lt;em&gt;&lt;code&gt;e2-micro&lt;/code&gt;&lt;/em&gt; em alguma das regiões: &lt;code&gt;us-west1; us-central1; us-east1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdeo270nmuut1sot3u6nt.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%2Fdeo270nmuut1sot3u6nt.png" alt="Acessando o menu do Compute Engine &gt; Instâncias de VM" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Acessando o menu do Compute Engine &amp;gt; Instâncias de VM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Primeiro precisamos acessar no menu lateral o serviço de Compute Engine &amp;gt; Instâncias de VM.&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%2Fsmzq7rhluqjb7gba9esd.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%2Fsmzq7rhluqjb7gba9esd.png" alt="Habilitando a API do Compute Engine" width="800" height="526"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Habilitando a API do Compute Engine&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Se for a primeira vez que você estiver acessando o serviço de Compute Engine do Google, você será notificado para habilitar a API, basta clicar em &lt;code&gt;Habilitar&lt;/code&gt; e esperar o término da habilitação.&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%2Fyj1i4anxezoz7mta1oc6.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%2Fyj1i4anxezoz7mta1oc6.png" alt="Criar instância de VM" width="798" height="152"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Criar instância de VM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Clique no botão de &lt;code&gt;Criar Instância&lt;/code&gt; para começar a configuração de nossa nova máquina virtual no GCP.&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%2F7fhdhgdrxshcp61qvp1w.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%2F7fhdhgdrxshcp61qvp1w.png" alt="Configurando nossa nova VM" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Configurando nossa nova VM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora vamos configurar nossa máquina virtual para as configurações que se aplicam dentro do plano gratuito do Google Cloud, &lt;code&gt;e2-micro&lt;/code&gt; e a região escolhida foi a&lt;code&gt;us-central1 (Iowa)&lt;/code&gt;. Não se preocupe se um preço aparecer a direita, o desconto do nível gratuito será aplicado ao final de cada ciclo de pagamento.&lt;/p&gt;

&lt;p&gt;Por padrão a máquina será criada com o sistema operacional &lt;a href="https://wiki.debian.org/pt_BR/DebianIntroduction" rel="noopener noreferrer"&gt;Debian&lt;/a&gt; e um disco permanente de 10 GB, vamos prosseguir com essa configuração padrão para o nosso tutorial.&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%2Fzwa4pupab65qu5yxycqw.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%2Fzwa4pupab65qu5yxycqw.png" width="799" height="234"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Habilitando os protocolos HTTP e HTTPS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Precisamos adicionar uma última configuração, descendo a página você encontrar a sessão de Firewall, selecione para habilitar os tráfegos de HTTP e HTTPS no servidor.&lt;/p&gt;

&lt;p&gt;Agora clique em Criar e aguarda a criação da máquina virtual.&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%2Fjexevhkjc9bhskhisdhw.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%2Fjexevhkjc9bhskhisdhw.png" alt="Máquina virtual GCP" width="800" height="168"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Copie o IP público da máquina&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Com a criação finalizada, temos agora o IP público de nossa máquina, salve esse número, usaremos ele para configurar nosso domínio.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o domínio
&lt;/h2&gt;

&lt;p&gt;Eu sempre indico como resolvedor de DNS o &lt;a href="https://cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt;, pois ele oferece muitos serviços legais e o melhor, é gratuito. Caso você utilize algum outro serviço, acesse ele para configurar os domínios necessários para o boringproxy funcionar.&lt;/p&gt;

&lt;p&gt;Vamos precisar configurar dois domínios, o primeiro domínio será referente ao painel administrativo do boringproxy, por exemplo, &lt;code&gt;boringproxy.marquesfernandes.com&lt;/code&gt; e o segundo será domínio do tipo wildcard, ele será o responsável por automaticamente gerenciar os tuneis que vamos criar posteriormente, nesse caso vamos criar um domínio &lt;code&gt;*.boringproxy.marquesfernandes.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ambos irão apontar para o mesmo lugar, o IP público do nosso servidor criado na etapa anterior, então nossa configuração para o primeiro domínio será do tipo &lt;code&gt;A&lt;/code&gt; e do segundo vamos utilizar um &lt;code&gt;CNAME&lt;/code&gt; para o primeiro, dessa maneira se precisarmos trocar a configuração no futuro, só precisaremos alterar em um lugar.&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%2F6lj54ff48j5z0btehr6v.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%2F6lj54ff48j5z0btehr6v.png" alt="Criando o primeiro domínio" width="800" height="214"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Criando o primeiro domínio&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Crie o primeiro domínio selecionando o tipo como A, insira o IP do servidor copiado na etapa anterior e não se esqueça de desabilitar o proxy do Cloudflare.&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%2Ff15gc8sgdfp3nvi083f1.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%2Ff15gc8sgdfp3nvi083f1.png" width="799" height="213"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Criando o domínio Wildcard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora precisamos criar o nosso domínio Wildcard, para isso utilizaremos o &lt;code&gt;*&lt;/code&gt; antes do nome do subdomínio que queremos utilizar, nesse caso &lt;code&gt;*.boringproxy.marquesfernandes.com&lt;/code&gt;, ele será responsável para quando criarmos nossos tuneis no boringproxy, por exemplo, &lt;code&gt;api.boringproxy.marquesfernandes.com&lt;/code&gt; a configuração funcionar sem mais a necessidade de criar subdomínios no Cloudflare.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o boringproxy no servidor
&lt;/h2&gt;

&lt;p&gt;Agora que temos nossos domínios configurados, podemos finalmente partir para a configuração do boringproxy em nosso servidor, para isso vamos acessar o SSH de nossa máquina virtual. Volte na tela de listagem das máquinas virtuais no Google Cloud e selecione a máquina criada, clique no botão SSH e uma nova janela com o nosso terminal abrirá.&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%2Fstk2fyxus9bx527vpdkp.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%2Fstk2fyxus9bx527vpdkp.png" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Acessando o SSH da máquina virtual&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Aguarde a transferência das chaves de SSH e uma janela parecida com essa deverá ser carregada:&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%2Fnify0u7lg8lrkxx1di3z.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%2Fnify0u7lg8lrkxx1di3z.png" alt="Terminal VM SSH" width="800" height="130"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Terminal VM SSH&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, agora vamos criar uma pasta que abrigará a instalação do boringproxy, recomendo que a pasta seja criada em &lt;code&gt;/usr/local/boringproxy&lt;/code&gt;. Por se tratar de uma pasta em um local que requer permissões root, precisamos utilizar o comando sudo. Vamos utilizar &lt;code&gt;sudo su&lt;/code&gt; para não precisar digitar toda hora sudo, mas cuidado, você estará executando qualquer comando com privilégios elevados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo su
mkdir /usr/local/boringproxy

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

&lt;/div&gt;



&lt;p&gt;Entre na pasta usando o comando &lt;code&gt;cd /usr/local/boringproxy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Seguiremos as &lt;a href="https://boringproxy.io/installation/" rel="noopener noreferrer"&gt;instruções de instalação da documentação do boringproxy&lt;/a&gt; para Linux x86_64.&lt;/p&gt;

&lt;p&gt;Dentro da pasta criada execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
curl -LO https://github.com/boringproxy/boringproxy/releases/latest/download/boringproxy-linux-x86_64

chmod +x boringproxy-linux-x86_64

sudo setcap cap_net_bind_service=+ep boringproxy-linux-x86_64

&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%2Fomfzs1holevvxldrjp2d.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%2Fomfzs1holevvxldrjp2d.png" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você pretende usar os tuneis para encaminhamento de serviços como banco de dados, que utilizam o protocolo TCP e não HTTP, precisamos editar a configuração do sshd para permitir o encaminhamento de portas TCP.&lt;/p&gt;

&lt;p&gt;Vamos editar o arquivo &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; e trocar &lt;code&gt;GatewayPorts no&lt;/code&gt; por &lt;code&gt;GatewayPorts clientspecified&lt;/code&gt;. Você pode utilizar o seu editor preferido, no meu caso, &lt;code&gt;nano /etc/ssh/sshd_config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmdvkwmjx6x4039ytgazb.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%2Fmdvkwmjx6x4039ytgazb.png" width="799" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Iniciando o boringproxy no servidor
&lt;/h3&gt;

&lt;p&gt;Muito bem, agora podemos &lt;a href="https://boringproxy.io/usage/" rel="noopener noreferrer"&gt;iniciar o boringproxy&lt;/a&gt; em nosso servidor, no comando abaixo troque &lt;code&gt;boringproxy.marquesfernandes.com&lt;/code&gt;pelo primeiro domínio que você configurou.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
./boringproxy-linux-x86_64 server -admin-domain boringproxy.marquesfernandes.com

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

&lt;/div&gt;



&lt;p&gt;Seu e-mail será solicitado, essa informação é utilizada para gerar os certificados HTTPS necessários utilizando o &lt;a href="https://letsencrypt.org/pt-br/" rel="noopener noreferrer"&gt;Let’s Encrypt&lt;/a&gt;. Se tudo estiver correto, você deverá ver a mensagem &lt;code&gt;Successfully acquired certificate...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1sv7aw5i7fj4orzkar1b.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%2F1sv7aw5i7fj4orzkar1b.png" width="799" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Utilize o comando &lt;code&gt;ctrl + c&lt;/code&gt;para cancelar o serviço, agora utilize o comando &lt;code&gt;ls&lt;/code&gt; para listar os arquivos da pasta, note que um arquivo chamado boringproxy_db.json foi criado, ele é um mini banco de dados das configurações do boringproxy. Utilize o comando &lt;code&gt;cat boringproxy_db.json&lt;/code&gt; para ver o conteúdo do arquivo e pegar o token de acesso, salve esse token em algum lugar seguro.&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%2Fjfs3pgc3na8h66xlihij.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%2Fjfs3pgc3na8h66xlihij.png" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Execute novamente o comando &lt;code&gt;./boringproxy-linux-x86_64 server -admin-domain boringproxy.marquesfernandes.com&lt;/code&gt; para iniciar o boringproxy e acesse de seu navegador o domínio do admin, em nosso caso, &lt;code&gt;boringproxy.marquesfernandes.com&lt;/code&gt;. Se tudo foi configurado corretamente, uma tela solicitando o token de admin deve aparecer, insira o token e acesse o painel administrativo. Mantenha a janela do terminal da máquina virtual aberta e o serviço rodando para os próximos passo.&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%2Fd6bgqm700wc4x40z9bbx.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%2Fd6bgqm700wc4x40z9bbx.png" alt="Painel administrativo boringproxy" width="800" height="209"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Painel administrativo boringproxy&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Subindo algumas aplicações locais
&lt;/h2&gt;

&lt;p&gt;Vamos deixar algumas aplicações rodando em nossa máquina local para expor elas na internet usando os tuneis criados. Usarei dois exemplos simples, vamos subir um projeto em React e um banco de dados em Postgres rodando em &lt;a href="https://marquesfernandes.com/tecnologia/conteineres-e-docker-o-que-e-e-para-que-serve/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; para testar tanto uma configuração HTTPS e uma TCP, lembrando que você pode usar para qualquer serviço que você queria disponibilizar na internet, seja uma API, algum outro banco de dados, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://create-react-app.dev/docs/getting-started" rel="noopener noreferrer"&gt;React App&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Vamos utilizar o &lt;a href="https://create-react-app.dev/docs/getting-started" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt; para criar uma aplicação simples em nossa máquina local e expor ele publicamente na internet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
npx create-react-app my-app
cd my-app
npm start

&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%2Fj2unmo9u16ye1vdk3nju.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%2Fj2unmo9u16ye1vdk3nju.png" alt="React App funcionando" width="435" height="175"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;React App funcionando&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Se tudo der certo, sua aplicação estará rodando e disponível na porta &lt;code&gt;3000&lt;/code&gt;. Deixe esse terminal rodando.&lt;/p&gt;
&lt;h3&gt;
  
  
  Postgres no Docker
&lt;/h3&gt;

&lt;p&gt;Para subir o banco de dados, você precisa ter o Docker instalado e &lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;executar o seguinte comando&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
docker run --name my-postgres -e POSTGRES_PASSWORD=123456 -p 5432:5432 postgres

&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%2F020hkqr3xm2jtbydjn7i.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%2F020hkqr3xm2jtbydjn7i.png" alt="Executando o Postgres no Docker" width="794" height="160"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Executando o Postgres no Docker&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora temos o nosso banco de dados disponível na porta &lt;code&gt;5432&lt;/code&gt;. Use algum cliente de banco, como o &lt;a href="https://dbeaver.io/download/" rel="noopener noreferrer"&gt;DBvear&lt;/a&gt;, usando o usuário &lt;code&gt;postgres&lt;/code&gt; e a senha &lt;code&gt;123456&lt;/code&gt; para garantir que a conexão foi bem sucedida.&lt;/p&gt;
&lt;h2&gt;
  
  
  Criando os tuneis
&lt;/h2&gt;

&lt;p&gt;Agora que já temos algumas aplicações rodando, podemos criar a configuração de nossos tuneis, para isso vamos voltar ao painel administrativo em &lt;code&gt;boringproxy.marquesfernadnes.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adicionando um cliente
&lt;/h3&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%2Fsi39llab6vxmie3njy8c.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%2Fsi39llab6vxmie3njy8c.png" alt="Criando um cliente no boringproxy" width="799" height="199"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Criando um cliente no boringproxy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Primeiro precisamos criar um cliente, para isso navegue até a aba de clients e adicione um cliente com o nome de &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando os túneis
&lt;/h3&gt;

&lt;p&gt;O painel de túneis permite criar e remover túneis. Ele fornece uma maneira de especificar as configurações de um túnel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;
O FQDN de um domínio apontando para o &lt;code&gt;boringproxy&lt;/code&gt;servidor. Com a configuração do caractere curinga do DNS, pode ser qualquer subdomínio do &lt;code&gt;admin-domain&lt;/code&gt;. Você deve inserir o  &lt;strong&gt;domínio completo&lt;/strong&gt;  a partir do qual deseja que o túnel seja acessado, não apenas o subdomínio. Por exemplo, se você tivesse um registro DNS curinga &lt;code&gt;*.boringproxy.marquesfernandes.com&lt;/code&gt;apontando para seu servidor de proxy chato e desejasse que um servidor de mídia fosse acessado em &lt;code&gt;api.boringproxy.marquesfernandes.com&lt;/code&gt;, você teria que inserir &lt;code&gt;api.boringproxy.marquesfernandes.com&lt;/code&gt; neste campo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Name&lt;/strong&gt;
Escolha um cliente conectado como parceiro de túnel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Address&lt;/strong&gt;
O destino de encaminhamento visto do cliente&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client Port&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;O encaminhamento de porta para&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow External TCP&lt;/strong&gt;
Ativa o túnel TCP bruto para outros protocolos além do HTTP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password Protect&lt;/strong&gt;
Ative para definir nome de usuário e senha para autenticação básica HTTP&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%2Fww9b7iuzk9a2zaz6je0g.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%2Fww9b7iuzk9a2zaz6je0g.png" alt="Adicionando o túnel para a aplicação React" width="799" height="420"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Adicionando o túnel para a aplicação React&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora vamos criar o nosso primeiro túnel, ele fara o proxy para a nossa aplicação React. Configure o domínio desejado no campo de &lt;code&gt;domain&lt;/code&gt; utilizando o padrão do dominio. wildcard que criamos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain:&lt;/strong&gt; react.boringproxy.marquesfernandes.com&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tunnel Port&lt;/strong&gt; : Random&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Name&lt;/strong&gt; : admin &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Port&lt;/strong&gt; : 3000 (port da nossa aplicação react)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS Termination&lt;/strong&gt; : Client HTTPS&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%2F2kzdmy7nf1tereun4nvd.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%2F2kzdmy7nf1tereun4nvd.png" alt="Adicionando o túnel para o banco de dados" width="800" height="423"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Adicionando o túnel para o banco de dados&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Vamos criar um túnel também para o nosso banco de dados, seguiremos os mesmos passos do túnel para o React, porém, trocando algumas configurações.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tunnel Port&lt;/strong&gt; : 5432&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS Termination&lt;/strong&gt; : Server HTTPS &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow External TCP&lt;/strong&gt; : Sim&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%2F2q0afhisrzy5uigk26f1.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%2F2q0afhisrzy5uigk26f1.png" alt="Listagem de túneis do boringproxy" width="800" height="228"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Listagem de túneis do boringproxy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora você verá os dois túneis criados como na listagem acima.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configurando o boringproxy na máquina local
&lt;/h2&gt;

&lt;p&gt;E por fim, precisamos instalar o boringproxy em nossa máquina local, siga na &lt;a href="https://boringproxy.io/installation/" rel="noopener noreferrer"&gt;página oficial as instruções de instalação&lt;/a&gt; referente ao seu respectivo sistema operacional. Lembrando que se você estiver usando MacOS como eu, você precisa baixar a versão &lt;code&gt;boringproxy-darwin-x86_64&lt;/code&gt; e executar o comando &lt;code&gt;sudo chmod +x boringproxy-dawrin-x86_64&lt;/code&gt; para que ele se torne um executável.&lt;/p&gt;

&lt;p&gt;Agora precisamos iniciar o serviço para conectar em nosso servidor, para isso executaremos o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
./boringproxy-dawrin-x86_64 client \
    -server boringproxy.marquesfernandes.com -user admin -token &amp;lt;token_copiado_do_servidor&amp;gt; -client-name admin

&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%2Fm2u6pqvnzsxqv9udnvrh.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%2Fm2u6pqvnzsxqv9udnvrh.png" alt="boringproxy client" width="720" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os túneis serão sincronizados, os certificados necessários para o lado cliente serão emitidos e se tudo caminhar conforme o esperado, suas aplicações agora estarão disponíveis na internet. Em um navegador acesse a URL configurada para o React e veja a magia e faça o teste com o seu banco de dados também.&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%2F5wb85svchybelf02flr3.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%2F5wb85svchybelf02flr3.png" alt="React App acessível via Proxy" width="800" height="378"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;React App acessível via Proxy&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando o boringproxy para rodar como serviço
&lt;/h2&gt;

&lt;p&gt;Se você deseja configurar o boringproxy no lado servidor como um serviço, para evitar o trabalho de toda vez que quiser utilizar, precisar ir no ssh do servidor e subir, siga o tutorial:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://marquesfernandes.com/desenvolvimento/criando-um-servico-linux-com-systemd/" rel="noopener noreferrer"&gt;Criando um Serviço Linux com systemd&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/boringproxy-como-expor-servicos-locais-publicamente-na-internet/" rel="noopener noreferrer"&gt;boringproxy: Como expor serviços locais publicamente na internet&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>desenvolvimento</category>
      <category>tecnologia</category>
      <category>boringproxy</category>
      <category>cloudflare</category>
    </item>
    <item>
      <title>Top 6 Sites para Encontrar, Gerar, Criar e Compartilhar Memes</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Fri, 19 Aug 2022 14:10:19 +0000</pubDate>
      <link>https://dev.to/shadowlik/top-6-sites-para-encontrar-gerar-criar-e-compartilhar-memes-36dk</link>
      <guid>https://dev.to/shadowlik/top-6-sites-para-encontrar-gerar-criar-e-compartilhar-memes-36dk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvv6paglecpw1rwatno4.jpeg" 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%2Fwvv6paglecpw1rwatno4.jpeg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os memes caíram no gosto da internet, especialmente para nós brasileiros, vamos ser honestos, adoramos um bom meme não? Memes são divertidos e passam a mensagem provavelmente melhor do que poderíamos escrever, afinal, uma imagem vale por mil palavras.&lt;/p&gt;

&lt;p&gt;Você já se pegou procurando aquele meme antigo? Ou então querendo criar um meme customizado para mandar para algum grupo no zapzap? Pois bem, vamos facilitar sua vida com uma lista dos 6 melhores sites para você encontrar e criar memes online! Nada de baixar Photoshop ou qualquer outro programa para isso.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://memegenerator.net/" rel="noopener noreferrer"&gt;Meme Generator&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhiii0sp31pkdonl86kk.jpg" 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%2Fjhiii0sp31pkdonl86kk.jpg" alt="Meme Generator" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;memegenerator.net&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O &lt;a href="https://memegenerator.net/" rel="noopener noreferrer"&gt;Meme Generator&lt;/a&gt; é possivelmente uma das melhores ferramentas disponíveis para criar seus próprios memes. Simples e intuitivo, ele também permite que você navegue por memes criados por outras pessoas, um marketplace de memes!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="http://www.quickmeme.com/" rel="noopener noreferrer"&gt;quickmeme&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0x0obtaz4mf4blzsoi7.jpg" 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%2Fv0x0obtaz4mf4blzsoi7.jpg" alt="quickmeme" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;quickmeme.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O &lt;a href="http://www.quickmeme.com/" rel="noopener noreferrer"&gt;quickmeme&lt;/a&gt; permite navegar pelos memes e criar os seus próprios a partir de qualquer combinação de imagens e texto. Seu layout lembra muito o design do site &lt;a href="https://9gag.com/" rel="noopener noreferrer"&gt;9gag&lt;/a&gt;, com a possibilidade de votar e avaliar memes, bem como gerar memes aleatórios.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://imgur.com/memegen" rel="noopener noreferrer"&gt;Imgur&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://imgur.com/memegen" rel="noopener noreferrer"&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%2Fn4zr93ztb5a0d42wekqp.jpg" alt="imgur" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;imgur.com/memegen&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imgur.com/memegen" rel="noopener noreferrer"&gt;Imgur&lt;/a&gt; vem com muitas imagens embutidas que podem ser usadas para fazer seus memes instantaneamente. Esse site é amado pelas comunidades do Reddit, possui uma ampla variedade não só de memes, como de imagens e ferramentas.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://imgflip.com/memegenerator" rel="noopener noreferrer"&gt;Imgflip&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://imgflip.com/memegenerator" rel="noopener noreferrer"&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%2Fipahafajo7jjhb8dpskh.jpg" alt="imgflip" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;imgflip.com/memegenerator&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Os geradores de imagem &lt;a href="https://imgflip.com/memegenerator" rel="noopener noreferrer"&gt;Imgflip&lt;/a&gt; são projetados para serem incrivelmente rápidos e fornecer personalização poderosa, ao mesmo tempo, em que são simples e fáceis de usar. As imagens criadas no Imgflip podem ser “privadas” se você quiser apenas baixar a imagem e salvá-la para si mesmo, ou podem ser salvas publicamente para a comunidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://livememe.com/" rel="noopener noreferrer"&gt;livememe&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://livememe.com/" rel="noopener noreferrer"&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%2F1tejdqf0bfux43l2skzh.jpg" alt="livememe" width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;livememe.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Já na página inicial do &lt;a href="https://livememe.com/" rel="noopener noreferrer"&gt;LiveMeme&lt;/a&gt; você encontra uma enorme seleção dos personagens virais recorrentes mais populares da web, de Fry de Futurama a Jean-Luc Picard e Batman. A partir daí, basta adicionar sua legenda e pronto!&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/self/top-6-sites-para-encontrar-gerar-criar-e-compartilhar-memes/" rel="noopener noreferrer"&gt;Top 6 Sites para Encontrar, Gerar, Criar e Compartilhar Memes&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>self</category>
    </item>
    <item>
      <title>8 Playlists do Spotify para Programação e Foco para 2022</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Tue, 29 Mar 2022 11:45:49 +0000</pubDate>
      <link>https://dev.to/shadowlik/8-playlists-do-spotify-para-programacao-e-foco-para-2022-cfk</link>
      <guid>https://dev.to/shadowlik/8-playlists-do-spotify-para-programacao-e-foco-para-2022-cfk</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh2hy5irfxpdldy2kpk0b.jpeg" 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%2Fh2hy5irfxpdldy2kpk0b.jpeg" alt="Mulher trabalhando com um tablet e escutando música" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando precisamos focar para resolver aquele problema difícil, aquele código que trava a nossa mente, ou simplesmente tirar todo aquele barulho externo, seja no home-office (quem nunca teve problema com furadeira?), ou no escritório presencial como todas aquelas conversas em volta. É cientificamente comprovado que a música pode nos colocar no clima certo e desencadear o fluxo de ideias. O problema é que encontrar a música certa não é fácil por isso montei essa lista com as playlists que mais escuto no meu dia a dia, se você precisa encontrar a música certa para desenvolver e se concentrar melhor no trabalho veio no lugar certo. Mas Henrique, eu não tenho Spotify… Deixa no comentário qual app você usa que a gente da um jeito!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/1qvW13XhfMMZMlzQx362HR?si=b574082af5d842c7" rel="noopener noreferrer"&gt;1. Coding Beats&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/playlist/1qvW13XhfMMZMlzQx362HR?si=b574082af5d842c7" rel="noopener noreferrer"&gt;Coding Beats&lt;/a&gt; é uma playlist bem balanceada, perfeita pra aqueles dias que concentrar está difícil.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DXctgIf9k05Pu?si=3933d962e63a42d3" rel="noopener noreferrer"&gt;2. Aesthetic Lofi&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Se você está procurando uma playlist com batidas leves e músicas extremamente agradáveis ao ouvido vá de &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DXctgIf9k05Pu?si=3933d962e63a42d3" rel="noopener noreferrer"&gt;Aesthetic Lofi&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/3DIjw8eboATMgRN2RC6mz6?si=9ea886a730e841fc" rel="noopener noreferrer"&gt;3. Lofi Coding&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/playlist/3DIjw8eboATMgRN2RC6mz6?si=9ea886a730e841fc" rel="noopener noreferrer"&gt;Lofi Coding&lt;/a&gt; é pra quem busca algo mais tranquilo, que inspire a paz interior para não socar o computador.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/0pGdGpMm84h2Jl6Q1KmTMn?si=f4f07aeb59134115" rel="noopener noreferrer"&gt;4. Lofi Coders&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Outra playlist com músicas para acalmar a alma, &lt;a href="https://open.spotify.com/playlist/0pGdGpMm84h2Jl6Q1KmTMn?si=f4f07aeb59134115" rel="noopener noreferrer"&gt;Lofi Coders&lt;/a&gt; pode evitar que você xingue algum colega.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/2L8Gm7T2aJvRj1ih03UeKv?si=8f451c4a956b4d6e" rel="noopener noreferrer"&gt;5. Code-fi / lofi beats&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/playlist/2L8Gm7T2aJvRj1ih03UeKv?si=8f451c4a956b4d6e" rel="noopener noreferrer"&gt;Code-fi / lofi beats&lt;/a&gt; é mais uma playlist de boas para a acalmar a mente.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DX8Uebhn9wzrS?si=5853da4ede724eef" rel="noopener noreferrer"&gt;6. Chill Lofi Study Beats&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/playlist/37i9dQZF1DX8Uebhn9wzrS?si=5853da4ede724eef" rel="noopener noreferrer"&gt;Chill Lofi Study Beats&lt;/a&gt; traz algumas músicas focadas em batidas mais profundas.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DX72ScqV2Zfd6?si=c731cd3b29d545aa" rel="noopener noreferrer"&gt;7. Chasing Sunsets&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Se você busca uma playlist mais animada para sua sessão de trabalho, &lt;a href="https://open.spotify.com/playlist/37i9dQZF1DX72ScqV2Zfd6?si=c731cd3b29d545aa" rel="noopener noreferrer"&gt;Chasing Sunsets&lt;/a&gt; é com certeza uma das melhores playlists na minha opinião.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://open.spotify.com/playlist/0JPsIxkQc2L5CtnbhktnUe?si=5ad22dd06b074b93" rel="noopener noreferrer"&gt;8. Ibiza Lounge Music&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Outra alternativa animada, &lt;a href="https://open.spotify.com/playlist/0JPsIxkQc2L5CtnbhktnUe?si=5ad22dd06b074b93" rel="noopener noreferrer"&gt;Ibiza Lounge Music&lt;/a&gt; vai te fazer sentir estar trabalhando numa vibe bem relax e animada.&lt;/p&gt;

&lt;p&gt;E você? Tem alguma playlist favorita para aqueles momentos de foco? Compartilha aí com a gente nos comentários!&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/8-playlists-do-spotify-para-programacao-e-foco-para-2022/" rel="noopener noreferrer"&gt;8 Playlists do Spotify para Programação e Foco para 2022&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
      <category>foco</category>
      <category>musica</category>
      <category>playlist</category>
    </item>
    <item>
      <title>Melhores temas de ícones para Ubuntu e Linux Mint (Debian)</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Sat, 03 Apr 2021 21:27:22 +0000</pubDate>
      <link>https://dev.to/shadowlik/melhores-temas-de-icones-para-ubuntu-e-linux-mint-debian-13fb</link>
      <guid>https://dev.to/shadowlik/melhores-temas-de-icones-para-ubuntu-e-linux-mint-debian-13fb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpck07ez7ym88ad2u1lmx.jpg" 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%2Fpck07ez7ym88ad2u1lmx.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você não gosta dos ícones que vieram na sua distro, seja ela Ubuntu ou Linux Mint, ou simplesmente quer dar uma nova cara para o seu desktop, saiba que é possível dar um toque de personalidade a mais usando temas de ícones personalizados!&lt;/p&gt;

&lt;p&gt;Existem centenas de temas de ícones por ai, separei os que eu mais gosto e já usei pra facilitar a sua busca. Eles variam de veráios estilos que vão desde glifos sutis, planos e 2D a pacotes que vão de encontro ao brilho, gradiente e detalhes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/PapirusDevelopmentTeam/papirus-icon-theme" rel="noopener noreferrer"&gt;1. Papirus Icon Theme&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/PapirusDevelopmentTeam/papirus-icon-theme" rel="noopener noreferrer"&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%2Fiwvxg9ndyr3c0ewvopu4.png" alt="Papirus Icon Theme" width="784" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Papirus é um tema de ícone SVG gratuito e de código aberto para Linux, baseado no Paper Icon Set com muitos novos ícones e alguns extras, como suporte para Hardcode-Tray , suporte para esquema de cores KDE , suporte para Folder Color e outros .&lt;/p&gt;

&lt;p&gt;O tema do ícone do Papirus está disponível em quatro variantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Papirus&lt;/li&gt;
&lt;li&gt;Papirus Dark&lt;/li&gt;
&lt;li&gt;Papirus Light&lt;/li&gt;
&lt;li&gt;ePapirus (para sistema operacional elementar e Pantheon Desktop)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/numixproject/numix-icon-theme-circle" rel="noopener noreferrer"&gt;2. Numix Circle&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/numixproject/numix-icon-theme-circle" rel="noopener noreferrer"&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%2F2cn3wr4euayycicfsi7n.png" alt="Numix Circle" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Circle é um tema de ícone para Linux do &lt;a href="https://numixproject.github.io/" rel="noopener noreferrer"&gt;projeto Numix&lt;/a&gt;. O conjunto de ícones do Círculo Numix agora abrange vários milhares de ícones de aplicativos, desde os favoritos dos velhos tempos até os mais novos, todos eles (sem surpresa) colocados em uma moldura circular.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/vinceliuice/Qogir-theme" rel="noopener noreferrer"&gt;3. Qogir Icon Theme&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/vinceliuice/Qogir-theme" rel="noopener noreferrer"&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%2Fjgzmrlnaiabgxktiyvxq.png" alt="Qogir Icon Theme" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qogir é um tema de design plano para GTK 3, GTK 2 e Gnome-Shell que suporta ambientes de desktop baseados em GTK 3 e GTK 2 como Gnome, Unity, Budgie, Cinnamon Pantheon, XFCE, Mate, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/zayronxio/Os-Catalina-icons/" rel="noopener noreferrer"&gt;4. OS Catalina&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/zayronxio/Os-Catalina-icons/" rel="noopener noreferrer"&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%2F7623wfkuwy2tnozl2e1k.jpg" alt="OS Catalina" width="678" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você deseja fazer o Ubuntu se parecer com um Mac – você pode gostar da aparência do sistema operacional, mas não de suas limitações – um conjunto de ícones como o OS Catalina é uma maneira fácil de fazer isso.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/vinceliuice/vimix-icon-theme" rel="noopener noreferrer"&gt;5. Vimix&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/vinceliuice/vimix-icon-theme" rel="noopener noreferrer"&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%2Flzbwzczbjt74dg8oy0kt.jpg" alt="Vimix" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O tema do ícone Vimix é baseado no &lt;a href="https://github.com/snwh/paper-icon-theme" rel="noopener noreferrer"&gt;Paper-Icon-Theme&lt;/a&gt;, um tema moderno de ícones freedesktop cujo design é baseado no uso de cores fortes e formas geométricas simples para compor os ícones. Cada ícone foi meticulosamente projetado para uma visualização perfeita de pixels.&lt;/p&gt;

&lt;p&gt;Embora se inspire nos ícones do Material Design do Google, alguns aspectos foram ajustados para se adequar melhor a um ambiente de desktop.&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/melhores-temas-de-icones-para-ubuntu-e-linux-mint-debian/" rel="noopener noreferrer"&gt;Melhores temas de ícones para Ubuntu e Linux Mint (Debian)&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
      <category>debian</category>
      <category>icons</category>
      <category>linux</category>
    </item>
    <item>
      <title>Como saber e validar o dígito verificador do RG (Registro Geral)</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Sat, 03 Apr 2021 21:04:51 +0000</pubDate>
      <link>https://dev.to/shadowlik/como-saber-e-validar-o-digito-verificador-do-rg-registro-geral-41oc</link>
      <guid>https://dev.to/shadowlik/como-saber-e-validar-o-digito-verificador-do-rg-registro-geral-41oc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj6sr5ax6bkih1461rfxa.jpg" 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%2Fj6sr5ax6bkih1461rfxa.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O RG (Registro Geral), ou cédula de identidade, carteira de identidade, identidade é o nosso documento nacional de identificação civil no Brasil. Os dados que constam nesse documento variam de acordo com o órgão responsável pela sua emissão bem como a sua regra matemática de autenticidade. Nesse artigo vamos demonstrar a regra e validação baseado em um documento emitido pela &lt;a href="https://www.ssp.sp.gov.br/" rel="noopener noreferrer"&gt;SSP-SP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O  &lt;strong&gt;dígito verificador&lt;/strong&gt; , nada mais é que o dígito que vem após o traço (xx.xxx.xxx- &lt;strong&gt;d&lt;/strong&gt; ). Ele  é um mecanismo de autenticação utilizado para verificar a validade e a autenticidade do um valor numérico, funciona como uma prevenção de fraudes ou possíveis erros de transmissão e geração do documento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como calcular o dígito verificador do RG
&lt;/h2&gt;

&lt;p&gt;Para aprender a lógica por trás da geração do dígito verificador utilizaremos neste artigo um RG válido e gerado randomicamente: &lt;code&gt;39.406.714-?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Primeiro vamos fazer uma tabela com 3 linhas e 8 colunas, teremos na primeira linha os 8 primeiros algarismos do número do RG.&lt;/p&gt;

&lt;p&gt;| 3 | 9 | 4 | 0 | 6 | 7 | 1 | 4 |&lt;br&gt;
| | | | | | | | |&lt;br&gt;
| | | | | | | | |&lt;/p&gt;

&lt;p&gt;Agora precisamos preencher a segunda linha, ela sempre obedecerá uma sequência lógica de números para todos o cálculo de qualquer RG. A sequência é &lt;strong&gt;2,3,4,5,6,7,8 e 9&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;| 3 | 9 | 4 | 0 | 6 | 7 | 1 | 4 |&lt;br&gt;
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |&lt;br&gt;
| | | | | | | | |&lt;/p&gt;

&lt;p&gt;Agora para obter os valores da terceira linha devemos multiplicar os números de cada linha por coluna. Por exemplo, 3×2, 9×3 e assim por diante.&lt;/p&gt;

&lt;p&gt;| 3 | 9 | 4 | 0 | 6 | 7 | 1 | 4 |&lt;br&gt;
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |&lt;br&gt;
| 6 | 27 | 16 | 0 | 36 | 49 | 8 | 36 |&lt;/p&gt;

&lt;p&gt;Agora que temos nossa tabela completa, precisamos somar todos os números obtidos na terceira linha. Em nosso exemplo teremos: &lt;strong&gt;6 + 27 + 16 + 0 + 36 + 49 + 8 + 36 = 178&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora precisamos descobrir o resto da divisão desse número por 11, você pode descobrir usando a calculador do seu computador usando o operador &lt;code&gt;mod&lt;/code&gt; &lt;strong&gt;: 178 mod 11&lt;/strong&gt;  &lt;strong&gt;= 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora precisamos subtrair de 11 o resto da nossa divisão e teremos finalmente o nosso dígito verificador: &lt;strong&gt;11 – 2 = 9&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Abaixo você encontra o algoritmo feito em JavaScript ES5 seguindo a lógica explicada acima.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function descobrirDigito(rg) {
    var digitos = rg.split("");
    var totais = [];
    var total = 0;

    // Multiplicamos os que seriam da primeira linha com os da segunda    
    digitos.forEach(function (digito, index) {
        totais.push(Number(digito) * (2 + index));
    });

    // Multiplicamos as colunas
    totais.forEach(function(numero) { total += numero });

    // Descobrimos o resto da divisão
    var resto = total % 11;

    return 11 - resto;
}

console.log(descobrirDigito("39406714"));

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Casos especiais
&lt;/h2&gt;

&lt;p&gt;Como tudo no Brasil, temos alguns casos especiais que precisamos estar atentos:&lt;/p&gt;

&lt;h3&gt;
  
  
  O dígito verificador do RG é X
&lt;/h3&gt;

&lt;p&gt;Quando nos deparamos com o dígito verificador &lt;strong&gt;X&lt;/strong&gt; , isso significa que o resultado da última etapa de nossa conta é &lt;strong&gt;10 (11 – 1)&lt;/strong&gt;. Então o dígito verificador &lt;strong&gt;10&lt;/strong&gt; foi substituído pelo algarismo romano &lt;strong&gt;X&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  O dígito verificador é 0
&lt;/h3&gt;

&lt;p&gt;Qundo nos deparamos com o dígito verificador &lt;strong&gt;0&lt;/strong&gt; , isso significa que o resultado da última etapa de nossa conta é &lt;strong&gt;11 (11 – 0)&lt;/strong&gt;. Então o dígito verificador &lt;strong&gt;11&lt;/strong&gt; foi substituído pelo algarismo 0.&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/self/como-saber-e-validar-o-digito-verificador-do-rg-registro-geral/" rel="noopener noreferrer"&gt;Como saber e validar o dígito verificador do RG (Registro Geral)&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>self</category>
      <category>rg</category>
    </item>
    <item>
      <title>Como configurar o headset bluetooth com microfone no Ubuntu, Mint (Debian)</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Fri, 02 Apr 2021 14:26:15 +0000</pubDate>
      <link>https://dev.to/shadowlik/como-configurar-o-headset-bluetooth-com-microfone-no-ubuntu-mint-debian-pma</link>
      <guid>https://dev.to/shadowlik/como-configurar-o-headset-bluetooth-com-microfone-no-ubuntu-mint-debian-pma</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lsln7h7aiacprtolpgo.jpg" 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%2F0lsln7h7aiacprtolpgo.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você usa ou acabou de migrar para o ambiente linux, especialmente nas distros Ubuntu ou Mint, derivados do Debian, você pode encontrar problemas com o microfone do seu headset bluetooth.&lt;/p&gt;

&lt;p&gt;Especialmente agora durante a pandemia, as famosas call (videoconferência) fazem cada vez mais parte do nosso cotidiano. Então você resolveu comprar aquele fone bluetooth bacana pra usar e quando conectou o seu microfone não funcionou? Não se preocupe, existe uma maneira de conseguir fazer o microfone do seu headset bluetooth funcionar no linux.&lt;/p&gt;

&lt;p&gt;Esse tutorial foi testado com fones da JBL e Air Pods, mas ele deverá funcionar para a maioria dos casos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ativando o microfone do headset bluetooth
&lt;/h2&gt;

&lt;p&gt;Para que o headset consiga funcionar corretamente com o microfone, você precisará habilitar o perfil de áudio HSP/HFP. Porém, por padrão, o &lt;a href="https://wiki.archlinux.org/index.php/PulseAudio_(Portugu%C3%AAs)#:~:text=PulseAudio%20%C3%A9%20um%20software%20livre,GNU%20Lesser%20General%20Public%20License." rel="noopener noreferrer"&gt;pulseaudio&lt;/a&gt; (servidor de som embarcado nessas distribuições do linux) só oferece suporte para o HSP. Para fazer o HSP/HFP funcionar, precisamos habilitar o HFP no pulseaudio e para isso vamos utilizar o serviço &lt;a href="https://en.wikipedia.org/wiki/OFono" rel="noopener noreferrer"&gt;ofono&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instale o &lt;code&gt;ofono&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo apt install ofono

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Configure o &lt;code&gt;pulseaudio&lt;/code&gt; para usar o &lt;code&gt;ofono&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Edite o arquivo &lt;code&gt;/etc/pulse/default.pa&lt;/code&gt; , encontre a linha &lt;code&gt;load-module module-bluetooth-discover&lt;/code&gt; e mude para &lt;code&gt;load-module module-bluetooth-discover headset=ofono&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adicione o usuário &lt;code&gt;pulse&lt;/code&gt; ao grupo &lt;code&gt;bluetooth&lt;/code&gt; para que ele tenha as permissões necessárias&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo usermod -aG bluetooth pulse

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Edite e adicione as permissões no arquivo &lt;code&gt;/etc/dbus-1/system.d/ofono.conf&lt;/code&gt; adicione o código abaixo logo antes do fechamento &lt;code&gt;&amp;lt;/busconfig&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;policy user="pulse"&amp;gt;
    &amp;lt;allow send_destination="org.ofono"/&amp;gt;
&amp;lt;/policy&amp;gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Para fazer o ofono funcionar é necessário fornecer um modem para ele. E para isso vamos instalar um emulador de modem chamado &lt;a href="https://packages.debian.org/stretch/devel/ofono-phonesim" rel="noopener noreferrer"&gt;phonesim&lt;/a&gt; que será implementado pelo ofono para funcionar. Instale o &lt;code&gt;ofono-phonesim&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo add-apt-repository ppa:smoser/bluetooth
$ sudo apt-get update
$ sudo apt-get install ofono-phonesim

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configure o &lt;code&gt;phonesim&lt;/code&gt; adicionando as seguintes linhas no arquivo &lt;code&gt;/etc/ofono/phonesim.conf&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[phonesim]
Driver=phonesim
Address=127.0.0.1
Port=12345

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

&lt;/div&gt;



&lt;p&gt;Agora, reinicie o serviço ofono:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo systemctl restart ofono.service

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Agora precisamos definir e habilitar alguns serviços para iniciar o ofono-phonesim como serviço.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para executar &lt;code&gt;ofono-phonesim -p 12345 /usr/share/phonesim/default.xml&lt;/code&gt; na inicialização do sistema, crie como root o arquivo &lt;code&gt;/etc/systemd/system/ofono-phonesim.service&lt;/code&gt; com o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[Unit]
Description=Run ofono-phonesim in the background

[Service]
ExecStart=ofono-phonesim -p 12345 /usr/share/phonesim/default.xml
Type=simple
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

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

&lt;/div&gt;



&lt;p&gt;Depois que o &lt;code&gt;ofono-phonesim&lt;/code&gt; for executado, você também precisará habilitar e colocar o modem phonesim online.&lt;/p&gt;

&lt;p&gt;Para isso vamos usar o código de um &lt;a href="http://git.kernel.org/pub/scm/network/ofono/ofono.git" rel="noopener noreferrer"&gt;repositório&lt;/a&gt; git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ cd /tmp
$ git clone git://git.kernel.org/pub/scm/network/ofono/ofono.git
$ sudo mv ofono /opt/

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

&lt;/div&gt;



&lt;p&gt;Agora você pode habilitar e tornar o modem phonesim online criando outro serviço do que depende do serviço ofono-phonesim.Novamente, crie um novo arquivo de serviço como root o arquivo em &lt;code&gt;/etc/systemd/system/phonesim-enable-modem.service&lt;/code&gt; e coloque o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[Unit]
Description=Enable and online phonesim modem
Requires=ofono-phonesim.service

[Service]
ExecStart=/opt/ofono/test/enable-modem /phonesim
ExecStart=/opt/ofono/test/online-modem /phonesim
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

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

&lt;/div&gt;



&lt;p&gt;Em seguida, execute os seguintes comandos para habilitar e executar os dois daemons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo systemctl daemon-reload
$ sudo systemctl enable ofono-phonesim.service
$ sudo systemctl enable phonesim-enable-modem.service
$ sudo service phonesim-enable-modem start

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

&lt;/div&gt;



&lt;p&gt;Verifique se tudo ocorreu como esperado e se o serviço está sendo executado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ sudo service phonesim-enable-modem status

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Por fim, reinicie o &lt;code&gt;pulseuadio&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ pulseaudio -k.

&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%2Fre5r3660qg29p9belrbj.jpg" 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%2Fre5r3660qg29p9belrbj.jpg" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você já deve conseguir enxergar o seu headset como dispositivo de input na parte de configuração de som. Existe uma certa instabilidade nesse setup, de vez em quando pode ser que o seu fone de uma desconfigurada ou a troca de perfil de áudio não funcione, quando isso ocorrer, reinicie os serviços como descrito acima e também o pulseaudio.&lt;/p&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/como-configurar-o-headset-bluetooth-com-microfone-no-ubuntu-mint-debian/" rel="noopener noreferrer"&gt;Como configurar o headset bluetooth com microfone no Ubuntu, Mint (Debian)&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
      <category>bluetooth</category>
      <category>debian</category>
      <category>fone</category>
    </item>
    <item>
      <title>O que é codificação de URL e como funciona?</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Sun, 21 Feb 2021 00:46:42 +0000</pubDate>
      <link>https://dev.to/shadowlik/o-que-e-codificacao-de-url-e-como-funciona-f0n</link>
      <guid>https://dev.to/shadowlik/o-que-e-codificacao-de-url-e-como-funciona-f0n</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzxcx6ub44owi5ern3wf.jpg" 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%2Fvzxcx6ub44owi5ern3wf.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um URL (acrônimo em inglês para Uniform Resource Locator) é o endereço de um recurso na rede mundial de computadores. Os URLs têm uma estrutura bem definida que foi formulada na &lt;a href="https://tools.ietf.org/html/rfc1738" rel="noopener noreferrer"&gt;RFC 1738&lt;/a&gt; por &lt;a href="https://pt.wikipedia.org/wiki/Tim_Berners-Lee" rel="noopener noreferrer"&gt;Tim Berners-Lee&lt;/a&gt;, inventor da rede mundial de computadores.&lt;/p&gt;

&lt;p&gt;Uma URL segue a seguinte &lt;em&gt;sintaxe:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protocolo:[//[usuario:senha@]host[:porta]]caminho[?parametro][#fragmento]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O uso mais conhecido para a URL é para a conexão em sites, como podemos ver no exemplo abaixo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://google.com.br
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Diversas melhorias foram feitas na RFC inicial. O RFC atual que define a sintaxe do URI é o &lt;a href="https://tools.ietf.org/html/rfc3986" rel="noopener noreferrer"&gt;RFC 3986&lt;/a&gt;. Esta postagem contém informações do documento RFC mais recente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diferença entre URL e URI
&lt;/h2&gt;

&lt;p&gt;Você provavelmente vai escutar em alguns lugares falando URL e em outros URI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um URI é um identificador para um recurso específico. Como uma página, livro ou documento&lt;/li&gt;
&lt;li&gt;A URL é tipo especial de identificador que também lhe diz como acessá-lo, como HTTPs, FTP, etc. Um exemplo seria o próprio site &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;https://marquesfernandes.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se o protocolo (HTTPS, FTP, etc.) estiver presente ou implícito para um domínio, você deve chamá-lo de URL, embora ele também seja um URI. Todos os URLs são URIs, mas nem todos os URIs são URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codificação de URL (codificação com percentual)
&lt;/h2&gt;

&lt;p&gt;Um URL é composto de um conjunto limitado de caracteres pertencentes ao conjunto de caracteres US-&lt;a href="https://marquesfernandes.com/desenvolvimento/codigo-ascii-tabela-ascii-completa/" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt;. Esses caracteres incluem dígitos (0-9), letras (AZ, az), e alguns caracteres especiais, (&lt;code&gt;"-"&lt;/code&gt;, &lt;code&gt;"."&lt;/code&gt;, &lt;code&gt;"_"&lt;/code&gt;, &lt;code&gt;"~"&lt;/code&gt;), por se tratar de US-ASCII, os caracteres permitidos não incluem os acentos como os encontrados na língua portuguesa.&lt;/p&gt;

&lt;p&gt;Existem alguns caracteres especiais que possuem um uso especial nas URLs. Alguns exemplos de caracteres reservados são &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;:&lt;/code&gt;etc. Quaisquer dados transmitidos como parte da URL, seja em consulta segmento de corda ou caminho, não deve conter esses caracteres diretamente.&lt;/p&gt;

&lt;p&gt;Além disso, caracteres perigosos como &lt;code&gt;espaço&lt;/code&gt;, &lt;code&gt;\&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt;, &lt;code&gt;}&lt;/code&gt;etc, e qualquer carácter fora do conjunto de caracteres &lt;a href="https://marquesfernandes.com/desenvolvimento/codigo-ascii-tabela-ascii-completa/" rel="noopener noreferrer"&gt;ASCII&lt;/a&gt;, não são permitidos diretamente nas URLs.&lt;/p&gt;

&lt;p&gt;Então, o que fazer quando precisamos enviar dados na URL que contenham esses caracteres não permitidos? Usamos a magia da codificação.&lt;/p&gt;

&lt;p&gt;A codificação de URL converte os caracteres reservados e inseguros em um formato compreendido por todos os navegadores e servidores da internet. Primeiro convertemos o caractere em um ou mais bytes. Então, cada byte é representado por dois dígitos hexadecimais com um prefixo de % (por exemplo &lt;code&gt;%20&lt;/code&gt;). O sinal de porcentagem é usado como um caractere de segurança.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo de codificação de URL
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Espaço:&lt;/strong&gt;  um dos caracteres codificados de URL mais frequentes que você provavelmente encontrará é um &lt;code&gt;espaço vazio&lt;/code&gt;. O valor ASCII do &lt;code&gt;espaço vazio&lt;/code&gt;caractere em decimal é &lt;code&gt;32&lt;/code&gt;, que quando convertido em hexadecimal passa a ser &lt;code&gt;20&lt;/code&gt;. Agora, adicionamos o prefixo de porcentagem ( &lt;code&gt;%&lt;/code&gt;), que nos dá o valor codificado do URL: &lt;code&gt;%20&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tabela de referência de codificação de porcentagem de caracteres ASCII
&lt;/h2&gt;

&lt;p&gt;A tabela a seguir é uma referência de caracteres ASCII para sua forma codificada de URL correspondente.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decimal&lt;/th&gt;
&lt;th&gt;Personagem&lt;/th&gt;
&lt;th&gt;Codificação de URL (UTF-8)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;NUL (caractere nulo)&lt;/td&gt;
&lt;td&gt;%00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SOH (início do cabeçalho)&lt;/td&gt;
&lt;td&gt;%01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;STX (início do texto)&lt;/td&gt;
&lt;td&gt;%02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ETX (fim do texto)&lt;/td&gt;
&lt;td&gt;%03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;EOT (fim da transmissão)&lt;/td&gt;
&lt;td&gt;%04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ENQ (inquérito)&lt;/td&gt;
&lt;td&gt;%05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ACK (reconhecer)&lt;/td&gt;
&lt;td&gt;%06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;BEL (sino)&lt;/td&gt;
&lt;td&gt;%07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;BS (retrocesso)&lt;/td&gt;
&lt;td&gt;%08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;HT (guia horizontal)&lt;/td&gt;
&lt;td&gt;%09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;LF (alimentação de linha)&lt;/td&gt;
&lt;td&gt;%0A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;VT (guia vertical)&lt;/td&gt;
&lt;td&gt;%0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;FF (alimentação de formulário)&lt;/td&gt;
&lt;td&gt;%0C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;CR (retorno de carro)&lt;/td&gt;
&lt;td&gt;%0D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;SO (mude para fora)&lt;/td&gt;
&lt;td&gt;%0E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;SI (mudança)&lt;/td&gt;
&lt;td&gt;%0F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;DLE (escape do link de dados)&lt;/td&gt;
&lt;td&gt;%10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;DC1 (controle de dispositivo 1)&lt;/td&gt;
&lt;td&gt;%11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;DC2 (controle de dispositivo 2)&lt;/td&gt;
&lt;td&gt;%12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;DC3 (controle do dispositivo 3)&lt;/td&gt;
&lt;td&gt;%13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;DC4 (controle do dispositivo 4)&lt;/td&gt;
&lt;td&gt;%14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;NAK (reconhecimento negativo)&lt;/td&gt;
&lt;td&gt;%15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;SYN (sincronizar )&lt;/td&gt;
&lt;td&gt;%16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;ETB (fim do bloco de transmissão)&lt;/td&gt;
&lt;td&gt;%17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;POSSO (cancelar)&lt;/td&gt;
&lt;td&gt;%18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;EM (fim da mídia)&lt;/td&gt;
&lt;td&gt;%19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;SUB (substituto)&lt;/td&gt;
&lt;td&gt;%1A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;ESC (escapar)&lt;/td&gt;
&lt;td&gt;%1B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;FS (separador de arquivo)&lt;/td&gt;
&lt;td&gt;%1C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;GS (separador de grupo)&lt;/td&gt;
&lt;td&gt;%1D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;RS (separador de registro)&lt;/td&gt;
&lt;td&gt;%1E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;US (separador de unidade)&lt;/td&gt;
&lt;td&gt;%1F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;espaço&lt;/td&gt;
&lt;td&gt;%20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;%21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;“&lt;/td&gt;
&lt;td&gt;%22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;#&lt;/td&gt;
&lt;td&gt;%23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;$&lt;/td&gt;
&lt;td&gt;%24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;%&lt;/td&gt;
&lt;td&gt;%25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;%26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;‘&lt;/td&gt;
&lt;td&gt;%27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;(&lt;/td&gt;
&lt;td&gt;%28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;)&lt;/td&gt;
&lt;td&gt;%29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;%2A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;%2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;,&lt;/td&gt;
&lt;td&gt;%2C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;%2D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;46&lt;/td&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;%2E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;td&gt;%2F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;%30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;%31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;%32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;%33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;%34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;%35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;%36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;%37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;%38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;%39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;:&lt;/td&gt;
&lt;td&gt;%3A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;;&lt;/td&gt;
&lt;td&gt;%3B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;&amp;lt;&lt;/td&gt;
&lt;td&gt;%3C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;td&gt;=&lt;/td&gt;
&lt;td&gt;%3D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;&amp;gt;&lt;/td&gt;
&lt;td&gt;%3E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;%3F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;@&lt;/td&gt;
&lt;td&gt;%40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;%41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;66&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;%42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;67&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;%43&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;68&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;%44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;69&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;%45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;%46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;71&lt;/td&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;%47&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;%48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;I&lt;/td&gt;
&lt;td&gt;%49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;td&gt;J&lt;/td&gt;
&lt;td&gt;%4A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;K&lt;/td&gt;
&lt;td&gt;%4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;76&lt;/td&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;%4C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;%4D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;%4E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;%4F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;P&lt;/td&gt;
&lt;td&gt;%50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;81&lt;/td&gt;
&lt;td&gt;Q&lt;/td&gt;
&lt;td&gt;%51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;82&lt;/td&gt;
&lt;td&gt;R&lt;/td&gt;
&lt;td&gt;%52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;td&gt;S&lt;/td&gt;
&lt;td&gt;%53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;84&lt;/td&gt;
&lt;td&gt;T&lt;/td&gt;
&lt;td&gt;%54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;85&lt;/td&gt;
&lt;td&gt;U&lt;/td&gt;
&lt;td&gt;%55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;86&lt;/td&gt;
&lt;td&gt;V&lt;/td&gt;
&lt;td&gt;%56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;%57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;88&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;%58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;89&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;%59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;Z&lt;/td&gt;
&lt;td&gt;%5A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;[&lt;/td&gt;
&lt;td&gt;%5B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;92&lt;/td&gt;
&lt;td&gt;\&lt;/td&gt;
&lt;td&gt;%5C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;]&lt;/td&gt;
&lt;td&gt;%5D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;^&lt;/td&gt;
&lt;td&gt;%5E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;td&gt;_&lt;/td&gt;
&lt;td&gt;%5F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;td&gt;%60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;%61&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;td&gt;b&lt;/td&gt;
&lt;td&gt;%62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;td&gt;%63&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;d&lt;/td&gt;
&lt;td&gt;%64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;e&lt;/td&gt;
&lt;td&gt;%65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;f&lt;/td&gt;
&lt;td&gt;%66&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;g&lt;/td&gt;
&lt;td&gt;%67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;h&lt;/td&gt;
&lt;td&gt;%68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;105&lt;/td&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;td&gt;%69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;106&lt;/td&gt;
&lt;td&gt;j&lt;/td&gt;
&lt;td&gt;%6A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;k&lt;/td&gt;
&lt;td&gt;%6B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;eu&lt;/td&gt;
&lt;td&gt;%6C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;m&lt;/td&gt;
&lt;td&gt;%6D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;110&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;%6E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;td&gt;o&lt;/td&gt;
&lt;td&gt;%6F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;112&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;td&gt;%70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;113&lt;/td&gt;
&lt;td&gt;q&lt;/td&gt;
&lt;td&gt;%71&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;%72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;115&lt;/td&gt;
&lt;td&gt;s&lt;/td&gt;
&lt;td&gt;%73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;116&lt;/td&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;td&gt;%74&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;td&gt;u&lt;/td&gt;
&lt;td&gt;%75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;118&lt;/td&gt;
&lt;td&gt;v&lt;/td&gt;
&lt;td&gt;%76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;119&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;%77&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;%78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;121&lt;/td&gt;
&lt;td&gt;y&lt;/td&gt;
&lt;td&gt;%79&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;122&lt;/td&gt;
&lt;td&gt;z&lt;/td&gt;
&lt;td&gt;%7A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;{&lt;/td&gt;
&lt;td&gt;%7B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;124&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;125&lt;/td&gt;
&lt;td&gt;}&lt;/td&gt;
&lt;td&gt;%7D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;~&lt;/td&gt;
&lt;td&gt;%7E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;127&lt;/td&gt;
&lt;td&gt;DEL (apagar)&lt;/td&gt;
&lt;td&gt;%7F&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/o-que-e-codificacao-de-url-e-como-funciona/" rel="noopener noreferrer"&gt;O que é codificação de URL e como funciona?&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
      <category>internet</category>
      <category>navegador</category>
      <category>uri</category>
    </item>
    <item>
      <title>Como baixar todas suas fotos marcadas no Facebook</title>
      <dc:creator>Henrique Marques Fernandes</dc:creator>
      <pubDate>Tue, 05 Jan 2021 23:06:13 +0000</pubDate>
      <link>https://dev.to/shadowlik/como-baixar-todas-suas-fotos-marcadas-no-facebook-10gh</link>
      <guid>https://dev.to/shadowlik/como-baixar-todas-suas-fotos-marcadas-no-facebook-10gh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcdd55y98yjk0knf6k47.jpg" 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%2Flcdd55y98yjk0knf6k47.jpg" width="150" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Facebook vem caindo em desuso há um tempo. Então recentemente pensei em fazer um backup de todas minhas fotos, até que me deparei com um problema: como baixar as fotos em que eu fui marcado? &lt;/p&gt;

&lt;p&gt;O Facebook agora permite que você baixe todos os dados fornecidos a ele, fotos, curtidas, publicações, contatos e muito mais, mas ele não oferece a opção de baixar suas fotos marcadas/tagged por amigos.&lt;/p&gt;

&lt;p&gt;Eu encontrei uma solução, relativamente simples, mas você vai precisar ter o Python 2 instalado para rodar um script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Baixe o script em Python: &lt;a href="https://github.com/mgjohnston/fmpd" rel="noopener noreferrer"&gt;https://github.com/mgjohnston/fmpd&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Acessa a página “Fotos com você” e role até o final dela-  &lt;a href="https://www.facebook.com/me/photos" rel="noopener noreferrer"&gt;https://www.facebook.com/me/photos&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abra o Inspecionar do Google Chrome (&lt;code&gt;ctrl + shift + i&lt;/code&gt;), ignore o aviso de segurança e executa o seguinte código:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
for (link of document.getElementsByTagName('a')) { 
  if (!link.href.includes("?fbid=")) continue; 
  console.log(new URL(link.href).searchParams.get("fbid")); 
}

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

&lt;/div&gt;



&lt;p&gt;Agora você precisa copiar todas as URLs geradas e salvar em um arquivo chamado list.txt. Não esqueça de limpar o arquivo e deixar apenas os FBIDs das fotos.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Vamos precisar agora dos cookies do Facebook para o script conseguir funcionar e acessar as fotos para baixar em seu computador. Eu recomendo que você use a extensão &lt;a href="https://chrome.google.com/webstore/detail/cookiestxt/njabckikapfpffapmjgojcnbfjonfjfg" rel="noopener noreferrer"&gt;cookies.txt para o Chrome&lt;/a&gt; e salve o arquivo como “cookies.txt” na mesma pasta em que você baixou o script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use o Python 2 para rodar o script e baixar as fotos.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python download.py

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

&lt;/div&gt;



&lt;p&gt;O post &lt;a href="https://marquesfernandes.com/tecnologia/como-baixar-todas-suas-fotos-marcadas-no-facebook/" rel="noopener noreferrer"&gt;Como baixar todas suas fotos marcadas no Facebook&lt;/a&gt; apareceu primeiro em &lt;a href="https://marquesfernandes.com" rel="noopener noreferrer"&gt;Henrique Marques Fernandes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tecnologia</category>
      <category>download</category>
      <category>facebook</category>
      <category>python</category>
    </item>
  </channel>
</rss>
