Skip to content

Repository files navigation

mydevice

Digite a URL de um site e veja-o rodando de verdade dentro de uma moldura de celular, tablet ou desktop — navegável, com a cor da moldura à sua escolha e com download do mockup em PNG de fundo transparente.

O site não é embutido num <iframe>: ele é aberto num Chrome headless no servidor, com a emulação real do aparelho (user-agent mobile, toque e viewport). Por isso PWAs reconhecem corretamente que estão num celular, e funciona mesmo em sites que bloqueiam incorporação.

Rodando localmente

npm install
npm start

Abra http://localhost:5177. Usa o Chrome ou Edge já instalado na máquina.

Localmente é permitido apontar para localhost — dá para ver o seu próprio projeto em desenvolvimento dentro de uma moldura.

Publicando

Precisa de um processo Node persistente com WebSocket e um Chromium ao lado. Plataformas serverless (Vercel, Netlify Functions, Cloudflare Workers) não servem: a sessão ao vivo depende de conexão contínua e de um navegador vivo entre as requisições.

O Dockerfile já traz o Chromium e as fontes necessárias.

Render

Há um render.yaml pronto. No painel: New → Blueprint, aponte para o repositório e confirme. Ou crie um Web Service com runtime Docker.

Railway

New Project → Deploy from GitHub repo. O Dockerfile é detectado automaticamente. Em Settings → Networking, gere o domínio público.

Fly.io

fly launch --dockerfile Dockerfile
fly deploy

Ajustes

Variável Padrão Para que serve
PORT 5177 Porta HTTP (as plataformas definem sozinhas)
MAX_SESSIONS 6 Sessões simultâneas. Cada uma é uma aba de Chrome viva — subir demais estoura a memória
ALLOW_PRIVATE_HOSTS 0 em produção Deixa abrir endereços internos. Mantenha desligado em servidor público
PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium Caminho do navegador
PUBLIC_URL http://localhost:5177 Domínio público. Usado na URL canônica, no sitemap e no llms.txt — defina no deploy, senão o SEO aponta para localhost
ADSENSE_CLIENT vazio ID do publisher (ca-pub-...). Sem ele, nenhum anúncio é carregado e /ads.txt responde 404
ADSENSE_SLOT_1, ADSENSE_SLOT_2 vazio IDs dos blocos de anúncio criados no painel do AdSense

Reserve pelo menos 1 GB de RAM: Chromium com várias abas não cabe nos planos gratuitos mais apertados. Comece com MAX_SESSIONS=2 se a memória for pouca.

GET /health responde {"ok":true} para o health check da plataforma.

Segurança

Como o servidor abre qualquer URL que o visitante digitar, num servidor público ele poderia ser usado para alcançar coisas que só a máquina enxerga. Por isso:

  • endereços de loopback, redes privadas, link-local e CGNAT são recusados;
  • o endpoint de metadados da nuvem (169.254.169.254) é bloqueado no próprio resolvedor do navegador, então nem um redirecionamento chega até ele;
  • há teto de sessões simultâneas.

Ainda assim, o app deixa qualquer visitante navegar pela internet a partir do IP do seu servidor. Se for expor publicamente, considere colocar autenticação na frente.

Como funciona a transmissão

Nenhum método de captura sozinho resolve, então ela é híbrida:

  • Page.startScreencast é rápido (~23 fps) mas o Chrome headless ignora o deviceScaleFactor e sempre entrega 1x — borrado numa tela HiDPI;
  • page.screenshot respeita a densidade de pixels (nítido) mas leva ~105 ms por quadro, teto de ~10 fps — lento demais para navegar.

Enquanto você interage, vale o screencast (fluido, ~20 fps, ~40 ms de resposta ao clique). Assim que você para, o screencast é desligado e a tela passa a ser enviada em alta resolução. Desligar importa: numa página que se atualiza sozinha (um relógio, por exemplo) os quadros 1x ficariam apagando os nítidos.

Leitura por buscadores e IA

O conteúdo da página está em HTML de verdade e é lido sem executar JavaScript (cerca de 900 palavras no HTML bruto), com dados estruturados JSON-LD (SoftwareApplication e FAQPage).

Rota Para que serve
/robots.txt Libera explicitamente rastreadores de IA (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot e outros)
/llms.txt Resumo do site em formato legível por modelos de linguagem
/sitemap.xml Mapa das páginas
/ads.txt Gerado a partir de ADSENSE_CLIENT; some se a variável não estiver definida
/privacidade Política de privacidade, exigida pelo AdSense

Sobre o AdSense

Os blocos só aparecem quando ADSENSE_CLIENT está definido — enquanto a conta não é aprovada, o site fica sem espaços vazios.

Vale saber de dois riscos antes de submeter para aprovação:

  1. A ferramenta exibe sites de terceiros. O AdSense tem política contra veicular anúncios em telas cujo conteúdo não pertence ao publisher. Por isso os blocos de anúncio ficam apenas na área de conteúdo próprio, abaixo da ferramenta, e nunca ao lado da moldura.
  2. Sites que são só ferramenta costumam ser reprovados por conteúdo insuficiente. Por isso a página traz documentação própria, tabela de aparelhos e FAQ.

Mesmo assim, a aprovação é decisão do Google.

About

mydevice - veja e navegue por qualquer site dentro de molduras realistas de celular, tablet e desktop, com download do mockup em PNG transparente

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages