[{"data":1,"prerenderedAt":3541},["ShallowReactive",2],{"pt-BR-home-articles":3},[4,482,801,1840,2404,3214],{"id":5,"title":6,"articleCover":7,"articleCoverEmbed":8,"articleCoverEmbedUploadDate":9,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":13,"categoriesIds":466,"description":469,"enAlternateSlug":470,"extension":471,"meta":472,"navigation":473,"path":474,"ptBrAlternateSlug":475,"publishedAt":476,"seo":477,"sitemap":478,"stem":479,"updatedAt":476,"wordCount":480,"__hash__":481},"blog\u002Fblog\u002Fpor-que-javascript-se-chama-javascript.md","Por que JavaScript se chama JavaScript? A história do nome","\u002Fimages\u002Fblog\u002Fhistoria-da-programacao\u002Fpor-que-javascript-se-chama-javascript.webp","https:\u002F\u002Fwww.youtube.com\u002Fembed\u002FU1balPnfm_8","2026-11-05T12:45:30-03:00",720,1280,"thiago-nunes-batista",{"type":14,"value":15,"toc":453},"minimark",[16,20,23,28,40,49,53,67,70,83,86,116,128,132,139,146,150,161,215,226,250,253,257,264,277,280,284,293,308,311,339,351,355,358,367,371,449],[17,18,19],"p",{},"JavaScript não é Java, não é uma versão do Java e não foi feita pela empresa do Java. Mesmo assim, quase todo iniciante em programação tropeça nessa pergunta: se as duas linguagens não têm relação, por que o nome é tão parecido?",[17,21,22],{},"A resposta passa por uma disputa entre navegadores, por um protótipo escrito às pressas em 1995 e por uma marca registrada que, mais de 30 anos depois, ainda está no meio de um processo. Se preferir assistir, o vídeo acima conta essa história em quatro minutos. Aqui o texto vai mais fundo, com datas, comparações e as fontes.",[24,25,27],"h2",{"id":26},"por-que-a-netscape-precisava-de-uma-linguagem-para-o-navegador","Por que a Netscape precisava de uma linguagem para o navegador?",[17,29,30,31,39],{},"Em 1995, o Netscape Navigator era o navegador mais usado da internet, e a Microsoft estava chegando com o Internet Explorer. Esse período ficou conhecido como a ",[32,33,38],"a",{"href":34,"rel":35,"target":37},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBrowser_wars",[36],"nofollow","_blank","guerra dos navegadores",". Para ficar na frente, a Netscape queria páginas que reagissem ao que a pessoa fazia, em vez de só exibir texto e imagem.",[17,41,42,43,48],{},"Isso exigia uma linguagem de script, ou seja, uma linguagem simples para escrever pequenos programas que rodam dentro da própria página. A Netscape contratou ",[32,44,47],{"href":45,"rel":46,"target":37},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJavaScript#History",[36],"Brendan Eich"," para colocar o Scheme, uma linguagem de origem acadêmica, dentro do navegador. Só que a diretoria mudou o pedido: a nova linguagem deveria ter uma sintaxe parecida com a do Java, que estava em alta. E o prazo era curtíssimo.",[24,50,52],{"id":51},"quanto-tempo-brendan-eich-levou-para-criar-o-javascript","Quanto tempo Brendan Eich levou para criar o JavaScript?",[17,54,55,56,61,62,66],{},"A primeira versão saiu em cerca de ",[32,57,60],{"href":58,"rel":59,"target":37},"https:\u002F\u002Fbuttondown.com\u002Fhillelwayne\u002Farchive\u002Fdid-brendan-eich-really-make-javascript-in-10-days\u002F",[36],"10 dias",", em maio de 1995. O protótipo se chamava ",[63,64,65],"strong",{},"Mocha"," e era para ser apenas uma demonstração interna.",[17,68,69],{},"Vale uma ressalva. Os 10 dias valem para o protótipo, não para a linguagem como a conhecemos. Ela foi se ajustando nos meses seguintes e continuou evoluindo por décadas. Mas a pressa daquele começo explica várias esquisitices que sobrevivem até hoje.",[24,71,73,74,78,79,82],{"id":72},"por-que-typeof-null-retorna-object","Por que ",[75,76,77],"code",{},"typeof null"," retorna ",[75,80,81],{},"\"object\"","?",[17,84,85],{},"O exemplo mais famoso dessas marcas está no console de qualquer navegador:",[87,88,93],"pre",{"className":89,"code":90,"language":91,"meta":92,"style":92},"language-js shiki shiki-themes dracula","typeof null; \u002F\u002F \"object\"\n","js","",[75,94,95],{"__ignoreMap":92},[96,97,100,104,108,112],"span",{"class":98,"line":99},"line",1,[96,101,103],{"class":102},"s0Tla","typeof",[96,105,107],{"class":106},"sIQBb"," null",[96,109,111],{"class":110},"sCdxs","; ",[96,113,115],{"class":114},"shSDL","\u002F\u002F \"object\"\n",[17,117,118,121,122,127],{},[75,119,120],{},"null"," não é um objeto. Esse resultado é um ",[32,123,126],{"href":124,"rel":125,"target":37},"https:\u002F\u002Falexanderell.is\u002Fposts\u002Ftypeof-null\u002F",[36],"bug da primeira implementação",", ligado à etiqueta de tipo que a linguagem usava para identificar objetos. Ele nunca foi corrigido porque consertar hoje quebraria código que já existe e depende desse comportamento. Houve uma proposta de correção, e ela foi recusada justamente por isso.",[24,129,131],{"id":130},"de-mocha-a-livescript-e-javascript-como-o-nome-mudou-duas-vezes","De Mocha a LiveScript e JavaScript: como o nome mudou duas vezes",[17,133,134,135,138],{},"Em setembro de 1995, a linguagem apareceu numa versão beta do Navigator 2.0 já com outro nome, ",[63,136,137],{},"LiveScript",". Naquele momento o Java da Sun Microsystems era a linguagem mais comentada do mundo, e a Netscape tinha acabado de fechar uma parceria com a Sun.",[17,140,141,142,145],{},"Em dezembro de 1995, as duas empresas anunciaram juntas que o LiveScript passaria a se chamar ",[63,143,144],{},"JavaScript",". O próprio Brendan Eich descreveu a troca como uma jogada de marketing da Netscape, para aproveitar a fama do Java. Funcionou: o nome pegou. Também criou uma confusão que dura até hoje.",[24,147,149],{"id":148},"java-e-javascript-são-a-mesma-coisa","Java e JavaScript são a mesma coisa?",[17,151,152,153,156,157,160],{},"Não. Olhando o código, as duas parecem primas: chaves, ponto e vírgula, ",[75,154,155],{},"if"," e ",[75,158,159],{},"for",". Por dentro, são bem diferentes.",[162,163,164,178],"table",{},[165,166,167],"thead",{},[168,169,170,173,176],"tr",{},[171,172],"th",{},[171,174,175],{},"Java",[171,177,144],{},[179,180,181,193,204],"tbody",{},[168,182,183,187,190],{},[184,185,186],"td",{},"Execução",[184,188,189],{},"Compilado, roda na máquina virtual (JVM)",[184,191,192],{},"Nasceu para rodar dentro do navegador",[168,194,195,198,201],{},[184,196,197],{},"Tipos",[184,199,200],{},"Você declara o tipo de cada variável",[184,202,203],{},"O tipo é decidido na hora, durante a execução",[168,205,206,209,212],{},[184,207,208],{},"Herança",[184,210,211],{},"Baseada em classes",[184,213,214],{},"Baseada em protótipos",[87,216,220],{"className":217,"code":218,"language":219,"meta":92,"style":92},"language-java shiki shiki-themes dracula","int idade = 30; \u002F\u002F Java: o tipo é obrigatório\n","java",[75,221,222],{"__ignoreMap":92},[96,223,224],{"class":98,"line":99},[96,225,218],{},[87,227,229],{"className":89,"code":228,"language":91,"meta":92,"style":92},"let idade = 30; \u002F\u002F JavaScript: o tipo vem do valor\n",[75,230,231],{"__ignoreMap":92},[96,232,233,236,239,242,245,247],{"class":98,"line":99},[96,234,235],{"class":102},"let",[96,237,238],{"class":110}," idade ",[96,240,241],{"class":102},"=",[96,243,244],{"class":106}," 30",[96,246,111],{"class":110},[96,248,249],{"class":114},"\u002F\u002F JavaScript: o tipo vem do valor\n",[17,251,252],{},"A relação entre as duas é a mesma que existe entre pão e pão-duro: o começo da palavra é igual, e a semelhança acaba aí. O nome parecido virou um problema para a concorrência, e foi isso que levou a Microsoft a fazer o movimento seguinte.",[24,254,256],{"id":255},"o-que-são-jscript-e-ecmascript","O que são JScript e ECMAScript?",[17,258,259,260,263],{},"Quando a Microsoft quis a mesma linguagem no Internet Explorer, não podia usar o nome JavaScript, porque a marca pertencia à Sun. Em 1996, lançou no Internet Explorer 3 uma versão própria chamada ",[63,261,262],{},"JScript",", com diferenças em relação à da Netscape. Duas versões diferentes da mesma linguagem eram receita de site quebrado.",[17,265,266,267,270,271,276],{},"Para resolver, a Netscape levou a linguagem à Ecma, uma organização de padrões, em novembro de 1996. A primeira edição do padrão, o ECMA-262, saiu em junho de 1997, com um nome que ninguém queria: ",[63,268,269],{},"ECMAScript",". O nome foi um meio-termo político entre as empresas envolvidas. Brendan Eich chegou a dizer, ",[32,272,275],{"href":273,"rel":274,"target":37},"https:\u002F\u002Fbugzilla.mozilla.org\u002Fshow_bug.cgi?id=44841",[36],"num comentário no Bugzilla da Mozilla",", que ele soava como doença de pele.",[17,278,279],{},"É daí que vem o \"ES\" de ES6, que é o ECMAScript 2015, publicado em junho de 2015. De lá para cá, o padrão ganhou uma edição por ano. O padrão resolveu a confusão técnica, mas não a questão da marca.",[24,281,283],{"id":282},"de-quem-é-o-nome-javascript-hoje","De quem é o nome JavaScript hoje?",[17,285,286,287,292],{},"A marca \"JavaScript\" foi registrada pela Sun. Quando a Oracle ",[32,288,291],{"href":289,"rel":290,"target":37},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSun_acquisition_by_Oracle",[36],"comprou a Sun",", em janeiro de 2010, ela herdou o registro. A Oracle não vende nenhum produto chamado JavaScript.",[17,294,295,296,301,302,307],{},"Em setembro de 2024, uma ",[32,297,300],{"href":298,"rel":299,"target":37},"https:\u002F\u002Fdeno.com\u002Fblog\u002Fjavascript-tm-gofundme",[36],"carta aberta"," liderada por Ryan Dahl, criador do Node.js e da Deno, pediu que a Oracle liberasse o nome. Passou de 14 mil assinaturas, incluindo a de Brendan Eich. A Oracle recusou, e em novembro de 2024 a Deno ",[32,303,306],{"href":304,"rel":305,"target":37},"https:\u002F\u002Fdeno.com\u002Fblog\u002Fdeno-v-oracle3",[36],"pediu ao USPTO",", o escritório de marcas dos Estados Unidos, o cancelamento do registro.",[17,309,310],{},"O processo andou assim:",[312,313,314,324,333,336],"ul",{},[315,316,317,318,323],"li",{},"Em junho de 2025, o tribunal de marcas (TTAB) ",[32,319,322],{"href":320,"rel":321,"target":37},"https:\u002F\u002Fdeno.com\u002Fblog\u002Fdeno-v-oracle4",[36],"rejeitou a alegação de fraude"," da Deno. Ficaram de pé os argumentos de que o nome é genérico e de que a marca foi abandonada.",[315,325,326,327,332],{},"Em agosto de 2025, a Oracle ",[32,328,331],{"href":329,"rel":330,"target":37},"https:\u002F\u002Fwww.infoworld.com\u002Farticle\u002F3818005\u002Foracle-maintains-hold-on-javascript-trademark.html",[36],"apresentou sua resposta",", negando esses argumentos.",[315,334,335],{},"Ao longo de 2026, as partes pediram prorrogações de prazo em sequência.",[315,337,338],{},"Em 28 de agosto de 2026, o processo foi suspenso a pedido da Oracle, com consentimento da Deno, enquanto as duas partes negociam um acordo.",[17,340,341,344,345,350],{},[63,342,343],{},"Status conferido em 5 de novembro de 2026:"," no ",[32,346,349],{"href":347,"rel":348,"target":37},"https:\u002F\u002Fttabvue.uspto.gov\u002Fttabvue\u002Fv?pno=92086835&pty=CAN",[36],"registro público do TTAB"," (processo 92086835), o caso continua suspenso para negociação de acordo, sem decisão final. O texto vai ficar desatualizado se isso mudar, então vale olhar o link nas fontes.",[24,352,354],{"id":353},"resumindo","Resumindo",[17,356,357],{},"JavaScript se chama JavaScript por marketing. Em dezembro de 1995, a Netscape trocou o nome LiveScript para pegar carona no sucesso do Java, numa parceria com a Sun. As linguagens são diferentes por dentro, e o nome emprestado nunca foi devolvido: hoje a marca é da Oracle, que herdou o registro da Sun, e o futuro do nome está num processo suspenso para negociação.",[17,359,360,361,366],{},"Este artigo faz parte da série ",[32,362,365],{"href":363,"rel":364},"https:\u002F\u002Fwww.youtube.com\u002Fplaylist?list=PLUhXtxqxMwPw",[36],"O nome por trás do código",", no canal do YouTube.",[24,368,370],{"id":369},"fontes","Fontes",[312,372,373,380,387,394,401,408,414,421,428,435,442],{},[315,374,375,379],{},[32,376,144],{"href":377,"rel":378,"target":37},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJavaScript",[36]," (Wikipedia, seção History)",[315,381,382,386],{},[32,383,385],{"href":34,"rel":384,"target":37},[36],"Browser wars"," (Wikipedia)",[315,388,389,393],{},[32,390,392],{"href":58,"rel":391,"target":37},[36],"Did Brendan Eich really make JavaScript in 10 days?"," (Hillel Wayne)",[315,395,396,400],{},[32,397,399],{"href":124,"rel":398,"target":37},[36],"typeof null: investigating a classic JavaScript bug"," (alexanderell.is)",[315,402,403,407],{},[32,404,406],{"href":273,"rel":405,"target":37},[36],"Comentário de Brendan Eich sobre o nome ECMAScript"," (Bugzilla da Mozilla, 2006)",[315,409,410,386],{},[32,411,413],{"href":289,"rel":412,"target":37},[36],"Sun acquisition by Oracle",[315,415,416,420],{},[32,417,419],{"href":298,"rel":418,"target":37},[36],"Help us raise $200k to free the JavaScript trademark"," (Deno, 2024)",[315,422,423,427],{},[32,424,426],{"href":304,"rel":425,"target":37},[36],"Deno v Oracle Update 3"," (Deno, 2025)",[315,429,430,434],{},[32,431,433],{"href":320,"rel":432,"target":37},[36],"JavaScript Trademark Update"," (Deno, junho de 2025)",[315,436,437,441],{},[32,438,440],{"href":329,"rel":439,"target":37},[36],"Oracle maintains hold on JavaScript trademark"," (InfoWorld, 2025)",[315,443,444,448],{},[32,445,447],{"href":347,"rel":446,"target":37},[36],"Cancelamento 92086835, Deno Land Inc. × Oracle America, Inc."," (TTABVUE, USPTO), consultado em 5 de novembro de 2026",[450,451,452],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s0Tla, html code.shiki .s0Tla{--shiki-default:#FF79C6}html pre.shiki code .sIQBb, html code.shiki .sIQBb{--shiki-default:#BD93F9}html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .shSDL, html code.shiki .shSDL{--shiki-default:#6272A4}",{"title":92,"searchDepth":454,"depth":454,"links":455},2,[456,457,458,460,461,462,463,464,465],{"id":26,"depth":454,"text":27},{"id":51,"depth":454,"text":52},{"id":72,"depth":454,"text":459},"Por que typeof null retorna \"object\"?",{"id":130,"depth":454,"text":131},{"id":148,"depth":454,"text":149},{"id":255,"depth":454,"text":256},{"id":282,"depth":454,"text":283},{"id":353,"depth":454,"text":354},{"id":369,"depth":454,"text":370},[467,468],"historia-da-programacao","javascript","JavaScript não tem nada a ver com Java. Veja como a guerra dos navegadores, 10 dias de pressa e um acordo com a Sun em 1995 deram esse nome à linguagem.","why-is-javascript-called-javascript","md",{},true,"\u002Fblog\u002Fpor-que-javascript-se-chama-javascript","por-que-javascript-se-chama-javascript","2026-11-05",{"title":6,"description":469},{"loc":474,"lastmod":476},"blog\u002Fpor-que-javascript-se-chama-javascript",1307,"-dzW5RaQPbbfD4jCmdHPB8piEF01dXgvzHvgxV69Ot8",{"id":483,"title":484,"articleCover":485,"articleCoverEmbed":486,"articleCoverEmbedUploadDate":486,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":487,"categoriesIds":790,"description":791,"enAlternateSlug":792,"extension":471,"meta":793,"navigation":473,"path":794,"ptBrAlternateSlug":795,"publishedAt":476,"seo":796,"sitemap":797,"stem":798,"updatedAt":476,"wordCount":799,"__hash__":800},"blog\u002Fblog\u002Fpor-que-linux-se-chama-linux.md","Por que Linux se chama Linux? A história do nome Freax, Unix e GNU","\u002Fimages\u002Fblog\u002Fhistoria-da-programacao\u002Fpor-que-linux-se-chama-linux.webp",null,{"type":14,"value":488,"toc":778},[489,492,495,499,512,515,519,531,538,542,558,561,565,572,585,592,603,612,616,623,632,636,649,653,656,665,668,672,681,683,689,695,697,775],[17,490,491],{},"O Linux está no seu Android, por trás de quase todo site e nos supercomputadores mais rápidos do mundo. Mesmo assim, o criador dele não queria esse nome. Linus Torvalds achava \"Linux\" egocêntrico demais e escolheu outro: Freax.",[17,493,494],{},"Então como o nome Linux foi parar no projeto? A resposta envolve um sistema dos anos 1960, um professor que ficou bravo, um voluntário que mexeu numa pasta de servidor na Finlândia e uma disputa de marca registrada.",[24,496,498],{"id":497},"de-onde-vem-o-x-do-nome-linux","De onde vem o \"x\" do nome Linux?",[17,500,501,502,505,506,511],{},"O \"x\" vem do ",[63,503,504],{},"Unix",", um sistema operacional criado em 1969 na Bell Labs (AT&T) por Ken Thompson, Dennis Ritchie e colegas, segundo a ",[32,507,510],{"href":508,"rel":509},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHistory_of_Unix",[36],"história do Unix",". Um sistema operacional é o programa que faz o computador funcionar, como o Windows. O nome Unix, que antes era \"Unics\", foi um trocadilho com o Multics, um sistema grande e complicado do qual a Bell Labs tinha saído.",[17,513,514],{},"O Unix foi um sucesso, mas a AT&T licenciava o código, as licenças ficaram caras e ninguém podia redistribuí-lo livremente. A imagem que uso no vídeo é a de um carro alugado, caro e com o capô trancado. O \"x\" virou uma espécie de sobrenome dos sistemas inspirados nele: Minix, Linux e vários outros.",[24,516,518],{"id":517},"o-que-é-o-gnu-e-por-que-ele-não-tinha-kernel","O que é o GNU e por que ele não tinha kernel?",[17,520,521,522,530],{},"Em 27 de setembro de 1983, Richard Stallman ",[32,523,526,527],{"href":524,"rel":525},"https:\u002F\u002Fwww.gnu.org\u002Fgnu\u002Finitial-announcement.html",[36],"anunciou o projeto ",[63,528,529],{},"GNU",", com a ideia de montar um sistema livre, que qualquer pessoa pudesse abrir, estudar e modificar. O nome é uma brincadeira: GNU quer dizer \"GNU's Not Unix\" (GNU não é Unix), uma sigla que tem ela mesma dentro.",[17,532,533,534,537],{},"Em 1991 o GNU já tinha quase tudo de um sistema completo: o compilador GCC (1987), que traduz código em programa, o editor Emacs e o shell Bash (1989). Faltava o ",[63,535,536],{},"kernel",", o núcleo que conversa com as peças do computador (memória, disco, teclado). O kernel do GNU, o Hurd, ainda não estava pronto. Na metáfora do carro, o GNU tinha montado quase tudo, mas faltava o motor.",[24,539,541],{"id":540},"quem-criou-o-linux-e-por-quê","Quem criou o Linux e por quê?",[17,543,544,545,552,553,557],{},"O motor veio de onde ninguém esperava. Em janeiro de 1991, Linus Torvalds, um estudante de 21 anos da Universidade de Helsinque, comprou um PC com processador 386. Ele usava o ",[32,546,549],{"href":547,"rel":548},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMinix",[36],[63,550,551],{},"Minix",", um sistema que o professor Andrew Tanenbaum ",[32,554,556],{"href":547,"rel":555},[36],"criou em 1987"," para dar aula e cuja licença restringia a redistribuição.",[17,559,560],{},"Incomodado com as limitações, Linus começou a escrever o próprio kernel, só por diversão. Em 25 de agosto de 1991 ele avisou no grupo comp.os.minix, um fórum da época, que estava fazendo um sistema operacional livre e que era só um hobby, sem a pretensão de ficar grande e profissional como o GNU. Faltava só uma coisa para publicar o código: um nome.",[24,562,564],{"id":563},"por-que-o-linux-quase-se-chamou-freax","Por que o Linux quase se chamou Freax?",[17,566,567,568,571],{},"O nome que Linus queria era ",[63,569,570],{},"Freax",", uma mistura de \"free\" (livre), \"freak\" (esquisito) e o \"x\" do Unix. Ele chegou a pensar em \"Linux\", mas achou o nome metido demais, porque ia carregar o primeiro nome dele.",[17,573,574,575,580,581,584],{},"Em setembro de 1991 ele mandou o código para o servidor ftp.funet.fi (a ",[32,576,579],{"href":577,"rel":578},"https:\u002F\u002Flinuxiac.com\u002Flinux-birthday\u002F",[36],"história está no Linuxiac","), o computador onde as universidades finlandesas deixavam programas para baixar. Ari Lemmke, um dos administradores voluntários do servidor, não gostou de \"Freax\" e criou a pasta com outro nome: ",[75,582,583],{},"linux",". A versão 0.01 foi publicada ali dentro, em 17 de setembro de 1991. Linus não brigou pelo nome, e ele pegou.",[17,586,587,588,591],{},"O Freax não sumiu por completo. Ele ficou num comentário do ",[75,589,590],{},"Makefile"," do kernel daquela primeira versão:",[87,593,597],{"className":594,"code":595,"language":596,"meta":92,"style":92},"language-makefile shiki shiki-themes dracula","# Makefile for the FREAX-kernel.\n","makefile",[75,598,599],{"__ignoreMap":92},[96,600,601],{"class":98,"line":99},[96,602,595],{},[17,604,605,606,611],{},"Conferi esse trecho em 5 de novembro de 2026 numa cópia da versão 0.01. Linus também ",[32,607,610],{"href":608,"rel":609},"https:\u002F\u002Fcommons.wikimedia.org\u002Fwiki\u002FFile:Linus-linux.ogg",[36],"gravou um áudio"," explicando como pronuncia o nome (algo como \"Línux\", com \"i\" curto), que circulou junto com o código.",[24,613,615],{"id":614},"o-que-foi-a-briga-entre-tanenbaum-e-torvalds","O que foi a briga entre Tanenbaum e Torvalds?",[17,617,618,619,622],{},"Junto com o nome veio a primeira briga pública. Em janeiro de 1992, o professor que criou o Minix publicou uma mensagem com o título \"LINUX is obsolete\" (o Linux é ultrapassado). O argumento técnico era que um kernel moderno deveria ser um ",[63,620,621],{},"microkernel",", um motor de peças separadas, e o do Linux era monolítico, um bloco só. Tanenbaum ainda brincou que, se Linus fosse aluno dele, não tiraria nota alta.",[17,624,625,626,631],{},"Essa discussão ficou conhecida como o ",[32,627,630],{"href":628,"rel":629},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTanenbaum%E2%80%93Torvalds_debate",[36],"debate Tanenbaum–Torvalds",". Enquanto ela acontecia, o Linux mudou de licença: passou a usar a GPL, a licença do GNU que deixa qualquer um usar, mudar e repassar o código, a partir da versão 0.12, em 1992. Antes disso a licença própria proibia uso comercial. Com a GPL, o kernel de Linus encaixou no sistema do GNU, e o carro finalmente andou.",[24,633,635],{"id":634},"linux-ou-gnulinux","Linux ou GNU\u002FLinux?",[17,637,638,639,644,645,648],{},"Como o sistema que as pessoas usam é a soma do kernel com as ferramentas do GNU, a Free Software Foundation e Richard Stallman ",[32,640,643],{"href":641,"rel":642},"https:\u002F\u002Fwww.gnu.org\u002Fgnu\u002Fgnu-linux-faq.html",[36],"pedem"," até hoje que o sistema completo seja chamado de ",[63,646,647],{},"GNU\u002FLinux",". Na prática, a maioria das pessoas diz só Linux, e \"Linux\" tecnicamente nomeia o kernel. As duas formas aparecem em livros e distribuições, e a escolha é questão de preferência.",[24,650,652],{"id":651},"de-quem-é-a-marca-linux","De quem é a marca Linux?",[17,654,655],{},"A briga mais perigosa pelo nome veio de fora. Em 1995, um americano chamado William R. Della Croce Jr. registrou \"Linux\" como marca nos Estados Unidos sem ter escrito uma linha do código e passou a cobrar 10% de royalties de quem vendia o Linux em CD. A comunidade e algumas empresas foram à justiça, e em 1997 a marca foi transferida para Linus Torvalds.",[17,657,658,659,664],{},"Conferi em 5 de novembro de 2026: segundo a ",[32,660,663],{"href":661,"rel":662},"https:\u002F\u002Fwww.linuxfoundation.org\u002Flegal\u002Fthe-linux-mark",[36],"Linux Foundation",", Linus continua sendo o dono da marca no mundo todo, e a fundação é a licenciada exclusiva que administra os sublicenciamentos. O nome que ele achava metido demais é dele, por lei.",[17,666,667],{},"O Unix também é marca registrada, da The Open Group, que mantém uma certificação própria. Quase nenhuma distribuição Linux tem o selo, embora haja exceções, como o EulerOS, da Huawei.",[24,669,671],{"id":670},"e-depois-do-linux","E depois do Linux?",[17,673,674,675,680],{},"Catorze anos depois do Linux, em abril de 2005, Linus criou outra ferramenta e dessa vez escolheu o nome sozinho: ",[32,676,679],{"href":677,"rel":678},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGit",[36],"Git",". A história desse nome é o próximo episódio da série.",[24,682,354],{"id":353},[17,684,685,686,688],{},"O Linux tem esse nome porque quem administrava o servidor onde ele foi publicado não gostou de Freax e criou a pasta ",[75,687,583],{},". Linus Torvalds achava o nome metido demais, mas ele pegou, e o \"x\" ligou o sistema à família Unix. O nome ainda passou por uma tentativa de registro por um terceiro e voltou para Linus em 1997. Hoje ele é dono da marca, e a Linux Foundation cuida dela.",[17,690,360,691,694],{},[32,692,365],{"href":363,"rel":693},[36],", no canal Código ao Ponto.",[24,696,370],{"id":369},[312,698,699,705,712,724,731,736,742,749,756,763,770],{},[315,700,701,386],{},[32,702,704],{"href":508,"rel":703},[36],"History of Unix",[315,706,707,711],{},[32,708,710],{"href":524,"rel":709},[36],"Initial announcement of the GNU project"," (gnu.org, 1983)",[315,713,714,156,719,723],{},[32,715,718],{"href":716,"rel":717},"https:\u002F\u002Fwww.gnu.org\u002Fgnu\u002Flinux-and-gnu.html",[36],"Linux and the GNU System",[32,720,722],{"href":641,"rel":721},[36],"GNU\u002FLinux FAQ"," (gnu.org)",[315,725,726,386],{},[32,727,730],{"href":728,"rel":729},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHistory_of_Linux",[36],"History of Linux",[315,732,733,386],{},[32,734,551],{"href":547,"rel":735},[36],[315,737,738,386],{},[32,739,741],{"href":628,"rel":740},[36],"Tanenbaum–Torvalds debate",[315,743,744,748],{},[32,745,747],{"href":577,"rel":746},[36],"Linux's real birthday"," (Linuxiac), com o comentário do Makefile",[315,750,751,386],{},[32,752,755],{"href":753,"rel":754},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLinux#Trademark",[36],"Linux, seção Trademark",[315,757,758,762],{},[32,759,761],{"href":661,"rel":760},[36],"The Linux Mark"," (Linux Foundation, conferido em 5\u002F11\u002F2026)",[315,764,765,769],{},[32,766,768],{"href":608,"rel":767},[36],"Linus-linux.ogg"," (Wikimedia Commons)",[315,771,772,386],{},[32,773,679],{"href":677,"rel":774},[36],[450,776,777],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":92,"searchDepth":454,"depth":454,"links":779},[780,781,782,783,784,785,786,787,788,789],{"id":497,"depth":454,"text":498},{"id":517,"depth":454,"text":518},{"id":540,"depth":454,"text":541},{"id":563,"depth":454,"text":564},{"id":614,"depth":454,"text":615},{"id":634,"depth":454,"text":635},{"id":651,"depth":454,"text":652},{"id":670,"depth":454,"text":671},{"id":353,"depth":454,"text":354},{"id":369,"depth":454,"text":370},[467],"Linus Torvalds queria chamar o Linux de Freax. Veja por que o nome mudou, o que o x tem a ver com o Unix e como a marca Linux foi parar nas mãos dele.","why-is-linux-called-linux",{},"\u002Fblog\u002Fpor-que-linux-se-chama-linux","por-que-linux-se-chama-linux",{"title":484,"description":791},{"loc":794,"lastmod":476},"blog\u002Fpor-que-linux-se-chama-linux",1275,"-uZcHclwzozROvRu5Wv0Um1MtJAUYRFPbzuhk84_05g",{"id":802,"title":803,"articleCover":804,"articleCoverEmbed":486,"articleCoverEmbedUploadDate":486,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":805,"categoriesIds":1826,"description":1829,"enAlternateSlug":1830,"extension":471,"meta":1831,"navigation":473,"path":1832,"ptBrAlternateSlug":1833,"publishedAt":1834,"seo":1835,"sitemap":1836,"stem":1837,"updatedAt":1834,"wordCount":1838,"__hash__":1839},"blog\u002Fblog\u002Fvue-vapor-mode-como-funciona-e-como-usar.md","Vue Vapor Mode: o que é e o que muda no Vue 3.6","\u002Fimages\u002Fblog\u002Fvue\u002Fvue-vapor-mode-como-funciona-e-como-usar.webp",{"type":14,"value":806,"toc":1800},[807,822,829,833,836,839,842,847,874,878,889,1051,1058,1073,1077,1088,1158,1161,1165,1171,1228,1237,1241,1247,1299,1313,1316,1379,1390,1393,1397,1400,1461,1470,1477,1480,1487,1500,1535,1542,1546,1549,1665,1681,1685,1688,1695,1699,1702,1705,1722,1726,1730,1733,1737,1745,1749,1754,1758,1767,1771,1774,1778,1790,1794,1797],[17,808,809,810,813,814,817,818,821],{},"O Vue 3.6 ainda não saiu como versão estável. Em 6 de outubro de 2026, a versão mais recente é a ",[75,811,812],{},"3.6.0-rc.10"," (30 de setembro), e a estável continua sendo a ",[75,815,816],{},"3.5.43"," (17 de setembro). Confirmei isso no npm e nas releases do repositório ",[75,819,820],{},"vuejs\u002Fcore"," nesta data.",[17,823,824,825,828],{},"O ",[63,826,827],{},"Vue Vapor Mode"," é a principal novidade dessa versão: um modo de compilação que dispensa o Virtual DOM e gera código que atualiza o DOM diretamente. Ele é opt-in, então você escolhe componente a componente onde usar, sem reescrever o app. Neste artigo você vê como o Vapor funciona, como ativar no Vue e no Nuxt 4.6, o que ainda não é suportado e quando vale a pena testar.",[24,830,832],{"id":831},"como-o-vapor-funciona","Como o Vapor funciona",[17,834,835],{},"No modo tradicional, quando um estado reativo muda, o Vue executa a função de renderização, monta uma nova árvore de VNodes (objetos JavaScript que descrevem a interface), compara com a árvore anterior e só então altera o DOM real.",[17,837,838],{},"No Vapor Mode, o compilador analisa o template e gera código que manipula o DOM diretamente. Os componentes Vapor não criam VNodes nem comparam árvores em tempo de execução. Quando uma variável reativa muda, só o trecho do DOM ligado a ela é atualizado.",[17,840,841],{},"Segundo as notas oficiais do Vue 3.6, o objetivo é reduzir o tamanho base do bundle e melhorar a performance. As mesmas notas dizem que o Vapor mostrou, em benchmarks de terceiros (o js-framework-benchmark), o mesmo nível de performance do Solid e do Svelte 5. Como em qualquer benchmark, o resultado depende do cenário medido.",[843,844,846],"h3",{"id":845},"e-o-alien-signals","E o Alien Signals?",[17,848,849,850,853,854,859,860,863,864,863,867,156,870,873],{},"O Vue 3.6 também traz uma refatoração grande do ",[75,851,852],{},"@vue\u002Freactivity",", baseada na biblioteca ",[32,855,858],{"href":856,"rel":857},"https:\u002F\u002Fgithub.com\u002Fstackblitz\u002Falien-signals",[36],"alien-signals",". Segundo as notas do rc.1, ela melhora o desempenho e o uso de memória do sistema de reatividade. É uma mudança interna: ",[75,861,862],{},"ref",", ",[75,865,866],{},"reactive",[75,868,869],{},"computed",[75,871,872],{},"watch"," continuam com a mesma API. Como ela faz parte do Vue 3.6, o benefício não depende de você usar o Vapor.",[24,875,877],{"id":876},"como-ativar-o-vapor-mode","Como ativar o Vapor Mode",[17,879,880,881,884,885,888],{},"O Vapor funciona com SFCs que usam ",[75,882,883],{},"\u003Cscript setup>"," ou só template. Você marca o componente com o atributo ",[75,886,887],{},"vapor",":",[87,890,894],{"className":891,"code":892,"language":893,"meta":92,"style":92},"language-vue shiki shiki-themes dracula","\u003Cscript setup vapor lang=\"ts\">\nimport { ref } from 'vue'\n\nconst count = ref(0)\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cbutton @click=\"count++\">\n    count is {{ count }}\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n","vue",[75,895,896,929,948,954,978,988,993,1003,1026,1032,1042],{"__ignoreMap":92},[96,897,898,901,904,908,911,914,916,920,924,926],{"class":98,"line":99},[96,899,900],{"class":110},"\u003C",[96,902,903],{"class":102},"script",[96,905,907],{"class":906},"sY_PY"," setup",[96,909,910],{"class":906}," vapor",[96,912,913],{"class":906}," lang",[96,915,241],{"class":102},[96,917,919],{"class":918},"seVfx","\"",[96,921,923],{"class":922},"s-mGx","ts",[96,925,919],{"class":918},[96,927,928],{"class":110},">\n",[96,930,931,934,937,940,943,945],{"class":98,"line":454},[96,932,933],{"class":102},"import",[96,935,936],{"class":110}," { ref } ",[96,938,939],{"class":102},"from",[96,941,942],{"class":918}," '",[96,944,893],{"class":922},[96,946,947],{"class":918},"'\n",[96,949,951],{"class":98,"line":950},3,[96,952,953],{"emptyLinePlaceholder":473},"\n",[96,955,957,960,963,965,969,972,975],{"class":98,"line":956},4,[96,958,959],{"class":102},"const",[96,961,962],{"class":110}," count ",[96,964,241],{"class":102},[96,966,968],{"class":967},"sAOxA"," ref",[96,970,971],{"class":110},"(",[96,973,974],{"class":106},"0",[96,976,977],{"class":110},")\n",[96,979,981,984,986],{"class":98,"line":980},5,[96,982,983],{"class":110},"\u003C\u002F",[96,985,903],{"class":102},[96,987,928],{"class":110},[96,989,991],{"class":98,"line":990},6,[96,992,953],{"emptyLinePlaceholder":473},[96,994,996,998,1001],{"class":98,"line":995},7,[96,997,900],{"class":110},[96,999,1000],{"class":102},"template",[96,1002,928],{"class":110},[96,1004,1006,1009,1012,1015,1017,1019,1022,1024],{"class":98,"line":1005},8,[96,1007,1008],{"class":110},"  \u003C",[96,1010,1011],{"class":102},"button",[96,1013,1014],{"class":906}," @click",[96,1016,241],{"class":102},[96,1018,919],{"class":918},[96,1020,1021],{"class":922},"count++",[96,1023,919],{"class":918},[96,1025,928],{"class":110},[96,1027,1029],{"class":98,"line":1028},9,[96,1030,1031],{"class":110},"    count is {{ count }}\n",[96,1033,1035,1038,1040],{"class":98,"line":1034},10,[96,1036,1037],{"class":110},"  \u003C\u002F",[96,1039,1011],{"class":102},[96,1041,928],{"class":110},[96,1043,1045,1047,1049],{"class":98,"line":1044},11,[96,1046,983],{"class":110},[96,1048,1000],{"class":102},[96,1050,928],{"class":110},[17,1052,1053,1054,1057],{},"Fora do Nuxt, o ",[75,1055,1056],{},"@vitejs\u002Fplugin-vue"," compila SFCs Vapor (o changelog do plugin registra suporte a componentes Vapor, inclusive só com template), então use uma versão recente.",[17,1059,1060,1061,1064,1065,1068,1069,1072],{},"O Vue também aceita ",[75,1062,1063],{},"\u003Cscript vapor>"," como atalho de ",[75,1066,1067],{},"\u003Cscript setup vapor>",". Outra opção é colocar o marcador no template, com ",[75,1070,1071],{},"\u003Ctemplate vapor>",", para compilar o SFC inteiro em modo Vapor.",[843,1074,1076],{"id":1075},"componentes-vapor-em-um-app-existente","Componentes Vapor em um app existente",[17,1078,1079,1080,1083,1084,1087],{},"Num app criado com ",[75,1081,1082],{},"createApp()",", é preciso instalar o ",[75,1085,1086],{},"vaporInteropPlugin"," para usar componentes Vapor:",[87,1089,1092],{"className":1090,"code":1091,"language":923,"meta":92,"style":92},"language-ts shiki shiki-themes dracula","import { createApp, vaporInteropPlugin } from 'vue'\nimport App from '.\u002FApp.vue'\n\ncreateApp(App).use(vaporInteropPlugin).mount('#app')\n",[75,1093,1094,1109,1125,1129],{"__ignoreMap":92},[96,1095,1096,1098,1101,1103,1105,1107],{"class":98,"line":99},[96,1097,933],{"class":102},[96,1099,1100],{"class":110}," { createApp, vaporInteropPlugin } ",[96,1102,939],{"class":102},[96,1104,942],{"class":918},[96,1106,893],{"class":922},[96,1108,947],{"class":918},[96,1110,1111,1113,1116,1118,1120,1123],{"class":98,"line":454},[96,1112,933],{"class":102},[96,1114,1115],{"class":110}," App ",[96,1117,939],{"class":102},[96,1119,942],{"class":918},[96,1121,1122],{"class":922},".\u002FApp.vue",[96,1124,947],{"class":918},[96,1126,1127],{"class":98,"line":950},[96,1128,953],{"emptyLinePlaceholder":473},[96,1130,1131,1134,1137,1140,1143,1146,1148,1151,1154,1156],{"class":98,"line":956},[96,1132,1133],{"class":967},"createApp",[96,1135,1136],{"class":110},"(App).",[96,1138,1139],{"class":967},"use",[96,1141,1142],{"class":110},"(vaporInteropPlugin).",[96,1144,1145],{"class":967},"mount",[96,1147,971],{"class":110},[96,1149,1150],{"class":918},"'",[96,1152,1153],{"class":922},"#app",[96,1155,1150],{"class":918},[96,1157,977],{"class":110},[17,1159,1160],{},"Com o plugin instalado, componentes Vapor e componentes comuns podem ficar aninhados uns dentro dos outros. As notas do Vue avisam que isso cobre props, eventos e slots no uso padrão, mas ainda não todos os casos de borda. A recomendação deles é manter regiões distintas no app, cada uma em um modo, e evitar o aninhamento misto sempre que der.",[843,1162,1164],{"id":1163},"app-100-vapor","App 100% Vapor",[17,1166,1167,1168,888],{},"Se todos os componentes forem Vapor, use ",[75,1169,1170],{},"createVaporApp()",[87,1172,1174],{"className":1090,"code":1173,"language":923,"meta":92,"style":92},"import { createVaporApp } from 'vue'\nimport App from '.\u002FApp.vue'\n\ncreateVaporApp(App).mount('#app')\n",[75,1175,1176,1191,1205,1209],{"__ignoreMap":92},[96,1177,1178,1180,1183,1185,1187,1189],{"class":98,"line":99},[96,1179,933],{"class":102},[96,1181,1182],{"class":110}," { createVaporApp } ",[96,1184,939],{"class":102},[96,1186,942],{"class":918},[96,1188,893],{"class":922},[96,1190,947],{"class":918},[96,1192,1193,1195,1197,1199,1201,1203],{"class":98,"line":454},[96,1194,933],{"class":102},[96,1196,1115],{"class":110},[96,1198,939],{"class":102},[96,1200,942],{"class":918},[96,1202,1122],{"class":922},[96,1204,947],{"class":918},[96,1206,1207],{"class":98,"line":950},[96,1208,953],{"emptyLinePlaceholder":473},[96,1210,1211,1214,1216,1218,1220,1222,1224,1226],{"class":98,"line":956},[96,1212,1213],{"class":967},"createVaporApp",[96,1215,1136],{"class":110},[96,1217,1145],{"class":967},[96,1219,971],{"class":110},[96,1221,1150],{"class":918},[96,1223,1153],{"class":922},[96,1225,1150],{"class":918},[96,1227,977],{"class":110},[17,1229,1230,1231,1233,1234,1236],{},"Assim o runtime do Virtual DOM não entra no bundle. Cada componente continua precisando do marcador ",[75,1232,887],{},". Componentes escritos com render function ou JSX seguem sendo componentes de Virtual DOM e exigem interop. Um app Vapor também pode instalar o ",[75,1235,1086],{}," para aceitar componentes de Virtual DOM, mas isso traz o runtime de volta e reduz o ganho de tamanho.",[24,1238,1240],{"id":1239},"vapor-no-nuxt-46","Vapor no Nuxt 4.6",[17,1242,1243,1244,888],{},"O Nuxt 4.6, lançado em 5 de outubro de 2026, suporta o Vapor em modo de interoperabilidade. A raiz do app continua no Virtual DOM, e você escolhe quais componentes ou páginas usam Vapor. Para habilitar, ligue a opção no ",[75,1245,1246],{},"nuxt.config.ts",[87,1248,1250],{"className":1090,"code":1249,"language":923,"meta":92,"style":92},"export default defineNuxtConfig({\n  vue: {\n    vapor: true,\n  },\n})\n",[75,1251,1252,1266,1276,1289,1294],{"__ignoreMap":92},[96,1253,1254,1257,1260,1263],{"class":98,"line":99},[96,1255,1256],{"class":102},"export",[96,1258,1259],{"class":102}," default",[96,1261,1262],{"class":967}," defineNuxtConfig",[96,1264,1265],{"class":110},"({\n",[96,1267,1268,1271,1273],{"class":98,"line":454},[96,1269,1270],{"class":110},"  vue",[96,1272,888],{"class":102},[96,1274,1275],{"class":110}," {\n",[96,1277,1278,1281,1283,1286],{"class":98,"line":950},[96,1279,1280],{"class":110},"    vapor",[96,1282,888],{"class":102},[96,1284,1285],{"class":106}," true",[96,1287,1288],{"class":110},",\n",[96,1290,1291],{"class":98,"line":956},[96,1292,1293],{"class":110},"  },\n",[96,1295,1296],{"class":98,"line":980},[96,1297,1298],{"class":110},"})\n",[17,1300,1301,1302,1304,1305,1308,1309,1312],{},"Depois marque os componentes com ",[75,1303,1067],{},", como no exemplo acima. O Nuxt exige Vue ",[75,1306,1307],{},"^3.6.0-rc.2"," ou mais novo. Segundo o anúncio, rotas, ",[75,1310,1311],{},"useAsyncData",", layouts e a maioria dos componentes embutidos funcionam sem mudanças. O anúncio recomenda testar o Vapor primeiro em um projeto novo.",[17,1314,1315],{},"A documentação do Nuxt lista algumas limitações do modo de interop:",[312,1317,1318,1321,1328,1348,1354,1372],{},[315,1319,1320],{},"a raiz do app não pode ser Vapor, porque os apps 100% Vapor não estão disponíveis no Nuxt;",[315,1322,1323,1324,1327],{},"componentes Vapor não expõem ",[75,1325,1326],{},"$el"," nas template refs;",[315,1329,1330,1333,1334,1337,1338,863,1341,156,1344,1347],{},[75,1331,1332],{},"\u003CClientOnly>"," pula o repasse de atributos, e ",[75,1335,1336],{},"\u003CNuxtIsland>",", os componentes de servidor e os componentes de head que leem texto filho (",[75,1339,1340],{},"\u003CTitle>",[75,1342,1343],{},"\u003CStyle>",[75,1345,1346],{},"\u003CNoscript>",") emitem aviso se receberem um slot Vapor;",[315,1349,1350,1353],{},[75,1351,1352],{},"onPrehydrate"," com chave volta para a forma sem chave (e avisa em desenvolvimento), porque não há instância de componente para anexar a chave;",[315,1355,1356,156,1359,1362,1363,1366,1367,344,1369,1371],{},[75,1357,1358],{},"asyncData",[75,1360,1361],{},"fetchKey"," via ",[75,1364,1365],{},"defineNuxtComponent"," não funcionam (use ",[75,1368,1311],{},[75,1370,883],{},");",[315,1373,1374,1375,1378],{},"composables do Nuxt chamados depois de um ",[75,1376,1377],{},"await"," podem perder o contexto.",[17,1380,1381,1382,1385,1386,1389],{},"O mesmo anúncio traz números de performance do Nuxt 4.6: o ",[75,1383,1384],{},"nuxt build"," de um projeto inicial passou de 4,4 s para 3,6 s (18% mais rápido) e a página com 300 ",[75,1387,1388],{},"\u003CNuxtLink>"," foi de 110 para 140 req\u002Fs no SSR (+26%). O Nuxt atribui esses ganhos às otimizações gerais da versão, não ao Vapor.",[17,1391,1392],{},"Se você ainda usa Nuxt 3, vale saber que ele chegou ao fim de vida em 31 de julho de 2026.",[24,1394,1396],{"id":1395},"o-que-o-vapor-ainda-não-suporta","O que o Vapor ainda não suporta",[17,1398,1399],{},"O Vapor aceita um subconjunto das APIs do Vue. As notas oficiais listam o que não está disponível ou não se aplica nos componentes Vapor:",[312,1401,1402,1420,1425,1433,1439,1444],{},[315,1403,1404,1405,863,1408,863,1411,1414,1415,1419],{},"Options API (",[75,1406,1407],{},"data",[75,1409,1410],{},"methods",[75,1412,1413],{},"mounted"," e companhia). Se você precisa entender a diferença, veja o artigo sobre ",[32,1416,1418],{"href":1417},"\u002Fblog\u002Fqual-a-diferenca-entre-a-composition-api-e-options-api-no-vuejs","Composition API e Options API",";",[315,1421,1422,1419],{},[75,1423,1424],{},"app.config.globalProperties",[315,1426,1427,1430,1431,1419],{},[75,1428,1429],{},"getCurrentInstance()",", que retorna ",[75,1432,120],{},[315,1434,1435,1436,1419],{},"eventos de ciclo de vida por elemento, como ",[75,1437,1438],{},"@vue:mounted",[315,1440,1441,1419],{},[75,1442,1443],{},"v-memo",[315,1445,1446,863,1448,863,1451,863,1454,156,1457,1460],{},[75,1447,1326],{},[75,1449,1450],{},"$props",[75,1452,1453],{},"$attrs",[75,1455,1456],{},"$slots",[75,1458,1459],{},"$refs"," nas template refs de componentes.",[17,1462,1463,1464,1466,1467,1469],{},"Bibliotecas de componentes baseadas em Virtual DOM também merecem teste. As notas falam em \"arestas\" ao usar uma biblioteca de componentes de Virtual DOM dentro do Vapor, sem citar nenhuma biblioteca específica. Se alguma delas depende de ",[75,1465,1429],{},", o ",[75,1468,120],{}," acima pode ser um problema, mas isso só um teste no seu projeto confirma.",[17,1471,1472,1473,1476],{},"As notas oficiais não listam ",[75,1474,1475],{},"\u003CSuspense>"," nem o Vue DevTools como incompatíveis com o Vapor, mas isso não garante suporte completo. O changelog das RCs registra várias correções de integração do Vapor com o Suspense, então o suporte está em andamento. Teste os dois no seu cenário antes de decidir.",[17,1478,1479],{},"O mesmo vale para SSR. O changelog das RCs traz várias correções de hidratação em componentes Vapor, o que indica que o SSR é suportado, mas ainda em ajuste. Se o seu app renderiza no servidor, teste a hidratação com atenção.",[843,1481,1483,1484],{"id":1482},"eventos-e-delegate","Eventos e ",[75,1485,1486],{},".delegate",[17,1488,1489,1490,1493,1494,1497,1498,888],{},"Nas RCs mais antigas, o Vapor delegava eventos para o ",[75,1491,1492],{},"document",", o que fazia um ",[75,1495,1496],{},"stopPropagation()"," em um ancestral impedir o handler do filho. Desde o rc.2, os listeners são ligados direto no elemento, como no Vue tradicional, e a delegação virou opt-in com o modificador ",[75,1499,1486],{},[87,1501,1503],{"className":891,"code":1502,"language":893,"meta":92,"style":92},"\u003Cbutton @click.delegate=\"onClick\" \u002F>\n",[75,1504,1505],{"__ignoreMap":92},[96,1506,1507,1509,1511,1514,1517,1520,1523,1525,1527,1530,1532],{"class":98,"line":99},[96,1508,900],{"class":110},[96,1510,1011],{"class":102},[96,1512,1513],{"class":110}," @",[96,1515,1516],{"class":906},"click",[96,1518,1519],{"class":110},".",[96,1521,1522],{"class":906},"delegate",[96,1524,241],{"class":102},[96,1526,919],{"class":918},[96,1528,1529],{"class":110},"onClick",[96,1531,919],{"class":918},[96,1533,1534],{"class":110}," \u002F>\n",[17,1536,1537,1538,1541],{},"A opção ",[75,1539,1540],{},"compilerOptions.eventDelegation"," foi removida.",[843,1543,1545],{"id":1544},"diretivas-customizadas","Diretivas customizadas",[17,1547,1548],{},"As diretivas customizadas também têm outra interface no Vapor. Em vez de um objeto com hooks, você escreve uma função que recebe o elemento e um getter reativo, e pode devolver uma função de limpeza:",[87,1550,1552],{"className":1090,"code":1551,"language":923,"meta":92,"style":92},"import { watchEffect } from 'vue'\n\nconst MyDirective = (el, source) => {\n  watchEffect(() => {\n    el.textContent = source()\n  })\n  return () => console.log('cleanup')\n}\n",[75,1553,1554,1569,1573,1603,1615,1628,1633,1660],{"__ignoreMap":92},[96,1555,1556,1558,1561,1563,1565,1567],{"class":98,"line":99},[96,1557,933],{"class":102},[96,1559,1560],{"class":110}," { watchEffect } ",[96,1562,939],{"class":102},[96,1564,942],{"class":918},[96,1566,893],{"class":922},[96,1568,947],{"class":918},[96,1570,1571],{"class":98,"line":454},[96,1572,953],{"emptyLinePlaceholder":473},[96,1574,1575,1577,1580,1583,1586,1590,1592,1595,1598,1601],{"class":98,"line":950},[96,1576,959],{"class":102},[96,1578,1579],{"class":967}," MyDirective",[96,1581,1582],{"class":102}," =",[96,1584,1585],{"class":110}," (",[96,1587,1589],{"class":1588},"sGEwX","el",[96,1591,863],{"class":110},[96,1593,1594],{"class":1588},"source",[96,1596,1597],{"class":110},") ",[96,1599,1600],{"class":102},"=>",[96,1602,1275],{"class":110},[96,1604,1605,1608,1611,1613],{"class":98,"line":956},[96,1606,1607],{"class":967},"  watchEffect",[96,1609,1610],{"class":110},"(() ",[96,1612,1600],{"class":102},[96,1614,1275],{"class":110},[96,1616,1617,1620,1622,1625],{"class":98,"line":980},[96,1618,1619],{"class":110},"    el.textContent ",[96,1621,241],{"class":102},[96,1623,1624],{"class":967}," source",[96,1626,1627],{"class":110},"()\n",[96,1629,1630],{"class":98,"line":990},[96,1631,1632],{"class":110},"  })\n",[96,1634,1635,1638,1641,1643,1646,1649,1651,1653,1656,1658],{"class":98,"line":995},[96,1636,1637],{"class":102},"  return",[96,1639,1640],{"class":110}," () ",[96,1642,1600],{"class":102},[96,1644,1645],{"class":110}," console.",[96,1647,1648],{"class":967},"log",[96,1650,971],{"class":110},[96,1652,1150],{"class":918},[96,1654,1655],{"class":922},"cleanup",[96,1657,1150],{"class":918},[96,1659,977],{"class":110},[96,1661,1662],{"class":98,"line":1005},[96,1663,1664],{"class":110},"}\n",[17,1666,1667,1668,1671,1672,1675,1676,1680],{},"A assinatura completa é ",[75,1669,1670],{},"(node, value?, argument?, modifiers?)",", e ",[75,1673,1674],{},"value"," é o getter reativo. Se quiser rever o básico, o artigo sobre ",[32,1677,1679],{"href":1678},"\u002Fblog\u002Fo-que-sao-diretivas-no-vue-e-como-implementa-las","diretivas no Vue"," cobre o modelo tradicional.",[24,1682,1684],{"id":1683},"onde-o-vapor-ajuda","Onde o Vapor ajuda",[17,1686,1687],{},"O ganho aparece onde o app faz muito trabalho de atualização de DOM: listas e tabelas densas, componentes que mudam várias vezes por segundo e páginas em que o tamanho do JavaScript inicial pesa. Para um CRUD comum, a diferença tende a passar despercebida pelo usuário.",[17,1689,1690,1691,1694],{},"O Vapor também não resolve problemas que não vêm do renderizador. Renderizar 10.000 itens no DOM continua lento nos dois modos, e a saída é virtualizar a lista. Chamar funções pesadas direto no template, como ",[75,1692,1693],{},"{{ calcularTotal(item) }}",", continua sendo má ideia nos dois modos.",[24,1696,1698],{"id":1697},"vale-adotar-agora","Vale adotar agora?",[17,1700,1701],{},"A própria equipe do Vue diz que o conjunto de recursos do Vapor está completo no RC e recomenda, por enquanto, dois usos: aplicar o Vapor em partes de um app existente, como uma página sensível a performance, e construir apps pequenos novos inteiramente em Vapor.",[17,1703,1704],{},"Para um app em produção que já roda bem no Vue 3.5, esperar a versão estável é a escolha mais segura. Para uma página isolada onde você já mediu um gargalo, um teste no Nuxt 4.6 ou num app Vue com interop é um bom experimento. Antes de começar, confira:",[312,1706,1707,1710,1716,1719],{},[315,1708,1709],{},"você mediu o desempenho atual (o painel Performance do navegador serve) e achou um gargalo de renderização;",[315,1711,1712,1713,1715],{},"o componente usa ",[75,1714,883],{}," ou só template;",[315,1717,1718],{},"as bibliotecas de UI que ele usa funcionam com interop no seu projeto;",[315,1720,1721],{},"você consegue isolar o Vapor numa rota ou componente e voltar atrás sem dor.",[24,1723,1725],{"id":1724},"perguntas-frequentes","Perguntas frequentes",[843,1727,1729],{"id":1728},"o-que-é-vapor-mode-no-vue","O que é Vapor Mode no Vue?",[17,1731,1732],{},"É um modo de compilação opt-in para SFCs, disponível no Vue 3.6 RC. Em vez de criar e comparar uma árvore de Virtual DOM em tempo de execução, o compilador gera código que atualiza o DOM diretamente.",[843,1734,1736],{"id":1735},"o-vue-36-já-saiu-como-estável","O Vue 3.6 já saiu como estável?",[17,1738,1739,1740,1742,1743,1519],{},"Ainda não. Até 6 de outubro de 2026, a versão mais recente é a ",[75,1741,812],{},", e a estável é a ",[75,1744,816],{},[843,1746,1748],{"id":1747},"o-vapor-mode-substitui-o-virtual-dom","O Vapor Mode substitui o Virtual DOM?",[17,1750,1751,1752,1519],{},"Não. Ele é opcional e convive com o Virtual DOM no mesmo app, por meio do ",[75,1753,1086],{},[843,1755,1757],{"id":1756},"preciso-reescrever-meu-app-para-usar-o-vapor","Preciso reescrever meu app para usar o Vapor?",[17,1759,1760,1761,1763,1764,1766],{},"Não. Você pode marcar um componente por vez com ",[75,1762,887],{},". Os componentes que usam Options API ficam fora, porque o Vapor só aceita ",[75,1765,883],{}," e templates.",[843,1768,1770],{"id":1769},"o-vapor-mode-funciona-com-options-api","O Vapor Mode funciona com Options API?",[17,1772,1773],{},"Não. As notas oficiais listam a Options API como não suportada.",[843,1775,1777],{"id":1776},"o-vapor-mode-funciona-com-nuxt","O Vapor Mode funciona com Nuxt?",[17,1779,1780,1781,344,1784,1786,1787,1789],{},"Sim, desde o Nuxt 4.6, em modo de interoperabilidade: ative ",[75,1782,1783],{},"vue: { vapor: true }",[75,1785,1246],{}," e marque os componentes com ",[75,1788,1067],{},". A raiz do app continua no Virtual DOM.",[843,1791,1793],{"id":1792},"o-vapor-mode-é-mais-rápido-que-o-virtual-dom","O Vapor Mode é mais rápido que o Virtual DOM?",[17,1795,1796],{},"Segundo as notas do Vue 3.6, o Vapor chegou ao nível de Solid e Svelte 5 em benchmarks de terceiros. Para a maioria dos apps o ganho percebido é pequeno, e o efeito real no seu projeto só aparece medindo.",[450,1798,1799],{},"html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .s0Tla, html code.shiki .s0Tla{--shiki-default:#FF79C6}html pre.shiki code .sY_PY, html code.shiki .sY_PY{--shiki-default:#50FA7B;--shiki-default-font-style:italic}html pre.shiki code .seVfx, html code.shiki .seVfx{--shiki-default:#E9F284}html pre.shiki code .s-mGx, html code.shiki .s-mGx{--shiki-default:#F1FA8C}html pre.shiki code .sAOxA, html code.shiki .sAOxA{--shiki-default:#50FA7B}html pre.shiki code .sIQBb, html code.shiki .sIQBb{--shiki-default:#BD93F9}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sGEwX, html code.shiki .sGEwX{--shiki-default:#FFB86C;--shiki-default-font-style:italic}",{"title":92,"searchDepth":454,"depth":454,"links":1801},[1802,1805,1809,1810,1815,1816,1817],{"id":831,"depth":454,"text":832,"children":1803},[1804],{"id":845,"depth":950,"text":846},{"id":876,"depth":454,"text":877,"children":1806},[1807,1808],{"id":1075,"depth":950,"text":1076},{"id":1163,"depth":950,"text":1164},{"id":1239,"depth":454,"text":1240},{"id":1395,"depth":454,"text":1396,"children":1811},[1812,1814],{"id":1482,"depth":950,"text":1813},"Eventos e .delegate",{"id":1544,"depth":950,"text":1545},{"id":1683,"depth":454,"text":1684},{"id":1697,"depth":454,"text":1698},{"id":1724,"depth":454,"text":1725,"children":1818},[1819,1820,1821,1822,1823,1824,1825],{"id":1728,"depth":950,"text":1729},{"id":1735,"depth":950,"text":1736},{"id":1747,"depth":950,"text":1748},{"id":1756,"depth":950,"text":1757},{"id":1769,"depth":950,"text":1770},{"id":1776,"depth":950,"text":1777},{"id":1792,"depth":950,"text":1793},[1827,1828],"vuejs","nuxt","O que é o Vue Vapor Mode, como ativar no Vue 3.6 (RC) e no Nuxt 4.6, o que ainda não funciona e quando vale a pena usar, com exemplos e perguntas frequentes.","vue-vapor-mode-what-it-is-and-how-to-use-it",{},"\u002Fblog\u002Fvue-vapor-mode-como-funciona-e-como-usar","vue-vapor-mode-como-funciona-e-como-usar","2026-10-06",{"title":803,"description":1829},{"loc":1832,"lastmod":1834},"blog\u002Fvue-vapor-mode-como-funciona-e-como-usar",1727,"NQrIpjH60lJ3Pb8kNbXKYS5Uv15ImJPunsIToGQO9LE",{"id":1841,"title":1842,"articleCover":1843,"articleCoverEmbed":486,"articleCoverEmbedUploadDate":486,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":1844,"categoriesIds":2390,"description":2392,"enAlternateSlug":2393,"extension":471,"meta":2394,"navigation":473,"path":2395,"ptBrAlternateSlug":2396,"publishedAt":2397,"seo":2398,"sitemap":2399,"stem":2401,"updatedAt":1834,"wordCount":2402,"__hash__":2403},"blog\u002Fblog\u002Fcomo-validar-cartao-de-credito-com-javascript.md","Como validar um cartão de crédito com JavaScript (algoritmo de Luhn)","\u002Fimages\u002Fblog\u002Fjavascript\u002Fcomo-validar-cartao-de-credito-com-javascript.webp",{"type":14,"value":1845,"toc":2367},[1846,1849,1852,1856,1863,1866,1869,1873,1883,1886,1919,1923,1939,1965,1971,1974,1978,1981,2177,2194,2198,2209,2226,2233,2236,2240,2243,2247,2254,2258,2271,2275,2278,2282,2289,2298,2300,2304,2315,2319,2322,2326,2329,2333,2336,2340,2343,2347,2350,2354,2357,2365],[17,1847,1848],{},"Você está construindo um formulário de checkout e precisa validar o campo de cartão antes de enviar os dados pro gateway de pagamento. A solução mais comum e recomendada é usar o algoritmo de Luhn para checar se o número tem o formato matemático correto.",[17,1850,1851],{},"Neste artigo, você vai entender exatamente como o algoritmo funciona, ver um exemplo numérico passo a passo e implementar uma função JavaScript pronta pra usar no seu projeto.",[24,1853,1855],{"id":1854},"o-que-é-o-algoritmo-de-luhn","O que é o algoritmo de Luhn",[17,1857,1858,1859,1862],{},"O algoritmo de Luhn, também chamado de \"fórmula do módulo 10\" ou \"mod-10\", foi criado por Hans Peter Luhn em 1954 e virou padrão da indústria para validar números de cartão de crédito. Ele calcula um ",[63,1860,1861],{},"dígito verificador"," (o último dígito do número) que permite detectar erros de digitação, como trocar dois dígitos de lugar ou digitar um número errado.",[17,1864,1865],{},"A ideia é simples: o emissor do cartão (banco ou bandeira) gera o número de forma que, quando você aplica a fórmula do Luhn, o resultado seja divisível por 10. Se não for, o número tem erro de formatação.",[17,1867,1868],{},"Isso é feito no lado do cliente (no navegador) antes de mandar os dados pro servidor. Assim você evita enviar requisições inválidas pro gateway de pagamento e melhora a experiência do usuário com feedback imediato.",[24,1870,1872],{"id":1871},"passo-a-passo-do-algoritmo-com-exemplo-numérico","Passo a passo do algoritmo com exemplo numérico",[17,1874,1875,1876,1879,1880,1519],{},"Vamos validar o número de teste da Visa que várias plataformas de pagamento usam em sandbox: ",[63,1877,1878],{},"4242 4242 4242 4242",". Primeiro, removemos espaços e traços, ficando com ",[75,1881,1882],{},"4242424242424242",[17,1884,1885],{},"Agora aplicamos o algoritmo de Luhn:",[1887,1888,1889,1895,1901,1907,1913],"ol",{},[315,1890,1891,1894],{},[63,1892,1893],{},"Comece pelo dígito mais à direita"," (o último 2) e vá para a esquerda. Esse primeiro dígito nunca é dobrado.",[315,1896,1897,1900],{},[63,1898,1899],{},"Dobre o valor de cada segundo dígito"," a partir daí, ou seja, pule um, dobre o próximo, pule um, dobre o próximo, e assim por diante.",[315,1902,1903,1906],{},[63,1904,1905],{},"Se o dobro resultar em dois dígitos",", some os dois algarismos entre si (ou subtraia 9, é equivalente).",[315,1908,1909,1912],{},[63,1910,1911],{},"Some todos os dígitos"," (os dobrados\u002Fajustados e os que não foram alterados).",[315,1914,1915,1918],{},[63,1916,1917],{},"Se o total for divisível por 10",", o número é válido pelo algoritmo de Luhn.",[843,1920,1922],{"id":1921},"exemplo-prático-com-4242424242424242","Exemplo prático com 4242424242424242",[17,1924,1925,1926,156,1929,1932,1933,1935,1936,1938],{},"O número tem 16 dígitos, alternando ",[75,1927,1928],{},"4",[75,1930,1931],{},"2",". Começando pelo dígito mais à direita (que não é dobrado) e indo para a esquerda, os dígitos que caem na posição \"dobrar\" são sempre os ",[75,1934,1928],{},", e os que caem na posição \"não dobrar\" são sempre os ",[75,1937,1931],{},". Isso acontece porque o número inteiro segue esse padrão alternado.",[312,1940,1941,1950],{},[315,1942,1943,1946,1947,1949],{},[63,1944,1945],{},"Dígitos que não são dobrados"," (8 dígitos, todos ",[75,1948,1931],{},"): 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 = 16",[315,1951,1952,1946,1955,1957,1958,1960,1961,1964],{},[63,1953,1954],{},"Dígitos dobrados",[75,1956,1928],{},"): cada ",[75,1959,1928],{}," dobrado vira ",[75,1962,1963],{},"8"," (4 × 2 = 8, não passa de 9, não precisa ajustar). 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 = 64",[17,1966,1967,1968,1519],{},"Somando os dois grupos: 16 + 64 = ",[63,1969,1970],{},"80",[17,1972,1973],{},"Como 80 é divisível por 10 (resto 0), esse número passa na validação do algoritmo de Luhn.",[24,1975,1977],{"id":1976},"implementação-em-javascript-puro","Implementação em JavaScript puro",[17,1979,1980],{},"Abaixo está uma função completa que remove espaços, traços e outros caracteres não numéricos, depois aplica o algoritmo de Luhn:",[87,1982,1985],{"className":1983,"code":1984,"language":468,"meta":92,"style":92},"language-javascript shiki shiki-themes dracula","function validarCartaoCredito(numero) {\n  \u002F\u002F Remove tudo que não for dígito\n  const digitos = numero.replace(\u002F\\D\u002Fg, \"\");\n\n  \u002F\u002F Cartões têm entre 13 e 19 dígitos (a maioria 16)\n  if (digitos.length \u003C 13 || digitos.length > 19) {\n    return false;\n  }\n\n  let soma = 0;\n  let deveDobrar = false; \u002F\u002F começa pelo último dígito (não dobra)\n\n  \u002F\u002F Percorre da direita para a esquerda\n  for (let i = digitos.length - 1; i >= 0; i--) {\n    let d = parseInt(digitos[i], 10);\n\n    if (deveDobrar) {\n      d *= 2;\n      \u002F\u002F Se resultou em dois dígitos, soma os algarismos (ou subtrai 9)\n      if (d > 9) {\n        d -= 9;\n      }\n    }\n\n    soma += d;\n    deveDobrar = !deveDobrar; \u002F\u002F alterna para o próximo dígito\n  }\n\n  return soma % 10 === 0;\n}\n\n\u002F\u002F Testando com o número de teste da Visa\nconsole.log(validarCartaoCredito(\"4242 4242 4242 4242\")); \u002F\u002F true\nconsole.log(validarCartaoCredito(\"4242424242424242\")); \u002F\u002F true\nconsole.log(validarCartaoCredito(\"1234 5678 1234 5678\")); \u002F\u002F false\n",[75,1986,1987,1992,1997,2002,2006,2011,2016,2021,2026,2030,2035,2040,2045,2051,2057,2063,2068,2074,2080,2086,2092,2098,2104,2110,2115,2121,2127,2132,2137,2143,2148,2153,2159,2165,2171],{"__ignoreMap":92},[96,1988,1989],{"class":98,"line":99},[96,1990,1991],{},"function validarCartaoCredito(numero) {\n",[96,1993,1994],{"class":98,"line":454},[96,1995,1996],{},"  \u002F\u002F Remove tudo que não for dígito\n",[96,1998,1999],{"class":98,"line":950},[96,2000,2001],{},"  const digitos = numero.replace(\u002F\\D\u002Fg, \"\");\n",[96,2003,2004],{"class":98,"line":956},[96,2005,953],{"emptyLinePlaceholder":473},[96,2007,2008],{"class":98,"line":980},[96,2009,2010],{},"  \u002F\u002F Cartões têm entre 13 e 19 dígitos (a maioria 16)\n",[96,2012,2013],{"class":98,"line":990},[96,2014,2015],{},"  if (digitos.length \u003C 13 || digitos.length > 19) {\n",[96,2017,2018],{"class":98,"line":995},[96,2019,2020],{},"    return false;\n",[96,2022,2023],{"class":98,"line":1005},[96,2024,2025],{},"  }\n",[96,2027,2028],{"class":98,"line":1028},[96,2029,953],{"emptyLinePlaceholder":473},[96,2031,2032],{"class":98,"line":1034},[96,2033,2034],{},"  let soma = 0;\n",[96,2036,2037],{"class":98,"line":1044},[96,2038,2039],{},"  let deveDobrar = false; \u002F\u002F começa pelo último dígito (não dobra)\n",[96,2041,2043],{"class":98,"line":2042},12,[96,2044,953],{"emptyLinePlaceholder":473},[96,2046,2048],{"class":98,"line":2047},13,[96,2049,2050],{},"  \u002F\u002F Percorre da direita para a esquerda\n",[96,2052,2054],{"class":98,"line":2053},14,[96,2055,2056],{},"  for (let i = digitos.length - 1; i >= 0; i--) {\n",[96,2058,2060],{"class":98,"line":2059},15,[96,2061,2062],{},"    let d = parseInt(digitos[i], 10);\n",[96,2064,2066],{"class":98,"line":2065},16,[96,2067,953],{"emptyLinePlaceholder":473},[96,2069,2071],{"class":98,"line":2070},17,[96,2072,2073],{},"    if (deveDobrar) {\n",[96,2075,2077],{"class":98,"line":2076},18,[96,2078,2079],{},"      d *= 2;\n",[96,2081,2083],{"class":98,"line":2082},19,[96,2084,2085],{},"      \u002F\u002F Se resultou em dois dígitos, soma os algarismos (ou subtrai 9)\n",[96,2087,2089],{"class":98,"line":2088},20,[96,2090,2091],{},"      if (d > 9) {\n",[96,2093,2095],{"class":98,"line":2094},21,[96,2096,2097],{},"        d -= 9;\n",[96,2099,2101],{"class":98,"line":2100},22,[96,2102,2103],{},"      }\n",[96,2105,2107],{"class":98,"line":2106},23,[96,2108,2109],{},"    }\n",[96,2111,2113],{"class":98,"line":2112},24,[96,2114,953],{"emptyLinePlaceholder":473},[96,2116,2118],{"class":98,"line":2117},25,[96,2119,2120],{},"    soma += d;\n",[96,2122,2124],{"class":98,"line":2123},26,[96,2125,2126],{},"    deveDobrar = !deveDobrar; \u002F\u002F alterna para o próximo dígito\n",[96,2128,2130],{"class":98,"line":2129},27,[96,2131,2025],{},[96,2133,2135],{"class":98,"line":2134},28,[96,2136,953],{"emptyLinePlaceholder":473},[96,2138,2140],{"class":98,"line":2139},29,[96,2141,2142],{},"  return soma % 10 === 0;\n",[96,2144,2146],{"class":98,"line":2145},30,[96,2147,1664],{},[96,2149,2151],{"class":98,"line":2150},31,[96,2152,953],{"emptyLinePlaceholder":473},[96,2154,2156],{"class":98,"line":2155},32,[96,2157,2158],{},"\u002F\u002F Testando com o número de teste da Visa\n",[96,2160,2162],{"class":98,"line":2161},33,[96,2163,2164],{},"console.log(validarCartaoCredito(\"4242 4242 4242 4242\")); \u002F\u002F true\n",[96,2166,2168],{"class":98,"line":2167},34,[96,2169,2170],{},"console.log(validarCartaoCredito(\"4242424242424242\")); \u002F\u002F true\n",[96,2172,2174],{"class":98,"line":2173},35,[96,2175,2176],{},"console.log(validarCartaoCredito(\"1234 5678 1234 5678\")); \u002F\u002F false\n",[17,2178,2179,2180,2183,2184,2187,2188,2193],{},"Essa função é o que você usa no ",[75,2181,2182],{},"onblur"," ou ",[75,2185,2186],{},"onsubmit"," do seu formulário. Se quiser testar online antes de integrar, temos um ",[32,2189,2192],{"href":2190,"rel":2191},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fvalidador-de-cartao-de-credito",[36],"validador de cartão de crédito online, gratuito"," que aplica exatamente essa lógica.",[24,2195,2197],{"id":2196},"o-que-esse-algoritmo-não-garante","O que esse algoritmo NÃO garante",[17,2199,2200,2201,2204,2205,2208],{},"Aqui vai o disclaimer que muita gente pula (e depois se arrepende): ",[63,2202,2203],{},"o algoritmo de Luhn valida apenas o FORMATO\u002Festrutura matemática do número",". Ele ",[63,2206,2207],{},"NÃO"," verifica:",[312,2210,2211,2214,2217,2220,2223],{},[315,2212,2213],{},"Se o cartão existe de verdade",[315,2215,2216],{},"Se está ativo ou bloqueado",[315,2218,2219],{},"Se tem limite disponível",[315,2221,2222],{},"Se pertence à pessoa que está preenchendo o formulário",[315,2224,2225],{},"Se não é um cartão reportado como roubado\u002Ffraudado",[17,2227,2228,2229,2232],{},"Isso só o emissor do cartão (banco ou bandeira) consegue checar, via gateway de pagamento real (Stripe, Pagar.me, Mercado Pago, etc.). O Luhn é só um \"filtro de digitação\". Ele evita que você mande ",[75,2230,2231],{},"1234 5678 1234 5678"," pro gateway e receba um erro bobo que poderia ter sido pego antes.",[17,2234,2235],{},"Não escreva no seu código nada que sugira que validar com Luhn significa \"cartão válido pra cobrar\", porque não é verdade.",[24,2237,2239],{"id":2238},"erros-comuns","Erros comuns",[17,2241,2242],{},"Se você já implementou validação de cartão, provavelmente já viu (ou cometeu) algum desses:",[843,2244,2246],{"id":2245},"validar-só-pela-quantidade-de-dígitos","Validar só pela quantidade de dígitos",[17,2248,2249,2250,2253],{},"Muitos formulários só checam se o número tem 16 dígitos. Isso deixa passar ",[75,2251,2252],{},"1111111111111111",", que tem 16 dígitos mas falha no Luhn. O inverso também acontece: American Express tem 15 dígitos, então validar só por \"tem que ter 16\" quebra o fluxo pra quem usa Amex.",[843,2255,2257],{"id":2256},"não-remover-espaçostraços-antes-de-validar","Não remover espaços\u002Ftraços antes de validar",[17,2259,2260,2261,2183,2264,2266,2267,2270],{},"O usuário digita ",[75,2262,2263],{},"4242-4242-4242-4242",[75,2265,1878],{},". Se você não limpar isso antes de aplicar o Luhn, a validação falha mesmo com o número correto. A linha ",[75,2268,2269],{},"numero.replace(\u002F\\D\u002Fg, '')"," resolve isso.",[843,2272,2274],{"id":2273},"tratar-luhn-como-verificação-antifraude","Tratar Luhn como verificação antifraude",[17,2276,2277],{},"Isso é clássico: o time de produto pede \"valida se o cartão é válido\" e o dev implementa Luhn achando que tá fazendo verificação de fraude. Não tá. Fraude requer análise de risco, tokenização, 3D Secure, regras do gateway. Nada disso o Luhn faz.",[843,2279,2281],{"id":2280},"usar-números-de-teste-como-se-fossem-reais","Usar números de teste como se fossem reais",[17,2283,2284,2285,2288],{},"Os números de teste que gateways como Stripe e PayPal disponibilizam são válidos pelo Luhn, mas ",[63,2286,2287],{},"não são cartões reais",". Eles só funcionam em ambiente de sandbox. Nunca use em produção e nunca tente \"testar se funciona\" em gateway real. Isso é violação dos termos e pode gerar bloqueio.",[17,2290,2291,2292,2297],{},"Se precisar de dados de teste válidos pelo Luhn pra testar formulários, nosso ",[32,2293,2296],{"href":2294,"rel":2295},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-cartao-de-credito",[36],"gerador de cartão de crédito para testes"," cria números estruturalmente corretos (mas não reais) pra você usar no QA.",[24,2299,1725],{"id":1724},[843,2301,2303],{"id":2302},"como-saber-se-um-número-de-cartão-é-válido","Como saber se um número de cartão é válido?",[17,2305,2306,2307,2310,2311,2314],{},"Depende do que você quer dizer com \"válido\". Se for ",[63,2308,2309],{},"formato correto",", use o algoritmo de Luhn, que é o que a maioria dos gateways espera no front-end. Se for ",[63,2312,2313],{},"cartão que realmente funciona",", só o gateway de pagamento (via emissor) consegue responder, depois que você tenta cobrar.",[843,2316,2318],{"id":2317},"dá-pra-testar-um-formulário-de-pagamento-sem-usar-cartão-real","Dá pra testar um formulário de pagamento sem usar cartão real?",[17,2320,2321],{},"Sim. Use os números de teste que cada gateway fornece (Stripe, Pagar.me, Mercado Pago, etc.). Eles são válidos pelo Luhn e simulam cenários como \"pagamento aprovado\", \"saldo insuficiente\", \"3D Secure\", etc. Nunca use cartões reais de terceiros. Use só os de sandbox.",[843,2323,2325],{"id":2324},"validar-cartão-de-crédito-é-a-mesma-coisa-que-verificar-se-ele-está-ativo","Validar cartão de crédito é a mesma coisa que verificar se ele está ativo?",[17,2327,2328],{},"Não. Validar (com Luhn) checa se o número tem a estrutura matemática correta. Verificar se está ativo, tem limite ou não tá bloqueado é papel do banco, feito via gateway, quando você tenta processar o pagamento.",[843,2330,2332],{"id":2331},"o-que-é-o-algoritmo-de-luhn-1","O que é o algoritmo de Luhn?",[17,2334,2335],{},"É uma fórmula matemática (módulo 10) que calcula um dígito verificador pra detectar erros de digitação em números como cartões de crédito, IMEI de celular, etc. Foi criado em 1954 por Hans Peter Luhn e virou padrão da indústria.",[843,2337,2339],{"id":2338},"posso-usar-o-luhn-pra-evitar-fraude","Posso usar o Luhn pra evitar fraude?",[17,2341,2342],{},"Não. O Luhn só pega erro de digitação. Fraude requer análise comportamental, verificação de endereço, 3D Secure, regras de risco do gateway. Nada disso o Luhn faz.",[843,2344,2346],{"id":2345},"qual-a-diferença-entre-número-válido-pelo-luhn-e-cartão-válido-pra-cobrar","Qual a diferença entre \"número válido pelo Luhn\" e \"cartão válido pra cobrar\"?",[17,2348,2349],{},"\"Número válido pelo Luhn\" significa formato matemático correto. \"Cartão válido pra cobrar\" significa que o emissor confirmou que o cartão existe, tá ativo, tem limite e não tá bloqueado. Só o gateway junto com o emissor respondem a segunda pergunta.",[24,2351,2353],{"id":2352},"fechamento","Fechamento",[17,2355,2356],{},"Se você tá implementando validação de cartão num formulário de checkout, o algoritmo de Luhn é o primeiro passo, e o mais importante, pra evitar erros bobos de digitação. Implemente a função acima, teste com os números de sandbox do seu gateway e lembre sempre: Luhn valida formato, não valida se o cartão funciona de verdade.",[17,2358,2359,2360,2364],{},"Quer testar sua implementação antes de subir pra produção? Experimente nosso ",[32,2361,2363],{"href":2190,"rel":2362},[36],"validador de cartão de crédito online",". Ele aplica exatamente a mesma lógica que você vai usar no código.",[450,2366,777],{},{"title":92,"searchDepth":454,"depth":454,"links":2368},[2369,2370,2373,2374,2375,2381,2389],{"id":1854,"depth":454,"text":1855},{"id":1871,"depth":454,"text":1872,"children":2371},[2372],{"id":1921,"depth":950,"text":1922},{"id":1976,"depth":454,"text":1977},{"id":2196,"depth":454,"text":2197},{"id":2238,"depth":454,"text":2239,"children":2376},[2377,2378,2379,2380],{"id":2245,"depth":950,"text":2246},{"id":2256,"depth":950,"text":2257},{"id":2273,"depth":950,"text":2274},{"id":2280,"depth":950,"text":2281},{"id":1724,"depth":454,"text":1725,"children":2382},[2383,2384,2385,2386,2387,2388],{"id":2302,"depth":950,"text":2303},{"id":2317,"depth":950,"text":2318},{"id":2324,"depth":950,"text":2325},{"id":2331,"depth":950,"text":2332},{"id":2338,"depth":950,"text":2339},{"id":2345,"depth":950,"text":2346},{"id":2352,"depth":454,"text":2353},[468,2391],"tools","Aprenda a validar número de cartão de crédito com JavaScript usando o algoritmo de Luhn. Exemplo prático, código pronto e o que o Luhn não verifica no cartão.","how-to-validate-credit-card-with-javascript",{},"\u002Fblog\u002Fcomo-validar-cartao-de-credito-com-javascript","como-validar-cartao-de-credito-com-javascript","2026-09-17",{"title":1842,"description":2392},{"loc":2395,"lastmod":2400},"2026-10-04","blog\u002Fcomo-validar-cartao-de-credito-com-javascript",1371,"7e8sJBJxJops2Y0YucnNzm_BlbI8q6k2H_Vq6eCaYsE",{"id":2405,"title":2406,"articleCover":2407,"articleCoverEmbed":486,"articleCoverEmbedUploadDate":486,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":2408,"categoriesIds":3203,"description":3204,"enAlternateSlug":3205,"extension":471,"meta":3206,"navigation":473,"path":3207,"ptBrAlternateSlug":3208,"publishedAt":2397,"seo":3209,"sitemap":3210,"stem":3211,"updatedAt":1834,"wordCount":3212,"__hash__":3213},"blog\u002Fblog\u002Fcomo-validar-cpf-com-javascript.md","Como validar um CPF com JavaScript","\u002Fimages\u002Fblog\u002Fjavascript\u002Fcomo-validar-cpf-com-javascript.webp",{"type":14,"value":2409,"toc":3180},[2410,2413,2420,2424,2427,2435,2438,2441,2445,2448,2456,2459,2465,2468,2474,2477,2483,2486,2492,2495,2501,2506,2510,2513,2519,2522,2528,2531,2537,2540,2546,2549,2555,2562,2567,2570,2572,2579,2582,2784,2787,2842,2855,2858,2867,2874,2881,2889,2893,2896,2967,2970,2972,2976,2979,2988,2995,3002,3006,3009,3016,3025,3032,3035,3039,3042,3045,3054,3057,3061,3064,3067,3069,3073,3076,3083,3086,3090,3093,3106,3109,3112,3121,3125,3128,3131,3134,3138,3147,3150,3154,3157,3160,3164,3170,3178],[17,2411,2412],{},"Validar CPF no front-end ajuda a evitar erros em formulários de cadastro, checkout e login. No back-end, a validação é uma segunda barreira contra dados digitados incorretamente e fraudes mais básicas.",[17,2414,2415,2416,2419],{},"Neste artigo, você vai entender o algoritmo do CPF e implementar uma função de ",[63,2417,2418],{},"validação de CPF"," em JavaScript puro, sem biblioteca externa.",[24,2421,2423],{"id":2422},"o-que-são-os-dígitos-verificadores","O que são os dígitos verificadores",[17,2425,2426],{},"Um CPF tem 11 dígitos:",[312,2428,2429,2432],{},[315,2430,2431],{},"Os 9 primeiros são a base do documento.",[315,2433,2434],{},"Os 2 últimos são os dígitos verificadores.",[17,2436,2437],{},"Esses dois dígitos são calculados a partir dos anteriores. A ideia é detectar erros comuns de digitação, como trocar ou remover um número.",[17,2439,2440],{},"A validação matemática, porém, não confirma se o CPF existe, pertence a determinada pessoa ou está regular na Receita Federal. Ela apenas verifica se os dígitos obedecem ao algoritmo do CPF.",[843,2442,2444],{"id":2443},"primeiro-dígito-verificador","Primeiro dígito verificador",[17,2446,2447],{},"Considere o CPF sem formatação:",[87,2449,2454],{"className":2450,"code":2452,"language":2453,"meta":92},[2451],"language-text","52998224725\n","text",[75,2455,2452],{"__ignoreMap":92},[17,2457,2458],{},"Os 9 primeiros dígitos são:",[87,2460,2463],{"className":2461,"code":2462,"language":2453,"meta":92},[2451],"5 2 9 9 8 2 2 4 7\n",[75,2464,2462],{"__ignoreMap":92},[17,2466,2467],{},"Multiplicamos cada número pelos pesos de 10 a 2:",[87,2469,2472],{"className":2470,"code":2471,"language":2453,"meta":92},[2451],"5×10 + 2×9 + 9×8 + 9×7 + 8×6 + 2×5 + 2×4 + 4×3 + 7×2\n",[75,2473,2471],{"__ignoreMap":92},[17,2475,2476],{},"O resultado é:",[87,2478,2481],{"className":2479,"code":2480,"language":2453,"meta":92},[2451],"50 + 18 + 72 + 63 + 48 + 10 + 8 + 12 + 14 = 295\n",[75,2482,2480],{"__ignoreMap":92},[17,2484,2485],{},"Agora calculamos o resto da divisão por 11:",[87,2487,2490],{"className":2488,"code":2489,"language":2453,"meta":92},[2451],"295 % 11 = 9\n",[75,2491,2489],{"__ignoreMap":92},[17,2493,2494],{},"Como o resto é maior que 1, fazemos:",[87,2496,2499],{"className":2497,"code":2498,"language":2453,"meta":92},[2451],"11 - 9 = 2\n",[75,2500,2498],{"__ignoreMap":92},[17,2502,2503,2504,1519],{},"Portanto, o primeiro dígito verificador é ",[75,2505,1931],{},[843,2507,2509],{"id":2508},"segundo-dígito-verificador","Segundo dígito verificador",[17,2511,2512],{},"Agora usamos os 10 primeiros dígitos, incluindo o verificador calculado:",[87,2514,2517],{"className":2515,"code":2516,"language":2453,"meta":92},[2451],"5 2 9 9 8 2 2 4 7 2\n",[75,2518,2516],{"__ignoreMap":92},[17,2520,2521],{},"Aplicamos os pesos de 11 a 2:",[87,2523,2526],{"className":2524,"code":2525,"language":2453,"meta":92},[2451],"5×11 + 2×10 + 9×9 + 9×8 + 8×7 + 2×6 + 2×5 + 4×4 + 7×3 + 2×2\n",[75,2527,2525],{"__ignoreMap":92},[17,2529,2530],{},"A soma fica:",[87,2532,2535],{"className":2533,"code":2534,"language":2453,"meta":92},[2451],"55 + 20 + 81 + 72 + 56 + 12 + 10 + 16 + 21 + 4 = 347\n",[75,2536,2534],{"__ignoreMap":92},[17,2538,2539],{},"O resto da divisão por 11 é:",[87,2541,2544],{"className":2542,"code":2543,"language":2453,"meta":92},[2451],"347 % 11 = 6\n",[75,2545,2543],{"__ignoreMap":92},[17,2547,2548],{},"Como o resto é maior que 1:",[87,2550,2553],{"className":2551,"code":2552,"language":2453,"meta":92},[2451],"11 - 6 = 5\n",[75,2554,2552],{"__ignoreMap":92},[17,2556,2557,2558,2561],{},"O segundo dígito verificador é ",[75,2559,2560],{},"5",". Assim, o CPF completo é:",[87,2563,2565],{"className":2564,"code":2452,"language":2453,"meta":92},[2451],[75,2566,2452],{"__ignoreMap":92},[17,2568,2569],{},"Esse é o algoritmo do CPF: calcular o primeiro dígito, incorporá-lo à sequência e calcular o segundo.",[24,2571,1977],{"id":1976},[17,2573,2574,2575,2578],{},"A função precisa lidar com entradas formatadas, como ",[75,2576,2577],{},"529.982.247-25",", e também com uma sequência de números sem pontuação.",[17,2580,2581],{},"Uma implementação possível é esta:",[87,2583,2585],{"className":1983,"code":2584,"language":468,"meta":92,"style":92},"function validarCPF(cpf) {\n  \u002F\u002F Garante que a entrada seja tratada como texto\n  cpf = String(cpf).replace(\u002F\\D\u002Fg, \"\");\n\n  \u002F\u002F Um CPF válido deve ter exatamente 11 dígitos\n  if (cpf.length !== 11) {\n    return false;\n  }\n\n  \u002F\u002F Rejeita CPFs formados pelo mesmo dígito\n  if (\u002F^(\\d)\\1{10}$\u002F.test(cpf)) {\n    return false;\n  }\n\n  \u002F\u002F Calcula o primeiro dígito verificador\n  let soma = 0;\n\n  for (let i = 0; i \u003C 9; i++) {\n    soma += Number(cpf[i]) * (10 - i);\n  }\n\n  let resto = soma % 11;\n  const primeiroDigito = resto \u003C 2 ? 0 : 11 - resto;\n\n  \u002F\u002F O primeiro dígito calculado deve ser igual ao informado\n  if (primeiroDigito !== Number(cpf[9])) {\n    return false;\n  }\n\n  \u002F\u002F Calcula o segundo dígito verificador\n  soma = 0;\n\n  for (let i = 0; i \u003C 10; i++) {\n    soma += Number(cpf[i]) * (11 - i);\n  }\n\n  resto = soma % 11;\n  const segundoDigito = resto \u003C 2 ? 0 : 11 - resto;\n\n  \u002F\u002F O segundo dígito calculado também deve ser igual ao informado\n  return segundoDigito === Number(cpf[10]);\n}\n",[75,2586,2587,2592,2597,2602,2606,2611,2616,2620,2624,2628,2633,2638,2642,2646,2650,2655,2659,2663,2668,2673,2677,2681,2686,2691,2695,2700,2705,2709,2713,2717,2722,2727,2731,2736,2741,2745,2750,2756,2762,2767,2773,2779],{"__ignoreMap":92},[96,2588,2589],{"class":98,"line":99},[96,2590,2591],{},"function validarCPF(cpf) {\n",[96,2593,2594],{"class":98,"line":454},[96,2595,2596],{},"  \u002F\u002F Garante que a entrada seja tratada como texto\n",[96,2598,2599],{"class":98,"line":950},[96,2600,2601],{},"  cpf = String(cpf).replace(\u002F\\D\u002Fg, \"\");\n",[96,2603,2604],{"class":98,"line":956},[96,2605,953],{"emptyLinePlaceholder":473},[96,2607,2608],{"class":98,"line":980},[96,2609,2610],{},"  \u002F\u002F Um CPF válido deve ter exatamente 11 dígitos\n",[96,2612,2613],{"class":98,"line":990},[96,2614,2615],{},"  if (cpf.length !== 11) {\n",[96,2617,2618],{"class":98,"line":995},[96,2619,2020],{},[96,2621,2622],{"class":98,"line":1005},[96,2623,2025],{},[96,2625,2626],{"class":98,"line":1028},[96,2627,953],{"emptyLinePlaceholder":473},[96,2629,2630],{"class":98,"line":1034},[96,2631,2632],{},"  \u002F\u002F Rejeita CPFs formados pelo mesmo dígito\n",[96,2634,2635],{"class":98,"line":1044},[96,2636,2637],{},"  if (\u002F^(\\d)\\1{10}$\u002F.test(cpf)) {\n",[96,2639,2640],{"class":98,"line":2042},[96,2641,2020],{},[96,2643,2644],{"class":98,"line":2047},[96,2645,2025],{},[96,2647,2648],{"class":98,"line":2053},[96,2649,953],{"emptyLinePlaceholder":473},[96,2651,2652],{"class":98,"line":2059},[96,2653,2654],{},"  \u002F\u002F Calcula o primeiro dígito verificador\n",[96,2656,2657],{"class":98,"line":2065},[96,2658,2034],{},[96,2660,2661],{"class":98,"line":2070},[96,2662,953],{"emptyLinePlaceholder":473},[96,2664,2665],{"class":98,"line":2076},[96,2666,2667],{},"  for (let i = 0; i \u003C 9; i++) {\n",[96,2669,2670],{"class":98,"line":2082},[96,2671,2672],{},"    soma += Number(cpf[i]) * (10 - i);\n",[96,2674,2675],{"class":98,"line":2088},[96,2676,2025],{},[96,2678,2679],{"class":98,"line":2094},[96,2680,953],{"emptyLinePlaceholder":473},[96,2682,2683],{"class":98,"line":2100},[96,2684,2685],{},"  let resto = soma % 11;\n",[96,2687,2688],{"class":98,"line":2106},[96,2689,2690],{},"  const primeiroDigito = resto \u003C 2 ? 0 : 11 - resto;\n",[96,2692,2693],{"class":98,"line":2112},[96,2694,953],{"emptyLinePlaceholder":473},[96,2696,2697],{"class":98,"line":2117},[96,2698,2699],{},"  \u002F\u002F O primeiro dígito calculado deve ser igual ao informado\n",[96,2701,2702],{"class":98,"line":2123},[96,2703,2704],{},"  if (primeiroDigito !== Number(cpf[9])) {\n",[96,2706,2707],{"class":98,"line":2129},[96,2708,2020],{},[96,2710,2711],{"class":98,"line":2134},[96,2712,2025],{},[96,2714,2715],{"class":98,"line":2139},[96,2716,953],{"emptyLinePlaceholder":473},[96,2718,2719],{"class":98,"line":2145},[96,2720,2721],{},"  \u002F\u002F Calcula o segundo dígito verificador\n",[96,2723,2724],{"class":98,"line":2150},[96,2725,2726],{},"  soma = 0;\n",[96,2728,2729],{"class":98,"line":2155},[96,2730,953],{"emptyLinePlaceholder":473},[96,2732,2733],{"class":98,"line":2161},[96,2734,2735],{},"  for (let i = 0; i \u003C 10; i++) {\n",[96,2737,2738],{"class":98,"line":2167},[96,2739,2740],{},"    soma += Number(cpf[i]) * (11 - i);\n",[96,2742,2743],{"class":98,"line":2173},[96,2744,2025],{},[96,2746,2748],{"class":98,"line":2747},36,[96,2749,953],{"emptyLinePlaceholder":473},[96,2751,2753],{"class":98,"line":2752},37,[96,2754,2755],{},"  resto = soma % 11;\n",[96,2757,2759],{"class":98,"line":2758},38,[96,2760,2761],{},"  const segundoDigito = resto \u003C 2 ? 0 : 11 - resto;\n",[96,2763,2765],{"class":98,"line":2764},39,[96,2766,953],{"emptyLinePlaceholder":473},[96,2768,2770],{"class":98,"line":2769},40,[96,2771,2772],{},"  \u002F\u002F O segundo dígito calculado também deve ser igual ao informado\n",[96,2774,2776],{"class":98,"line":2775},41,[96,2777,2778],{},"  return segundoDigito === Number(cpf[10]);\n",[96,2780,2782],{"class":98,"line":2781},42,[96,2783,1664],{},[17,2785,2786],{},"Exemplos de uso:",[87,2788,2790],{"className":1983,"code":2789,"language":468,"meta":92,"style":92},"console.log(validarCPF(\"529.982.247-25\"));\n\u002F\u002F true\n\nconsole.log(validarCPF(\"52998224725\"));\n\u002F\u002F true\n\nconsole.log(validarCPF(\"529.982.247-26\"));\n\u002F\u002F false\n\nconsole.log(validarCPF(\"111.111.111-11\"));\n\u002F\u002F false\n",[75,2791,2792,2797,2802,2806,2811,2815,2819,2824,2829,2833,2838],{"__ignoreMap":92},[96,2793,2794],{"class":98,"line":99},[96,2795,2796],{},"console.log(validarCPF(\"529.982.247-25\"));\n",[96,2798,2799],{"class":98,"line":454},[96,2800,2801],{},"\u002F\u002F true\n",[96,2803,2804],{"class":98,"line":950},[96,2805,953],{"emptyLinePlaceholder":473},[96,2807,2808],{"class":98,"line":956},[96,2809,2810],{},"console.log(validarCPF(\"52998224725\"));\n",[96,2812,2813],{"class":98,"line":980},[96,2814,2801],{},[96,2816,2817],{"class":98,"line":990},[96,2818,953],{"emptyLinePlaceholder":473},[96,2820,2821],{"class":98,"line":995},[96,2822,2823],{},"console.log(validarCPF(\"529.982.247-26\"));\n",[96,2825,2826],{"class":98,"line":1005},[96,2827,2828],{},"\u002F\u002F false\n",[96,2830,2831],{"class":98,"line":1028},[96,2832,953],{"emptyLinePlaceholder":473},[96,2834,2835],{"class":98,"line":1034},[96,2836,2837],{},"console.log(validarCPF(\"111.111.111-11\"));\n",[96,2839,2840],{"class":98,"line":1044},[96,2841,2828],{},[17,2843,2844,2845,2848,2849,2851,2852,1519],{},"O trecho ",[75,2846,2847],{},"replace(\u002F\\D\u002Fg, '')"," remove tudo que não for dígito. Isso permite aceitar tanto ",[75,2850,2577],{}," quanto ",[75,2853,2854],{},"52998224725",[17,2856,2857],{},"A expressão regular usada para dígitos repetidos merece atenção:",[87,2859,2861],{"className":1983,"code":2860,"language":468,"meta":92,"style":92},"\u002F^(\\d)\\1{10}$\u002F;\n",[75,2862,2863],{"__ignoreMap":92},[96,2864,2865],{"class":98,"line":99},[96,2866,2860],{},[17,2868,2869,2870,2873],{},"Ela identifica uma sequência de 11 caracteres formada pelo mesmo dígito. Isso impede que valores como ",[75,2871,2872],{},"111.111.111-11"," sejam aceitos.",[17,2875,2876,2877,2880],{},"Esse é um detalhe que costuma pegar quem já bateu cabeça com o problema: CPFs com todos os dígitos iguais passam pela conta matemática, mas devem ser rejeitados explicitamente. Se você implementar apenas os cálculos, ",[75,2878,2879],{},"11111111111"," será considerado válido pelo seu código.",[17,2882,2883,2884,1519],{},"Se quiser testar entradas rapidamente sem criar um formulário, use ",[32,2885,2888],{"href":2886,"rel":2887},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fvalidador-de-cpf",[36],"nosso validador de CPF online, gratuito",[843,2890,2892],{"id":2891},"validação-no-formulário","Validação no formulário",[17,2894,2895],{},"Você pode chamar a função no evento de envio do formulário:",[87,2897,2899],{"className":1983,"code":2898,"language":468,"meta":92,"style":92},"const formulario = document.querySelector(\"#formulario\");\nconst campoCPF = document.querySelector(\"#cpf\");\nconst mensagem = document.querySelector(\"#mensagem\");\n\nformulario.addEventListener(\"submit\", function (evento) {\n  evento.preventDefault();\n\n  if (!validarCPF(campoCPF.value)) {\n    mensagem.textContent = \"Informe um CPF válido.\";\n    return;\n  }\n\n  mensagem.textContent = \"CPF válido.\";\n});\n",[75,2900,2901,2906,2911,2916,2920,2925,2930,2934,2939,2944,2949,2953,2957,2962],{"__ignoreMap":92},[96,2902,2903],{"class":98,"line":99},[96,2904,2905],{},"const formulario = document.querySelector(\"#formulario\");\n",[96,2907,2908],{"class":98,"line":454},[96,2909,2910],{},"const campoCPF = document.querySelector(\"#cpf\");\n",[96,2912,2913],{"class":98,"line":950},[96,2914,2915],{},"const mensagem = document.querySelector(\"#mensagem\");\n",[96,2917,2918],{"class":98,"line":956},[96,2919,953],{"emptyLinePlaceholder":473},[96,2921,2922],{"class":98,"line":980},[96,2923,2924],{},"formulario.addEventListener(\"submit\", function (evento) {\n",[96,2926,2927],{"class":98,"line":990},[96,2928,2929],{},"  evento.preventDefault();\n",[96,2931,2932],{"class":98,"line":995},[96,2933,953],{"emptyLinePlaceholder":473},[96,2935,2936],{"class":98,"line":1005},[96,2937,2938],{},"  if (!validarCPF(campoCPF.value)) {\n",[96,2940,2941],{"class":98,"line":1028},[96,2942,2943],{},"    mensagem.textContent = \"Informe um CPF válido.\";\n",[96,2945,2946],{"class":98,"line":1034},[96,2947,2948],{},"    return;\n",[96,2950,2951],{"class":98,"line":1044},[96,2952,2025],{},[96,2954,2955],{"class":98,"line":2042},[96,2956,953],{"emptyLinePlaceholder":473},[96,2958,2959],{"class":98,"line":2047},[96,2960,2961],{},"  mensagem.textContent = \"CPF válido.\";\n",[96,2963,2964],{"class":98,"line":2053},[96,2965,2966],{},"});\n",[17,2968,2969],{},"Essa validação melhora a experiência no navegador, mas não substitui a validação no servidor. Qualquer código executado no front-end pode ser alterado ou ignorado pelo cliente. O back-end deve repetir a validação antes de salvar ou processar o dado.",[24,2971,2239],{"id":2238},[843,2973,2975],{"id":2974},"validar-cpf-só-com-regex-de-formato","Validar CPF só com regex de formato",[17,2977,2978],{},"Uma expressão como esta:",[87,2980,2982],{"className":1983,"code":2981,"language":468,"meta":92,"style":92},"\u002F^\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}$\u002F;\n",[75,2983,2984],{"__ignoreMap":92},[96,2985,2986],{"class":98,"line":99},[96,2987,2981],{},[17,2989,2990,2991,2994],{},"verifica apenas se o texto tem o formato ",[75,2992,2993],{},"000.000.000-00",". Ela não calcula os dígitos verificadores.",[17,2996,2997,2998,3001],{},"Por exemplo, ",[75,2999,3000],{},"123.456.789-00"," pode estar perfeitamente formatado e ainda assim ser um CPF inválido. Regex pode ajudar a conferir a aparência da entrada, mas não substitui o algoritmo do CPF.",[843,3003,3005],{"id":3004},"esquecer-os-zeros-à-esquerda","Esquecer os zeros à esquerda",[17,3007,3008],{},"CPF é identificador, não número para fazer operações matemáticas comuns. Por isso, trate-o como string.",[17,3010,3011,3012,3015],{},"Se você converter um CPF para ",[75,3013,3014],{},"Number",", um valor com zero inicial pode perder esse zero:",[87,3017,3019],{"className":1983,"code":3018,"language":468,"meta":92,"style":92},"const cpf = Number(\"012.345.678-90\");\n",[75,3020,3021],{"__ignoreMap":92},[96,3022,3023],{"class":98,"line":99},[96,3024,3018],{},[17,3026,3027,3028,3031],{},"Além disso, números muito grandes não devem ser usados como representação principal de documentos. A função deste artigo converte a entrada para texto com ",[75,3029,3030],{},"String(cpf)"," e remove a formatação antes de calcular.",[17,3033,3034],{},"Na prática, prefira manter o valor vindo do campo HTML como string desde o início.",[843,3036,3038],{"id":3037},"não-normalizar-a-entrada","Não normalizar a entrada",[17,3040,3041],{},"Se o código espera exatamente 11 dígitos, ele pode rejeitar um CPF formatado antes mesmo de fazer o cálculo.",[17,3043,3044],{},"Esta etapa resolve o problema:",[87,3046,3048],{"className":1983,"code":3047,"language":468,"meta":92,"style":92},"cpf = String(cpf).replace(\u002F\\D\u002Fg, \"\");\n",[75,3049,3050],{"__ignoreMap":92},[96,3051,3052],{"class":98,"line":99},[96,3053,3047],{},[17,3055,3056],{},"Ela remove pontos, traços, espaços e outros caracteres não numéricos. Depois disso, a função verifica se sobraram exatamente 11 dígitos.",[843,3058,3060],{"id":3059},"validar-apenas-no-navegador","Validar apenas no navegador",[17,3062,3063],{},"A validação no front-end é útil para dar retorno imediato, mas não é uma camada de segurança. Um usuário pode fazer uma requisição diretamente ao servidor sem passar pelo JavaScript da página.",[17,3065,3066],{},"A mesma regra deve existir no back-end, de preferência em uma função centralizada e coberta por testes.",[24,3068,1725],{"id":1724},[843,3070,3072],{"id":3071},"como-saber-se-um-cpf-é-válido","Como saber se um CPF é válido?",[17,3074,3075],{},"Primeiro, remova pontos e traço e confirme que restaram 11 dígitos. Depois, rejeite sequências com todos os dígitos iguais e calcule os dois dígitos verificadores conforme o algoritmo do CPF.",[17,3077,3078,3079,3082],{},"O CPF só será matematicamente válido se os dois dígitos calculados forem iguais aos dois últimos dígitos informados. A função ",[75,3080,3081],{},"validarCPF(cpf)"," apresentada neste artigo executa todas essas etapas.",[17,3084,3085],{},"Isso não significa que o documento esteja ativo, regular ou associado a uma pessoa específica. Significa apenas que ele passa pela validação matemática.",[843,3087,3089],{"id":3088},"como-calcular-o-dígito-verificador-do-cpf","Como calcular o dígito verificador do CPF?",[17,3091,3092],{},"Para o primeiro dígito, multiplique os 9 dígitos base pelos pesos de 10 a 2. Some os resultados e calcule o resto da divisão por 11.",[312,3094,3095,3100],{},[315,3096,3097,3098,1519],{},"Se o resto for 0 ou 1, o dígito será ",[75,3099,974],{},[315,3101,3102,3103,1519],{},"Caso contrário, o dígito será ",[75,3104,3105],{},"11 - resto",[17,3107,3108],{},"Para o segundo dígito, faça a mesma operação usando os 10 primeiros dígitos e os pesos de 11 a 2.",[17,3110,3111],{},"Em JavaScript, a parte central do cálculo pode ser escrita assim:",[87,3113,3115],{"className":1983,"code":3114,"language":468,"meta":92,"style":92},"const digito = resto \u003C 2 ? 0 : 11 - resto;\n",[75,3116,3117],{"__ignoreMap":92},[96,3118,3119],{"class":98,"line":99},[96,3120,3114],{},[843,3122,3124],{"id":3123},"validar-cpf-é-a-mesma-coisa-que-consultar-na-receita-federal","Validar CPF é a mesma coisa que consultar na Receita Federal?",[17,3126,3127],{},"Não. A validação matemática é uma verificação local: o sistema calcula os dígitos e compara o resultado com o CPF informado.",[17,3129,3130],{},"Uma consulta oficial é outra operação. Ela pode verificar informações cadastrais e a situação do CPF em uma base oficial, normalmente por meio de um serviço autorizado ou dos canais disponibilizados pela Receita Federal.",[17,3132,3133],{},"Portanto, um CPF pode passar pelo algoritmo e ainda não estar regular, não existir no cadastro consultado ou não pertencer à pessoa que o informou. O código JavaScript não confirma identidade nem situação cadastral.",[843,3135,3137],{"id":3136},"dá-para-gerar-um-cpf-válido-para-testes","Dá para gerar um CPF válido para testes?",[17,3139,3140,3141,3146],{},"Sim. Para testar máscaras, formulários e APIs, você pode usar números que passam pela validação matemática sem usar dados reais. Se você precisa de números de CPF válidos só para testar formulários, ",[32,3142,3145],{"href":3143,"rel":3144},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-cpf",[36],"nosso gerador de CPF"," resolve isso rapidinho.",[17,3148,3149],{},"Use dados de teste de forma controlada e deixe claro, no ambiente da equipe, que eles são fictícios. Também evite colocar documentos reais em exemplos públicos, arquivos de teste ou repositórios.",[843,3151,3153],{"id":3152},"a-função-valida-se-o-cpf-pertence-ao-usuário","A função valida se o CPF pertence ao usuário?",[17,3155,3156],{},"Não. Ela verifica somente o formato normalizado, a quantidade de dígitos, a regra dos dígitos verificadores e a rejeição de sequências repetidas.",[17,3158,3159],{},"Para confirmar titularidade, seria necessária uma etapa diferente, com uma fonte oficial ou um fluxo de verificação apropriado. A validação local não substitui esse processo.",[24,3161,3163],{"id":3162},"próximos-passos","Próximos passos",[17,3165,3166,3167,3169],{},"Agora você já tem o algoritmo do CPF e uma função ",[75,3168,3081],{}," pronta para adaptar ao seu projeto. Coloque a validação no front-end para orientar o usuário e repita a regra no back-end antes de persistir ou aceitar o cadastro.",[17,3171,3172,3173,3177],{},"Se quiser conferir valores sem escrever código, acesse ",[32,3174,3176],{"href":2886,"rel":3175},[36],"o nosso verificador de CPF online",". Depois, vale transformar os exemplos deste artigo em testes automatizados para cobrir entradas formatadas, CPFs inválidos e documentos com zeros à esquerda.",[450,3179,777],{},{"title":92,"searchDepth":454,"depth":454,"links":3181},[3182,3186,3189,3195,3202],{"id":2422,"depth":454,"text":2423,"children":3183},[3184,3185],{"id":2443,"depth":950,"text":2444},{"id":2508,"depth":950,"text":2509},{"id":1976,"depth":454,"text":1977,"children":3187},[3188],{"id":2891,"depth":950,"text":2892},{"id":2238,"depth":454,"text":2239,"children":3190},[3191,3192,3193,3194],{"id":2974,"depth":950,"text":2975},{"id":3004,"depth":950,"text":3005},{"id":3037,"depth":950,"text":3038},{"id":3059,"depth":950,"text":3060},{"id":1724,"depth":454,"text":1725,"children":3196},[3197,3198,3199,3200,3201],{"id":3071,"depth":950,"text":3072},{"id":3088,"depth":950,"text":3089},{"id":3123,"depth":950,"text":3124},{"id":3136,"depth":950,"text":3137},{"id":3152,"depth":950,"text":3153},{"id":3162,"depth":454,"text":3163},[468,2391],"Aprenda como validar um CPF com JavaScript puro, calcular os dígitos verificadores, tratar a formatação e rejeitar sequências inválidas em formulários web.","how-to-validate-cpf-with-javascript",{},"\u002Fblog\u002Fcomo-validar-cpf-com-javascript","como-validar-cpf-com-javascript",{"title":2406,"description":3204},{"loc":3207,"lastmod":1834},"blog\u002Fcomo-validar-cpf-com-javascript",1197,"ChuIrFW1vkcO6_sAKg1e6VanKeJwSnz4I_S9D9B48-w",{"id":3215,"title":3216,"articleCover":3217,"articleCoverEmbed":486,"articleCoverEmbedUploadDate":486,"articleCoverHeight":10,"articleCoverWidth":11,"authorId":12,"body":3218,"categoriesIds":3520,"description":3521,"enAlternateSlug":3522,"extension":471,"meta":3523,"navigation":473,"path":3524,"ptBrAlternateSlug":3525,"publishedAt":3526,"seo":3527,"sitemap":3528,"stem":3538,"updatedAt":1834,"wordCount":3539,"__hash__":3540},"blog\u002Fblog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores.md","Criei um Hub de Ferramentas Web Gratuitas para Devs","\u002Fimages\u002Fblog\u002Fferramentas\u002Fhub-ferramentas-gratuitas-para-desenvolvedores.webp",{"type":14,"value":3219,"toc":3501},[3220,3223,3234,3238,3242,3250,3253,3256,3263,3267,3277,3281,3291,3295,3299,3308,3312,3321,3325,3329,3337,3341,3345,3353,3357,3361,3374,3378,3382,3386,3393,3396,3400,3403,3406,3410,3413,3416,3420,3435,3449,3453,3459,3466,3470,3473,3487,3491],[17,3221,3222],{},"Sabe aquele momento em que você precisa gerar um CPF para testar um formulário? Ou quando precisa validar um cartão de crédito fake no ambiente de desenvolvimento? Durante minha carreira como dev, sempre recorria a diferentes sites para essas tarefas simples, mas essenciais do dia a dia.",[17,3224,3225,3226,3233],{},"Cada site possuía diferentes layouts e experiências de usuário, algumas boas, outras não. Pensando em criar algo que centralize essas diferentes ferramentas com uma interface simples e com excelente experiência de usuário, que criei o ",[63,3227,3228],{},[32,3229,3232],{"href":3230,"rel":3231},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas",[36],"Hub de Ferramentas para programadores do Código ao Ponto",", um hub totalmente gratuito que reúne várias ferramentas em um único local, que são diretas ao ponto e que funcionam sem a necessidade de criar um cadastro.",[24,3235,3237],{"id":3236},"quais-ferramentas-estão-disponíveis-no-hub","Quais ferramentas estão disponíveis no Hub?",[843,3239,3241],{"id":3240},"planning-poker-online","Planning Poker Online",[17,3243,3244,3249],{},[32,3245,3248],{"href":3246,"rel":3247},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fplanning-poker",[36],"A ferramenta mais completa do hub",". Crie uma sala, compartilhe o link com o time (sem necessidade de cadastro), e todos podem votar simultaneamente nas estimativas de tarefas.",[17,3251,3252],{},"A ferramenta funciona em tempo real com WebSocket - quando alguém vota, todos veem instantaneamente. Tem temporizador da sessão, lista de participantes com status, e opções de votação além da sequência tradicional de Fibonacci.",[17,3254,3255],{},"É o tipo de ferramenta \"mão na roda\" quando seu time precisa fazer uma Sprint Planning e não encontra um Planning Poker de qualidade e gratuito.",[3257,3258],"img",{"alt":3259,"height":3260,"src":3261,"width":3262},"interface da ferramenta Planning Poker",405,"\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-planning-poker-gratuito.webp",768,[843,3264,3266],{"id":3265},"gerador-e-validador-de-cpf","Gerador e Validador de CPF",[17,3268,3269,3270,3276],{},"Uma das ferramentas mais populares do hub. O ",[63,3271,3272],{},[32,3273,3275],{"href":3143,"rel":3274},[36],"Gerador de CPF"," cria números válidos instantaneamente para uso em ambientes de teste. Esse sucesso de acessos se deu devido à sua boa posição nas páginas de resultado de pesquisa do Google para o termo \"Gerador de CPF\", variando entre a segunda e quarta posição.",[3257,3278],{"alt":3279,"height":3260,"src":3280,"width":3262},"interface da ferramenta Gerador de CPF","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-cpf.webp",[17,3282,3283,3284,3290],{},"Como complemento, também foi criado o ",[63,3285,3286],{},[32,3287,3289],{"href":2886,"rel":3288},[36],"Validador de CPF"," que verifica se um número é válido estruturalmente com feedback imediato.",[3257,3292],{"alt":3293,"height":3260,"src":3294,"width":3262},"interface da ferramenta Validador de CPF","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-validador-de-cpf.webp",[843,3296,3298],{"id":3297},"gerador-e-validador-de-cartão-de-crédito","Gerador e Validador de Cartão de Crédito",[17,3300,824,3301,3307],{},[63,3302,3303],{},[32,3304,3306],{"href":2294,"rel":3305},[36],"Gerador de cartão de crédito"," permite selecionar a bandeira (Visa, Mastercard, American Express, etc.) e cria dados fictícios completos: número do cartão, CVV e data de validade. Cada campo tem um botão de cópia rápida ao lado.",[3257,3309],{"alt":3310,"height":3260,"src":3311,"width":3262},"interface da ferramenta Gerador de Cartão de Crédito","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-cartao-de-credito.webp",[17,3313,824,3314,3320],{},[63,3315,3316],{},[32,3317,3319],{"href":2190,"rel":3318},[36],"Validador de cartão de crédito"," identifica automaticamente a bandeira e verifica se o número é estruturalmente válido. Essencial para testar fluxos de pagamento.",[3257,3322],{"alt":3323,"height":3260,"src":3324,"width":3262},"interface da ferramenta Validador de Cartão de Crédito","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-validador-de-cartao-de-credito.webp",[843,3326,3328],{"id":3327},"contador-de-palavras-e-caracteres","Contador de Palavras e Caracteres",[17,3330,3331,3336],{},[32,3332,3335],{"href":3333,"rel":3334},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fcontador-de-caracteres-e-palavras",[36],"Conta em tempo real enquanto você digita ou cola texto",". Mostra caracteres totais, caracteres sem espaços, número de espaços e total de palavras. Útil para respeitar limites de caracteres em APIs ou validar campos de formulário.",[3257,3338],{"alt":3339,"height":3260,"src":3340,"width":3262},"interface da ferramenta Contador de Caracteres e Palavras","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-contador-de-caracteres-e-palavras.webp",[843,3342,3344],{"id":3343},"conversor-de-formato-de-data","Conversor de Formato de Data",[17,3346,3347,3352],{},[32,3348,3351],{"href":3349,"rel":3350},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fconversor-de-formato-de-data",[36],"Converte datas para os formatos mais usados em desenvolvimento",": ISO String, Timestamp e UTC String. Você pode usar a data\u002Fhora atual ou inserir uma data específica, com botão de cópia rápida no resultado.",[3257,3354],{"alt":3355,"height":3260,"src":3356,"width":3262},"interface da ferramenta Conversor de Formato de Data","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramentas-gerador-e-conversor-de-formato-de-datas.webp",[843,3358,3360],{"id":3359},"gerador-de-link-do-whatsapp","Gerador de Link do WhatsApp",[17,3362,3363,3364,3369,3370,3373],{},"Insira o número de telefone (com seleção de código do país) e a mensagem desejada. ",[32,3365,3368],{"href":3366,"rel":3367},"https:\u002F\u002Fcodigoaoponto.com\u002Fferramentas\u002Fgerador-de-url-mensagem-do-whatsapp",[36],"A ferramenta"," gera um link direto para abrir a conversa no WhatsApp, com ",[63,3371,3372],{},"pré-visualização em tempo real"," mostrando exatamente como a mensagem vai aparecer, incluindo formatações e emojis. Muito útil para testar os textos que serão usados naquelas tarefas em que o usuário clica em \"Entrar em contato pelo Whatsapp\".",[3257,3375],{"alt":3376,"height":3260,"src":3377,"width":3262},"interface da ferramenta Gerador de URL pré-preenchida com texto no Whatsapp","\u002Fimages\u002Fblog\u002Fferramentas\u002Fferramenta-gerador-de-link-compartilhavel-no-whatsapp.webp",[24,3379,3381],{"id":3380},"decisões-de-design-e-usabilidade","Decisões de design e usabilidade",[843,3383,3385],{"id":3384},"sem-fricção-sem-barreiras","Sem fricção, sem barreiras",[17,3387,3388,3389,3392],{},"A decisão mais importante do projeto foi: ",[63,3390,3391],{},"nenhuma ferramenta exige cadastro",". Isso foi não-negociável desde o início. Acesse, use, pronto.",[17,3394,3395],{},"Para o Planning Poker, que é colaborativo, você pode criar as salas com links compartilháveis. Sem login, sem senha, sem complicação.",[843,3397,3399],{"id":3398},"interface-limpa-e-intuitiva","Interface limpa e intuitiva",[17,3401,3402],{},"Cada ferramenta segue um padrão visual consistente: área de input à esquerda, resultado à direita, e botões de ação bem visíveis.",[17,3404,3405],{},"Abaixo de cada ferramenta, tem uma seção educativa explicando casos de uso, exemplos práticos e como aquela ferramenta pode ajudar no dia a dia. A ideia é que mesmo quem nunca usou entenda rapidamente o valor.",[843,3407,3409],{"id":3408},"acessível-em-português-e-inglês","Acessível em português e inglês",[17,3411,3412],{},"Desde o início, implementei internacionalização. O sistema detecta automaticamente o idioma do navegador, mas você pode trocar manualmente quando quiser.",[17,3414,3415],{},"Português para atender a comunidade brasileira, inglês para alcançar desenvolvedores do mundo todo. A arquitetura está preparada para adicionar novos idiomas facilmente.",[843,3417,3419],{"id":3418},"responsivo-e-rápido","Responsivo e rápido",[17,3421,3422,3423,3428,3429,3434],{},"Todas essas ferramentas possuem suas versões em ",[32,3424,3427],{"href":3425,"rel":3426},"https:\u002F\u002Fcodigoaoponto.com\u002Fen\u002Ftools",[36],"Inglês com o I18N"," e são testadas com o ",[32,3430,3433],{"href":3431,"rel":3432},"https:\u002F\u002Fpagespeed.web.dev\u002F",[36],"Lighthouse\u002FPageSpeed Insights"," para garantir boa performance de carregamento e estabilidade visual.",[17,3436,3437,3438,156,3443,3448],{},"A como meta mínima de pontuação foi de 90 pontos no PageSpeed Insights em todas as categorias, o que é um grande desafio, especialmente quando se usa scripts de terceiros como ",[32,3439,3442],{"href":3440,"rel":3441},"https:\u002F\u002Fdevelopers.google.com\u002Fanalytics",[36],"Google Analytics",[32,3444,3447],{"href":3445,"rel":3446},"https:\u002F\u002Fadsense.google.com\u002Fstart",[36],"Google Adsense",", mas que fazendo as devidas otimizações, entregam uma ótima velocidade de carregamento.",[24,3450,3452],{"id":3451},"a-stack-por-trás","A stack por trás",[17,3454,824,3455,3458],{},[63,3456,3457],{},"Nuxt 4"," foi escolhido no frontend pelo seu foco em performance e SEO, aspectos muito importantes para ser bem ranqueado pelo Google.",[17,3460,3461,3462,3465],{},"No backend, foi escolhido o ",[63,3463,3464],{},"NestJS"," pela sua arquitetura modular e suporte nativo a WebSocket, necessário para o Planning Poker. Além de também ser em JavaScript, facilitando o desenvolvimento Full Stack do projeto.",[24,3467,3469],{"id":3468},"o-que-vem-por-aí","O que vem por aí",[17,3471,3472],{},"O backlog tem algumas ideias interessantes:",[312,3474,3475,3481],{},[315,3476,3477,3480],{},[63,3478,3479],{},"Sprint Retro"," para cerimônias de retrospectiva",[315,3482,3483,3486],{},[63,3484,3485],{},"Mais utilitários"," conforme a comunidade for sugerindo",[24,3488,3490],{"id":3489},"quer-conhecer","Quer conhecer?",[17,3492,3493,3494,3500],{},"A ferramenta tem ajudado centenas de usuários diariamente, você também pode ser um deles ",[63,3495,3496],{},[32,3497,3499],{"href":3230,"rel":3498},[36],"Clicando aqui",", espero te ajudar, muito obrigado 🙋🏻",{"title":92,"searchDepth":454,"depth":454,"links":3502},[3503,3511,3517,3518,3519],{"id":3236,"depth":454,"text":3237,"children":3504},[3505,3506,3507,3508,3509,3510],{"id":3240,"depth":950,"text":3241},{"id":3265,"depth":950,"text":3266},{"id":3297,"depth":950,"text":3298},{"id":3327,"depth":950,"text":3328},{"id":3343,"depth":950,"text":3344},{"id":3359,"depth":950,"text":3360},{"id":3380,"depth":454,"text":3381,"children":3512},[3513,3514,3515,3516],{"id":3384,"depth":950,"text":3385},{"id":3398,"depth":950,"text":3399},{"id":3408,"depth":950,"text":3409},{"id":3418,"depth":950,"text":3419},{"id":3451,"depth":454,"text":3452},{"id":3468,"depth":454,"text":3469},{"id":3489,"depth":454,"text":3490},[2391],"Criei um hub de ferramentas web gratuitas para programadores: gerador de CPF, validadores, Planning Poker e outros utilitários, em português e inglês.","free-developer-tools-hub",{},"\u002Fblog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores","hub-de-ferramentas-gratuitas-para-desenvolvedores","2026-01-06",{"title":3216,"description":3521},{"loc":3524,"images":3529,"lastmod":1834},[3530,3531,3532,3533,3534,3535,3536,3537],{"loc":3261},{"loc":3280},{"loc":3294},{"loc":3311},{"loc":3324},{"loc":3340},{"loc":3356},{"loc":3377},"blog\u002Fhub-de-ferramentas-gratuitas-para-desenvolvedores",1034,"yjmUjnoFNggMq3x61INaFg-ySaqtVv517zm-qVl13o4",1794009277238]