v1.52.0
como usar
guia sem manual · atualizado em 31/10/2026

Um app que imprime etiqueta de verdade — e a história de como ele chegou aqui

Isso aqui não é release note. É a história do freeLabel contada do começo: o problema, as tentativas que falharam, o bug que parecia impossível, as medições que ninguém faz, e o que já dá para fazer hoje com ele.

📱 feito para ler no celular 🖨️ SLP650 (203 dpi) 🔌 100% offline 🧉 sem instalação, sem senha de admin
⬇ baixar o app (v1.52.0) como abrir e imprimir 3,1 MB · macOS · já vem com o filtro da impressora — nada para instalar
Tela do freeLabel: painel de etiqueta, canvas com a etiqueta de exemplo e galeria de modelos a tela de trabalho hoje — essa é a versão 1.52.0
v1.52versão atual — a 1.0 nasceu em 29/out
0bytes que cabem num QR (EC L)
0dpi da térmica — 8 pontos por mm
0instalações necessárias

Role para baixo. Cada capítulo tem print de verdade — nada de mockup.

01
o problema

Uma etiqueta, uma impressora emprestada e nenhuma senha de administrador

Tudo começou com uma situação bem comum em campo: preciso identificar equipamento — bomba, compressor, quadro elétrico, válvula — com etiqueta que aguente o ambiente e que dê para ler daqui a dois anos, com graxa em cima. A solução óbvia é uma impressora térmica de etiquetas. A que apareceu foi uma Seiko SLP650.

O problema não é a impressora. É o caminho até ela:

Primeira lição do projeto: o problema nunca foi “desenhar uma etiqueta”. Foi chegar no papel sem pedir senha para ninguém. Todo o resto veio depois.
02
a virada

O filtro oficial da SII + o driver que o macOS já tem

Depois de muita tentativa (e bastante papel jogado fora), apareceu o caminho: a própria SII distribui um filtro CUPS — um programinha que converte imagem em comandos da impressora. Ele se chama rastertosiislp e vem dentro do pacote oficial, que é só um monte de arquivos.

A ideia então foi simples e teimosa: se o problema é “instalar”, então não instale nada. Copiar o filtro oficial para uma pasta comum, usar o backend USB que já existe no macOS, e chamar a impressão por script — tudo dentro da pasta do usuário, sem sudo, sem driver assinado, sem tocar no sistema.

O que passou a funcionar

  • Enviar PNG em 203 dpi direto para a SLP650
  • Escolher o tamanho do rolo (SRLDPI) pelo próprio comando
  • Rodar de pendrive, de pasta solta, sem instalar
  • Ver o log de cada impressão e saber por que falhou

O que o macOS ainda atrapalha

As pastas Downloads, Desktop e Documents são protegidas (TCC): um app de fora não pode executar arquivos de lá. O app detecta, avisa e manda mover a pasta para ~/freeLabel — foi a primeira de uma longa série de brigas com o sistema.

Nasceram aí os primeiros comandos numerados: 0-liberar (tira a quarentena), 1-diagnostico, 2-imprimir, 3-teste-minimo — que imprime um SLP de teste para separar “problema de transporte” de “problema de conversão”. Até hoje eles estão no pacote, porque diagnóstico é metade do trabalho.

03
o designer

Se já sei mandar pixels, então dá para desenhar a etiqueta

Com o caminho de impressão resolvido, o próximo problema era óbvio: eu estava desenhando etiqueta em editor de imagem, medindo pixel na régua, torcendo para o texto caber. Isso não escala.

A escolha foi radical de propósito: um único arquivo HTML, aberto numa janela própria, sem servidor de internet, sem build complexo. Todas as bibliotecas (código de barras, QR, leitor de planilha) ficam dentro do arquivo. Consequência: funciona sem internet, funciona em Mac antigo, funciona se você copiar a pasta para um pendrive.

Etiqueta com texto, código de barras CODE128 e QR code
Texto, CODE128 e QR no mesmo layout. Tudo desenhado em milímetros, não em pixels.

Por que milímetros importam tanto

A etiqueta é 54 × 101 mm (rolo SLP-SRL). A térmica imprime a 203 dpi, o que dá exatamente 8 pontos por milímetro. Se o layout fosse em pixel de tela, cada zoom bagunçaria a medida. Em milímetros, o app sabe que 1 mm = 8 pontos e consegue gerar o PNG já no tamanho final de impressão — sem “ajustar à página” e sem sair deslocado.

Detalhe técnico: a área imprimível não é a etiqueta inteira
A SLP650 não imprime até a borda. Para o rolo SRL a área útil medida no PPD oficial é x 2,66 → 51,34 mm e y 2,70 → 98,30 mm. O app guarda essa tabela por tamanho (2RLE, 1RL, SRL, RND, RDO…) e avisa quando algo passa da linha vermelha — antes de gastar etiqueta.
Galeria de modelos à direita, com miniatura de cada etiqueta pronta
A galeria: modelo salvo vira miniatura. Isso aqui era uma lista de JSON até virar pasta com nome, grupo e cópia de segurança.
04
o que ele faz

O kit completo — e o motivo de cada peça existir

Texto

Tamanho em pontos, negrito, itálico, alinhamento, cor, espaçamento entre letras, altura de linha e “ajustar” (encolhe até caber na caixa). Parece básico — mas é o que evita etiqueta com texto estourando.

Códigos

CODE128, EAN-13, EAN-8, UPC, CODE39, ITF14, MSI, Pharmacode e QR com correção L/M/Q/H. O app valida o dado: se o número não fecha o dígito verificador do EAN, ele avisa em vez de sair um risco torto.

Imagem e formas

Arrastar imagem, colar com ⌘V, cortar regiões de uma foto para virar objeto, retângulo, elipse, linha, seta, cruz e moldura da etiqueta. A moldura faz parte da arte (sai no PNG e na impressão).

Camadas, máscara e cópias

Ordem das camadas, esconder, duplicar, máscara (recorta um objeto usando outro como forma) e “Array…” para repetir o mesmo objeto em grade — de etiqueta de patrimônio a cartela de 20 unidades.

Modelos que sobrevivem a atualização

Modelo salvo no navegador é frágil: limpar cache, trocar de janela, atualizar o app — some. Aqui o modelo vai para arquivo, em dados/modelos.json ao lado do app, com uma cópia da versão anterior em modelos.bak.json. Se a gravação falhar no meio, o backup salva o dia. E o backup/restauração em JSON existe para levar modelos de uma máquina para outra sem sobrescrever: modelo repetido entra como “(importado)”.

05
lote por planilha

40 etiquetas diferentes em um clique (e sem digitar nada de novo)

O motivo de o app existir, na prática: casa de bombas com 40 equipamentos. Cada etiqueta tem TAG, nome e setor. Digitar 40 vezes é garantia de erro de digitação — e erro em etiqueta de segurança não é detalhe.

O fluxo é este: você monta uma etiqueta com marcadores {{codigo}}, {{nome}} e {{setor}} (ou liga cada camada a uma coluna pelo painel Campos da etiqueta), escolhe o arquivo .xlsx ou .csv, confere a prévia da primeira etiqueta e manda imprimir. O app lê a planilha dentro da máquina — nada é enviado para a internet.

Janela de impressão em lote com planilha carregada, mapeamento de colunas e prévia
Lote: 4 linhas carregadas, colunas mapeadas automaticamente e a prévia da 1ª etiqueta antes de gastar rolo.
06
a janela nativa

Quando o app ficou “de verdade” — e quebrou de um jeito estranho

Abrir no Chrome em modo app funciona, mas tem cara de site. A virada foi criar uma janela nativa (WKWebView) gerada na hora com osacompile: ícone no Dock, título, foco, restaurar ao clicar no ícone. O visual segue sendo o mesmo HTML — só que dentro de uma janela de app.

Só que aí apareceu o bug mais instrutivo do projeto. No app instalado, três botões não faziam nada:

Nenhum erro, nenhum aviso. Clicava e o silêncio. A causa: um WebView não tem seletor de arquivo nem download por padrão. Abrir aquela janelinha do Finder e salvar arquivo são coisas que o app precisa implementar — o Chrome faz, o WebView puro não faz. E o app não tinha esse pedaço.

A gambiarra que virou arquitetura

Como o app já roda um servidor Perl local (é ele que serve o HTML e conversa com a impressora), a solução foi ensinar esse servidor a abrir os diálogos do macOS:

Efeito colateral bom: a mesma ponte consertou de uma vez todos os outros downloads e seletores do app — exportar PNG, backup de modelos, importar JSON, inserir imagem, cortar imagem, relatório do lote.
07
códigos

QR ou código de barras? A resposta com número, não com achismo

Pergunta legítima de quem vai imprimir: “cabe isso no código?”. Em vez de repetir o que dizem por aí, medi nas bibliotecas que o app realmente usa — e conferi decodificando de volta.

2.953bytes num QR versão 40, correção L
2.331bytes com correção M (o ajuste esperto)
11módulos por caractere no CODE128
~27caracteres que cabem num CODE128 de 44 mm

Resumo da medição: um QR de 1.000 caracteres ocupa 105 × 105 módulos; de 2.000, 149 × 149; o teto de 2.953 chega em 177 × 177. No papel, com a térmica a 203 dpi, o mínimo confiável é 2 pontos por módulo (0,25 mm). Numa área de 44 mm isso dá 2,6 pontos/módulo para 1.000 caracteres — passa — e 1,9 para o teto, que sai borrado. Ou seja: até ~1 KB é seguro no lado curto; o teto só cabe no lado longo de 101 mm.

Etiqueta com texto, código de barras e QR renderizada a 300 dpi
O render a 300 dpi que vai para o filtro da SLP650: QR de 22 mm e CODE128 legíveis na distância de leitura. É esse arquivo que imprime — não o que está na tela.
Detalhe técnico: imagem dentro de QR (dá, mas é pouco)
Testei de verdade: PNG em base64 dentro do QR e decodificado de volta com zbarimg. Funciona e volta byte a byte idêntico — mas o base64 infla 33%, e o teto do QR é 2.953 bytes, então cabe imagem de no máximo ~2,1 KB. Na prática: ícone de 16 px (108 B) vira QR 45 × 45; foto de 64 × 64 (1 KB) vira QR 125 × 125 e ainda decodifica. Foto de verdade, não. Para etiqueta, URL curta ou um ID resolve melhor — e quem lê precisa de um app que entenda base64, porque o leitor comum só mostra texto.
08
conforto e confiança

Botão “Nova etiqueta” — e a versão que finalmente diz a verdade

Um pedido simples: começar do zero sem apagar objeto por objeto. Agora existe o botão azul Nova etiqueta no topo do painel esquerdo, antes do seletor de papel. Ele pergunta antes, diz o que vai apagar, e não mexe no que não deve: papel escolhido e calibração ficam, modelos salvos ficam. Deu errado? Ctrl/⌘ Z volta.

Popup de confirmação do botão Nova etiqueta
Confirmação dentro do próprio app — com o aviso de que dá para desfazer.

Junto veio um detalhe que parecia cosmético e não era: o número da versão no cabeçalho estava digitado à mão no HTML (v1.46.0) enquanto o pacote já ia na 1.50. Ou seja: o app mentia sobre a própria versão — e é justamente esse número que responde “você está com o build novo?”. Agora o número é injetado no build a partir de um único lugar, e o empacotador aborta se não achar o marcador. Nunca mais dessincroniza.

09
o modificador

Lacre de segurança: a palavra repetida que esconde outra

O pedido veio como imagem: uma etiqueta coberta por LACRE em diagonal, e no meio dela, de vez em quando, GARANTIA aparecendo em outro estilo. É o velho truque de segurança: difícil de copiar, fácil de reconhecer de longe — se a etiqueta foi violada, o padrão denuncia.

Referência: etiqueta com LACRE repetido e GARANTIA destacada
A referência que veio no pedido.
Resultado gerado no app
Gerado no app: mesma palavra, 15% de destaque, 1,35 de entrelinha, −33°.

O modificador virou um item de texto normal com uma chave ligada: Padrão diagonal. Você digita a palavra, opcionalmente a palavra de destaque, e regula quatro coisas:

Painel do freeLabel com o modificador Padrão diagonal ligado
O modificador no painel. Repare no preenchimento cobrindo a área imprimível inteira.
Detalhe técnico: por que o padrão não “embaralha” entre prévia e impressão
Cada palavra é sorteada por um gerador com semente fixa (id do objeto + palavra + tamanho + fonte). O mesmo desenho aparece no canvas, na miniatura, no PNG e no papel — nada de a prévia ser uma coisa e a etiqueta outra. Desenhar 300 dpi leva ~4 ms, então nem pesa. E o texto pode vir da planilha: no lote, cada etiqueta ganha o seu padrão com a palavra da linha.
10
usar hoje

Do zip ao papel em oito passos

Descompacte fora das pastas protegidas

Coloque em ~/freeLabel ou numa pasta sua. Downloads/Desktop/Documents fazem o macOS bloquear a execução dos scripts.

Abra o freeLabel.app

Se aparecer “desenvolvedor não identificado”: clique com o botão direito → Abrir → Abrir. Só na primeira vez.

Confira o cabeçalho

Tem que aparecer freeLabel v1.52.0 e o botão azul Imprimir SLP650 (sem “script não encontrado”).

Escolha o papel

No rolo padrão: SLP-SRL / MPL4 — 54 × 101. O app mostra o tamanho SII (SRLDPI) logo abaixo.

Monte a etiqueta

Texto, código de barras, QR, imagem ou um modelo da galeria. Arraste com o mouse, ajuste fino com as setas, Shift = 0,1 mm.

Teste a escala uma vez

“Imprimir teste de escala” gera moldura + quadrado de 20 × 20 mm. Meça com régua: 20 mm = está 1:1.

Imprima

Azul = direto na SLP650 (sem driver e sem senha). “Imprimir (diálogo)” é o caminho antigo, só com fila instalada — nele use 100%, nunca “ajustar à página”.

Salve o modelo

Dê um nome, escolha o grupo e salve. Fica em arquivo na pasta do app, com backup, e aparece na galeria para reutilizar.

Se a etiqueta sair deslocada: ajuste Desloc. X/Y (mm) na calibração. Se sair maior ou menor que o real, ajuste a Escala (%). É calibração de impressora, não de layout — mexa uma vez e esqueça.
11
por dentro

A arquitetura que ninguém vê (e que explica os bugs)

Para quem gosta do encanamento — e para quem for mexer no app depois:

Peças

  • index.html — o app inteiro: layout, canvas, libs embutidas
  • server.pl — servidor local (Perl puro) em 127.0.0.1:8731
  • window.jxa — a janela nativa (JXA + WKWebView)
  • 2-imprimir.command — PNG → filtro rastertosiislp → USB
  • dados/modelos.json — modelos, com .bak

Rotas do servidor

  • /print — enfileira um job (fila de verdade, um por vez)
  • /job, /queue — estado e resultado de cada etiqueta
  • /tpl — grava/lê modelos (com cópia de segurança)
  • /pick, /save — diálogos do macOS (WebView não tem)
  • /health, /log — diagnóstico em uma tela
Detalhe técnico: como a impressão realmente acontece
O canvas é renderizado no DPI final (203, 300 ou 600), o app converte para PNG 1-bit na densidade escolhida e manda por POST /print. O servidor grava o arquivo em /tmp, enfileira, e um processo filho chama 2-imprimir.command com arquivo, tamanho SII e cópias. O retorno (incluindo a saída do filtro) volta para a tela e para o log. É por isso que dá para saber se o problema foi conversão, papel ou cabo — em vez de só “não imprimiu”.
Detalhe técnico: por que tem tanta checagem de sintaxe e de runtime
O build do app não é “salva e reza”: ele roda node --check no script e depois abre a página num Chrome headless procurando um marcador data-js-error que o próprio app preenche se algo estourar. Se o HTML quebrar, o build falha antes de virar zip. Isso já pegou erro bobo mais de uma vez.
Detalhe técnico: as bibliotecas e o “sem internet”
JsBarcode (códigos de barras), qrcode.js (QR) e SheetJS (planilha) ficam embutidas no HTML no momento do build. O app não faz requisição para fora: nem fonte, nem CDN, nem telemetria. A única conversa de rede é com o próprio servidor local na porta 8731.
12
linha do tempo

Três dias: do 1.0 ao 1.52

29/out · v1.0.0 → v1.3.0
O começo: imprimir sem admin

Filtro oficial da SII, backend USB, scripts numerados e o primeiro PNG saindo na SLP650.

29/out · designer
Nasce o editor de etiqueta

HTML único, medidas em milímetros, presets de rolo, texto/código/QR/imagem. Primeiras versões do “freeLabel designer”.

29–30/out
Modelos em arquivo, galeria e lote

Modelos saem do navegador e viram arquivo com backup; planilha entra no jogo, com mapeamento de colunas e relatório.

30/out · v1.4x
A janela nativa

WKWebView via osacompile, ATS liberado para o servidor local, ícone e foco de app de verdade.

31/out · v1.50.0
O bug dos três botões

Descoberta de que WebView não abre arquivo nem baixa: pontes /pick e /save no servidor Perl.

31/out · v1.51.0
Nova etiqueta + versão honesta

Botão com confirmação e desfazer; versão do cabeçalho passa a vir do build, não digitada à mão.

31/out · v1.52.0
Padrão diagonal (lacre)

Modificador de texto que repete a palavra e esconde a segunda, com semente fixa e cobertura exata da área imprimível.

13
o que falta

O que o app ainda não faz (e a gente sabe)

Cada item desses é uma decisão adiada de propósito: enquanto não aparecer necessidade real, mexer nisso só aumenta a chance de quebrar o que já funciona. Esse app é usado para imprimir etiqueta de segurança em campo — “bonitinho” perde para “não me deixa errar”.

Resumo em três linhas

Um app de arquivo único, offline, que desenha etiqueta em milímetros e imprime numa SLP650 sem instalar nada. Tem lote por planilha, modelos em arquivo, códigos validados e padrão de segurança. Roda numa janela nativa — e, quando o sistema não coopera, o servidor local dá um jeito.