Guarde a licença da imagem na mesma pasta do arquivo, e deixe um script conferir
Monte um registro de licença ao lado de cada imagem do site, com origem, data e usos permitidos, e use um script em Node.js para acusar arquivo sem registro antes do deploy.
A Padaria Trigal vai lançar uma campanha e quer usar as fotos do site num folheto impresso. Alguém pergunta: "podemos usar essas imagens?". Ninguém sabe. Metade foi baixada por um estagiário que já saiu, a outra metade veio do site antigo. A resposta curta: guarde a origem e a licença de cada imagem num arquivo de texto ao lado dela, no dia em que ela entra no projeto. Um licencas.json por pasta, com URL de origem, data, licença e usos permitidos, resolve. Um script simples confere se toda imagem tem registro e falha o deploy quando não tem.
Este guia mostra o formato do registro, o script de conferência e o que fazer com as imagens antigas cuja origem já se perdeu.
Por que a licença se perde
A licença de uma imagem vive em três lugares: na página de onde ela foi baixada, na cabeça de quem baixou e, às vezes, num e-mail. Nenhum deles acompanha o arquivo. A imagem vai para o repositório, é redimensionada, renomeada, copiada para outro projeto, e a ligação com a origem some.
Um ano depois, a pergunta "podemos usar?" tem três respostas possíveis: sim, com prova; não sei; não. "Não sei" é a mais cara, porque a única decisão segura é tratar a imagem como não liberada e trocá-la, às vezes em dezenas de lugares. Anotar no dia custa um minuto. Investigar depois custa uma tarde, quando dá para descobrir.
E não é só foto de banco. Foto de cliente depende do contrato com ele. Foto própria precisa estar marcada como própria, senão vira "não sei" do mesmo jeito. Ícones e ilustrações têm suas próprias licenças, como mostra pacote de ícone grátis ainda tem licença.
O formato do registro ao lado do arquivo
Colocar o registro na mesma pasta tem uma vantagem simples: quem move a pasta leva o registro junto. Uma planilha central funciona, mas se descola dos arquivos na primeira reorganização.
Na Trigal, cada pasta de imagens ganhou um licencas.json, com uma entrada por arquivo:
{
"pao-de-fermentacao.jpg": {
"origem": "https://unsplash.com/photos/... (URL completa da página da foto)",
"autor": "Nome do fotógrafo como aparece na página",
"licenca": "Unsplash License",
"url_licenca": "https://unsplash.com/license",
"obtido_em": "2026-03-14",
"usos_permitidos": "site, redes sociais e folheto; não vender a foto como produto",
"observacoes": "sem pessoas, sem marca visível"
},
"fachada-loja.jpg": {
"origem": "foto própria",
"autor": "Equipe Trigal",
"licenca": "própria",
"obtido_em": "2026-05-02",
"usos_permitidos": "qualquer uso da empresa"
},
"bolo-casamento-cliente.jpg": {
"origem": "enviada pela cliente por e-mail",
"autor": "Cliente (contrato 2026-041)",
"licenca": "autorização por escrito no contrato",
"obtido_em": "2026-06-20",
"usos_permitidos": "portfólio no site; não usar em anúncio pago"
}
}
Os campos obrigatórios são quatro: origem, licenca, obtido_em e usos_permitidos. O último é o que responde à pergunta da campanha sem precisar abrir a licença de novo. Repare que a foto da cliente pode ir para o site e não pode ir para anúncio: sem o registro, alguém usaria no folheto sem pensar.
Como montar o processo passo a passo
- Crie o
licencas.jsonem cada pasta de imagens. Comece pelas pastas que vão para produção. - Registre no momento do download. Com a página da foto aberta, copie a URL, o autor e o nome da licença. Antes de baixar, confira os limites dela, como explica foto de banco gratuito: o que a licença deixa fazer.
- Use o nome final do arquivo. Renomeie a imagem antes de registrar, para a chave do JSON bater com o arquivo.
- Adicione o script de conferência ao projeto. Ele roda local e na integração contínua.
- Faça o deploy falhar quando faltar registro. Regra que só gera aviso é ignorada na primeira sexta-feira corrida.
- Ao copiar imagem para outro projeto, copie a entrada. A imagem sem a nota volta a ser "não sei".
O script que acusa imagem sem registro
O script abaixo percorre a pasta de imagens, confere se cada arquivo tem entrada no licencas.json da mesma pasta com os campos obrigatórios, e aponta também entradas de arquivos que já não existem. Funciona com Node.js 18 ou mais novo, sem dependências:
// scripts/check-licencas.js
const fs = require('node:fs/promises');
const path = require('node:path');
const RAIZ = process.argv[2] || 'public/img';
const EXTENSOES = new Set(['.jpg', '.jpeg', '.png', '.webp', '.avif', '.gif', '.svg']);
const CAMPOS = ['origem', 'licenca', 'obtido_em', 'usos_permitidos'];
async function lerLicencas(pasta) {
const arquivo = path.join(pasta, 'licencas.json');
try {
return JSON.parse(await fs.readFile(arquivo, 'utf8'));
} catch (erro) {
if (erro.code === 'ENOENT') return {};
throw new Error(arquivo + ': ' + erro.message);
}
}
async function verificarPasta(pasta, problemas) {
const entradas = await fs.readdir(pasta, { withFileTypes: true });
const licencas = await lerLicencas(pasta);
const imagens = new Set();
for (const entrada of entradas) {
const caminho = path.join(pasta, entrada.name);
if (entrada.isDirectory()) {
await verificarPasta(caminho, problemas);
continue;
}
if (!EXTENSOES.has(path.extname(entrada.name).toLowerCase())) continue;
imagens.add(entrada.name);
const registro = licencas[entrada.name];
if (!registro) {
problemas.push(caminho + ': sem registro em licencas.json');
continue;
}
const faltando = CAMPOS.filter((campo) => !registro[campo]);
if (faltando.length > 0) {
problemas.push(caminho + ': falta ' + faltando.join(', '));
}
}
for (const nome of Object.keys(licencas)) {
if (!imagens.has(nome)) {
problemas.push(path.join(pasta, nome) + ': registro sem arquivo');
}
}
}
async function main() {
const problemas = [];
await verificarPasta(RAIZ, problemas);
if (problemas.length > 0) {
for (const problema of problemas) console.error(problema);
console.error(problemas.length + ' problema(s) de licença de imagem.');
process.exitCode = 1;
return;
}
console.log('Todas as imagens têm registro de licença.');
}
main().catch((erro) => {
console.error(erro.message);
process.exitCode = 1;
});
No package.json, um script "check:licencas": "node scripts/check-licencas.js public/img" deixa a conferência a um comando de distância. Na primeira execução, a Trigal viu algo assim:
public/img/home/banner-paes.jpg: sem registro em licencas.json
public/img/home/cafe-da-manha.jpg: falta usos_permitidos
public/img/produtos/croissant-antigo.jpg: registro sem arquivo
3 problema(s) de licença de imagem.
O script garante que a pergunta foi respondida, não que a resposta está certa. Quem revisa o pull request ainda precisa olhar se a URL de origem abre e se os usos batem com a licença.
O que fazer com as imagens antigas sem origem
Para cada imagem que o script acusar, tente nesta ordem: busca reversa no Google Lens ou no TinEye para achar a página original; histórico do repositório e e-mails antigos para descobrir quem trouxe o arquivo; pergunta direta a quem trabalhou no projeto. Se achar, registre. Se não achar, troque a imagem ou registre explicitamente como "licenca": "não liberada" e tire de qualquer uso comercial. Imagem achada na busca, sem banco nenhum, quase sempre cai nesse caso, como explica pegar imagem da internet não torna a imagem sua.
Erros comuns
- Registrar só a home do banco. "Pixabay" não diz qual foto, de qual autor, sob qual versão da licença.
- Guardar a licença numa planilha separada. A primeira reorganização de pastas descola o registro dos arquivos.
- Script que só avisa. Aviso é ignorado; a imagem sem registro chega à produção do mesmo jeito.
- Deixar a foto própria sem registro. Um ano depois, ninguém sabe se ela é própria ou baixada.
- Esquecer o limite de uso de foto de cliente. A foto autorizada para portfólio aparece num anúncio pago.
- Copiar imagem entre projetos sem a entrada. O projeto novo começa com uma imagem "não sei".
Checklist
- Toda pasta de imagens publicadas tem um
licencas.json. - Cada entrada tem origem, licença, data e usos permitidos.
- A origem é a URL da página da foto, não a home do banco.
- Fotos próprias e de clientes também estão registradas.
- O script de conferência roda na integração contínua e falha o build.
- Imagens sem origem descoberta estão marcadas como não liberadas ou foram trocadas.
Abra a pasta de imagens da sua home. Para cada arquivo, você consegue dizer de onde ele veio e se pode ir para um anúncio pago? Os que você não consegue são os primeiros a revisar.
Referência: http://pixabay.com/pt/