Navegador Híbrido Smallweb
Documentação de ideia para construir um navegador híbrido para Gemini, Gopher, Nex, Spartan e outros protocolos da smallweb.
Navegador Híbrido Smallweb
Um navegador híbrido para Gemini, Gopher, Nex, Spartan e outros protocolos pequenos não deve tentar competir com Chrome, Firefox ou Safari.
Essa seria a primeira ideia errada.
Ele deve competir com outra coisa: a dependência da web moderna como único modo aceitável de acessar, publicar e preservar conteúdo.
A ideia aqui é construir um navegador leve, modular, textual, seguro e extensível para explorar a smallweb: cápsulas Gemini, buracos Gopher, espaços Nex, servidores Spartan, arquivos, páginas simples, logs pessoais, diretórios, feeds e documentos.
Ele deve ser pequeno o bastante para rodar em hardware velho, mas organizado o bastante para não virar brinquedo abandonado depois da primeira versão.
Diagnóstico
A web moderna virou pesada demais para uma parte enorme do que as pessoas realmente precisam fazer.
Muitas páginas que poderiam ser documentos simples viraram aplicações gigantescas, cheias de JavaScript, rastreadores, fontes externas, frameworks, banners, métricas, cookies e dependências.
Enquanto isso, protocolos como Gopher, Gemini, Nex e Spartan mantêm uma proposta radicalmente simples:
- conectar;
- pedir um recurso;
- receber texto, menu ou arquivo;
- navegar;
- fechar a conexão.
Não há DOM monstruoso.
Não há JavaScript obrigatório.
Não há publicidade embutida por padrão.
Não há modelo de atenção baseado em vício.
Isso torna esses protocolos interessantes para:
- smallweb;
- indieweb;
- permacomputação;
- publicação pessoal;
- servidores pequenos;
- hardware antigo;
- arquivos comunitários;
- educação técnica;
- cyberativismo;
- preservação digital.
Nome provisório
Moth
Nome sugerido: Moth.
A mariposa combina com a ideia de navegar por luzes pequenas na escuridão.
Mas o nome é secundário. O mais importante é a arquitetura.
Outras opções:
LanternBurrowCapsuleSmallgateGloomMurmurNighthostWayfarerPeregrineHollow
Objetivo do projeto
Criar um navegador híbrido, modular e leve para protocolos da smallweb.
O navegador deve abrir, navegar, exibir, baixar, arquivar e favoritar conteúdos de múltiplos protocolos, usando uma interface simples e uma arquitetura interna comum.
Objetivo principal
Construir primeiro um MVP TUI.
Ou seja: um navegador em terminal, bonito e funcional, com suporte inicial a Gemini e Gopher.
Depois disso, adicionar Nex, Spartan e uma interface desktop.
O que ele não deve ser no começo
Ele não deve começar como:
- navegador web completo;
- substituto de Firefox;
- cliente mobile;
- engine HTML;
- leitor universal de tudo;
- plataforma social;
- aplicativo Electron pesado;
- software com 40 preferências antes de abrir a primeira página.
Isso mataria o projeto.
Princípio central
O protocolo muda. O documento interno permanece.
Cada protocolo deve ser convertido para uma estrutura interna comum chamada, por exemplo, Document.
A interface não deve se importar se o conteúdo veio de Gemini, Gopher, Nex ou Spartan.
Ela deve receber um documento já normalizado.
type Document struct {
URL string
Title string
MimeType string
Protocol string
Blocks []Block
Links []Link
RawBytes []byte
StatusCode string
Meta string
}
Essa separação é o que impede o projeto de virar uma bagunça.
Protocolos-alvo
| Protocolo | Prioridade | Dificuldade | Observação |
|---|---|---|---|
| Gemini | Alta | Média | Começar por ele. Precisa de TLS e TOFU. |
| Gopher | Alta | Baixa | Simples, antigo, ótimo para MVP. |
| Nex | Média | Baixa | Muito simples; bom para adicionar cedo. |
| Spartan | Média | Média | Tratar como experimental até confirmar a spec final usada. |
| Finger | Baixa | Baixa | Pode ser um módulo futuro divertido. |
| HTTP | Baixa | Alta | Não implementar render web. Abrir externamente. |
| File | Média | Baixa | Permitir abrir arquivos locais .gmi, .txt, .md. |
Gemini
Gemini é um protocolo de aplicação para acesso a documentos remotos, parecido em espírito com HTTP e Gopher, mas com simplicidade deliberada.
Características importantes:
- usa URLs
gemini://; - normalmente usa a porta
1965; - usa TLS;
- funciona em modelo request-response;
- o cliente envia uma URL terminada por CRLF;
- o servidor responde com status, meta e corpo;
- o formato nativo é
text/gemini, também chamado de Gemtext; - Gemtext é line-oriented, com links, títulos, listas, citações e blocos preformatados.
Pontos críticos em Gemini
O maior detalhe não é renderizar texto. Isso é fácil.
O ponto crítico é segurança:
- validação TLS;
- TOFU, ou trust on first use;
- persistência de certificados conhecidos;
- alerta quando certificado muda;
- suporte opcional a certificados de cliente;
- redirects limitados;
- tratamento de input status;
- downloads seguros.
Tipos de status Gemini
O cliente deve tratar famílias de status:
| Classe | Significado geral |
|---|---|
1x |
Input necessário |
2x |
Sucesso |
3x |
Redirect |
4x |
Falha temporária |
5x |
Falha permanente |
6x |
Certificado de cliente necessário |
Parser Gemtext
Blocos principais:
| Sintaxe | Bloco |
|---|---|
# |
Heading 1 |
## |
Heading 2 |
### |
Heading 3 |
=> |
Link |
* |
Lista |
> |
Citação |
| ``` | Bloco preformatado |
| texto | Parágrafo |
Gopher
Gopher é mais antigo e ainda mais simples.
Ele funciona como um sistema de documentos e menus distribuídos.
Características importantes:
- usa URLs
gopher://; - normalmente usa a porta
70; - o cliente envia um selector;
- o servidor responde com texto ou menu;
- menus têm linhas com tipo, nome, selector, host e porta;
- é extremamente fácil de depurar manualmente;
- a resposta de diretório termina com um ponto em uma linha isolada.
Tipos Gopher básicos
| Tipo | Significado |
|---|---|
0 |
Arquivo de texto |
1 |
Diretório/menu |
3 |
Erro |
7 |
Busca |
9 |
Arquivo binário |
g |
GIF |
I |
Imagem |
h |
HTML ou link externo |
i |
Linha informativa |
Parser Gopher
Cada linha de menu pode virar um Block.
Exemplo interno:
type GopherItem struct {
Type rune
Label string
Selector string
Host string
Port int
}
O navegador deve exibir menus como listas navegáveis.
Nex
Nex é um protocolo simples de recuperação distribuída de documentos, inspirado por Gopher e Gemini.
Características importantes:
- usa porta
1900; - o cliente conecta e envia um caminho, que pode ser vazio;
- o servidor responde com texto ou binário;
- a conexão é fechada após a resposta;
- não mantém estado;
- diretórios podem usar linhas começando com
=>como links; - se não houver extensão, o cliente pode assumir texto puro.
Por que Nex é interessante
Nex é quase brutal na simplicidade.
Isso é ótimo para um navegador pequeno.
Ele pode ser implementado depois de Gemini e Gopher com pouco esforço, desde que o core esteja bem separado.
Spartan
Spartan deve ser tratado como protocolo experimental no projeto.
Não coloque Spartan como base do MVP.
A regra prática:
- criar interface
Fetcher; - implementar Gemini;
- implementar Gopher;
- implementar Nex;
- só então adicionar Spartan;
- manter Spartan isolado atrás de feature flag.
Política para Spartan
Como o ecossistema é menor e mais difícil de pesquisar em fontes HTTP comuns, o projeto deve guardar a spec usada dentro de docs/specs/spartan.md, com data e origem.
Isso evita o erro clássico: implementar uma interpretação pessoal do protocolo e depois descobrir que os servidores reais falam outra variação.
Stack recomendada
A recomendação principal é:
Go no core + Bubble Tea na TUI + SQLite/JSON para estado.
Isso dá velocidade de desenvolvimento, binários simples, boa rede, boa portabilidade e manutenção razoável.
Stack principal
| Camada | Escolha recomendada |
|---|---|
| Linguagem | Go |
| TUI | Bubble Tea |
| Componentes TUI | Bubbles |
| Estilo terminal | Lip Gloss |
| Configuração | TOML |
| Estado simples | SQLite ou JSON |
| Logs | slog |
| Testes | testing nativo do Go |
| Build | GoReleaser |
| Desktop futuro | Tauri ou Fyne |
| Documentação | Markdown |
| CI | GitHub Actions ou Forgejo Actions |
Por que Go?
Go é uma escolha pragmática.
Vantagens:
- rede excelente;
- TLS nativo;
- binário único;
- compilação cruzada simples;
- consumo razoável;
- código legível;
- biblioteca padrão forte;
- curva menor que Rust;
- ótimo para ferramentas CLI/TUI.
Desvantagens:
- menos garantias que Rust;
- UI desktop nativa não é seu ponto forte;
- gerenciamento de erros pode ficar repetitivo;
- bibliotecas Gemini/Gopher podem ser menos maduras que implementar você mesmo.
Mesmo assim, para este projeto, Go é provavelmente o caminho mais rápido para sair do papel.
Alternativa em Rust
Rust é excelente para segurança, performance e binários pequenos.
Stack possível:
| Camada | Escolha |
|---|---|
| Linguagem | Rust |
| TUI | Ratatui |
| Terminal backend | Crossterm |
| TLS | rustls |
| Config | serde + toml |
| Storage | rusqlite |
| CLI | clap |
| Logs | tracing |
| Desktop | Tauri |
Quando escolher Rust
Escolha Rust se o objetivo for:
- máxima robustez;
- segurança de memória;
- projeto de longo prazo;
- integração futura com Tauri;
- distribuição como software mais sério.
Quando não escolher Rust
Não escolha Rust se você quer MVP rápido e pouca fricção.
Rust é ótimo, mas ele cobra pedágio.
Alternativa em Python
Python pode servir para protótipo, mas eu não faria o produto final nele.
Vantagens:
- rápido de escrever;
- ótimo para testar parsers;
- bom para protótipos;
- muitas bibliotecas.
Desvantagens:
- distribuição pior;
- dependências mais frágeis;
- performance menor;
- empacotamento multiplataforma mais chato;
- menos coerente com a ideia de navegador leve e permanente.
Python pode ser usado para scripts auxiliares, testes de crawler e conversores.
Interface inicial
A primeira interface deve ser TUI.
Nada de abrir com GUI antes de provar o core.
Tela sugerida
┌────────────────────────────────────────────────────────────────────┐
│ Moth gemini://example.org/ │
├────────────────────────────────────────────────────────────────────┤
│ # Example Capsule │
│ │
│ Welcome to a small place on the network. │
│ │
│ [1] About this capsule │
│ [2] Recent notes │
│ [3] Archive │
│ │
├────────────────────────────────────────────────────────────────────┤
│ ↑/↓ scroll enter open b back f forward / search q quit │
└────────────────────────────────────────────────────────────────────┘
Atalhos essenciais
| Tecla | Ação |
|---|---|
q |
sair |
g |
abrir URL |
enter |
abrir link selecionado |
b |
voltar |
f |
avançar |
r |
recarregar |
/ |
buscar na página |
s |
salvar/download |
a |
adicionar favorito |
B |
abrir favoritos |
h |
histórico |
y |
copiar URL |
? |
ajuda |
o |
abrir link HTTP externamente |
Arquitetura
A arquitetura deve ter separação radical entre:
- protocolos;
- documento interno;
- renderização;
- interface;
- storage;
- segurança.
Estrutura de pastas sugerida
moth/
cmd/
moth/
main.go
internal/
app/
app.go
commands.go
state.go
protocol/
fetcher.go
gemini/
client.go
parser.go
certs.go
gopher/
client.go
parser.go
nex/
client.go
parser.go
spartan/
client.go
parser.go
document/
document.go
blocks.go
links.go
normalize.go
render/
text.go
terminal.go
download.go
storage/
bookmarks.go
history.go
certstore.go
cache.go
security/
url.go
redirects.go
downloads.go
external.go
config/
config.go
defaults.go
ui/
tui/
model.go
update.go
view.go
keymap.go
styles.go
docs/
specs/
gemini.md
gopher.md
nex.md
spartan.md
architecture.md
security.md
testdata/
gemini/
gopher/
nex/
go.mod
README.md
LICENSE
Interface comum de protocolo
type Fetcher interface {
Schemes() []string
Fetch(ctx context.Context, req Request) (*Response, error)
}
type Request struct {
URL string
Method string
Input string
Headers map[string]string
}
type Response struct {
FinalURL string
Status string
Meta string
MimeType string
Body []byte
Links []Link
}
Registro de protocolos
type Registry struct {
fetchers map[string]Fetcher
}
func (r *Registry) Register(fetcher Fetcher) {
for _, scheme := range fetcher.Schemes() {
r.fetchers[scheme] = fetcher
}
}
Documento interno
type BlockType string
const (
BlockParagraph BlockType = "paragraph"
BlockHeading1 BlockType = "heading1"
BlockHeading2 BlockType = "heading2"
BlockHeading3 BlockType = "heading3"
BlockQuote BlockType = "quote"
BlockListItem BlockType = "list_item"
BlockLink BlockType = "link"
BlockPre BlockType = "pre"
BlockInfo BlockType = "info"
BlockError BlockType = "error"
)
type Block struct {
Type BlockType
Text string
URL string
}
type Link struct {
Index int
Text string
URL string
}
Esse formato permite transformar Gemini, Gopher, Nex e Spartan em uma mesma linguagem visual.
Renderização
A renderização deve ser simples.
Nada de tentar simular HTML.
Regras
- títulos devem se destacar;
- links devem ser numerados;
- texto deve quebrar de acordo com a largura do terminal;
- blocos preformatados devem preservar espaçamento;
- downloads devem ser claramente marcados;
- links externos devem pedir confirmação;
- imagens devem ser baixadas ou abertas externamente;
- binários nunca devem ser executados.
Política para imagens
No MVP:
- detectar imagem por MIME ou extensão;
- perguntar se deseja baixar ou abrir externamente;
- não renderizar imagem no terminal.
Futuro:
- preview via sixel/kitty graphics;
- thumbnails opcionais;
- modo texto puro sempre disponível.
Storage
O navegador precisa persistir:
- histórico;
- favoritos;
- certificados TOFU;
- cache opcional;
- downloads;
- configurações;
- sessões;
- identidade/certificados de cliente.
Opção simples: JSON
Boa para MVP:
~/.config/moth/config.toml
~/.local/share/moth/bookmarks.json
~/.local/share/moth/history.json
~/.local/share/moth/certs.json
Opção mais robusta: SQLite
Melhor para evolução:
~/.local/share/moth/moth.db
Tabelas:
CREATE TABLE history (
id INTEGER PRIMARY KEY,
url TEXT NOT NULL,
title TEXT,
protocol TEXT,
visited_at TEXT NOT NULL
);
CREATE TABLE bookmarks (
id INTEGER PRIMARY KEY,
url TEXT NOT NULL UNIQUE,
title TEXT,
tags TEXT,
created_at TEXT NOT NULL
);
CREATE TABLE certificates (
host TEXT NOT NULL,
port INTEGER NOT NULL,
fingerprint TEXT NOT NULL,
first_seen TEXT NOT NULL,
last_seen TEXT NOT NULL,
PRIMARY KEY (host, port)
);
Segurança
Este projeto parece simples, mas segurança ainda importa.
Não por causa de “exploit hollywoodiano”.
Por causa de erro besta.
Riscos reais
| Risco | Mitigação |
|---|---|
| Certificado Gemini mudou | Alertar e bloquear por padrão |
| Redirect infinito | Limite de 5 redirects |
| URL malformada | Parser rígido |
| Download perigoso | Nunca executar automaticamente |
| Link externo | Pedir confirmação |
file:// indevido |
Desabilitado por padrão |
| Path traversal | Normalizar paths |
| Conteúdo binário disfarçado | Detectar e tratar como download |
| Resposta gigante | Limite configurável |
| Host travado | Timeout obrigatório |
Política de downloads
Downloads devem ir para:
~/Downloads/moth/
Ou diretório definido no config.
Nunca abrir automaticamente.
Nunca marcar como executável.
Nunca sobrescrever sem confirmação.
Política de links HTTP/HTTPS
O navegador não deve renderizar HTTP.
Ele deve:
- detectar link HTTP/HTTPS;
- mostrar aviso;
- abrir no navegador padrão se o usuário confirmar.
Certificados Gemini e TOFU
TOFU significa trust on first use.
Na primeira conexão com um host Gemini, o navegador guarda a fingerprint do certificado.
Em conexões futuras:
- se a fingerprint for igual, segue;
- se mudou, alerta;
- se o usuário aceitar, atualiza;
- se o usuário recusar, aborta.
Exemplo de alerta
Certificado alterado para gemini://example.org
Fingerprint anterior:
SHA256: abc123...
Fingerprint nova:
SHA256: def456...
Isso pode ser renovação legítima ou ataque man-in-the-middle.
[aceitar uma vez] [atualizar] [cancelar]
Configuração
Arquivo:
[general]
home = "gemini://geminiprotocol.net/"
downloads_dir = "~/Downloads/moth"
open_external_http = "ask"
max_response_size_mb = 20
redirect_limit = 5
timeout_seconds = 15
[ui]
theme = "dark"
show_line_numbers = false
link_style = "numbered"
mouse = true
[protocols.gemini]
enabled = true
verify_mode = "tofu"
client_cert_dir = "~/.config/moth/certs"
[protocols.gopher]
enabled = true
[protocols.nex]
enabled = true
[protocols.spartan]
enabled = false
[privacy]
save_history = true
cache_pages = false
Dependências recomendadas em Go
Core
| Dependência | Uso |
|---|---|
net |
TCP |
net/url |
parsing de URL |
crypto/tls |
TLS para Gemini |
crypto/x509 |
certificados |
context |
timeouts/cancelamento |
log/slog |
logs |
os/exec |
abrir navegador externo |
database/sql |
SQLite |
encoding/json |
storage simples |
errors |
erros tipados |
Bibliotecas externas
| Biblioteca | Uso |
|---|---|
charmbracelet/bubbletea |
TUI |
charmbracelet/bubbles |
componentes TUI |
charmbracelet/lipgloss |
estilos no terminal |
spf13/cobra |
CLI |
spf13/viper |
configuração |
BurntSushi/toml |
TOML simples |
mattn/go-sqlite3 |
SQLite com CGO |
modernc.org/sqlite |
SQLite sem CGO |
atotto/clipboard |
copiar URL |
skratchdot/open-golang |
abrir links externos |
goreleaser/goreleaser |
builds |
Nota brutal sobre dependências
Não exagere.
Para o MVP, use poucas dependências:
bubbletea
bubbles
lipgloss
toml
sqlite ou json
O resto entra depois.
Dependências recomendadas em Rust
| Crate | Uso |
|---|---|
ratatui |
TUI |
crossterm |
backend terminal |
rustls |
TLS |
webpki-roots |
raízes TLS, se necessário |
serde |
serialização |
toml |
configuração |
rusqlite |
SQLite |
clap |
CLI |
url |
parsing de URL |
tracing |
logs |
directories |
caminhos padrão |
open |
abrir links externos |
Desktop futuro
Depois do MVP TUI, há três caminhos.
Caminho 1: Tauri
Melhor se você quiser:
- desktop bonito;
- frontend web local;
- core em Rust;
- app multiplataforma;
- possível mobile futuro.
Problema:
- se o core estiver em Go, integrar com Tauri exige bridge;
- pode ficar pesado conceitualmente para um navegador smallweb;
- ainda depende de WebView.
Caminho 2: Fyne
Melhor se você quiser:
- continuar em Go;
- GUI multiplataforma;
- empacotamento simples;
- menos peças.
Problema:
- UI pode ficar com cara genérica;
- controle visual menor.
Caminho 3: GTK
Melhor se você quiser:
- estética Linux/Unix;
- app mais nativo;
- integração com desktop livre.
Problema:
- multiplataforma mais chato;
- empacotamento mais trabalhoso.
Recomendação
Comece com TUI.
Só faça desktop quando o core estiver bom.
MVP v0.1
O MVP deve ser pequeno e realista.
Escopo
- abrir URL Gemini;
- abrir URL Gopher;
- renderizar Gemtext;
- renderizar Gopher menus;
- navegar por links;
- voltar/avançar;
- abrir URL manualmente;
- salvar favoritos;
- histórico básico;
- downloads simples;
- TOFU para Gemini;
- abrir HTTP externamente;
- config mínima.
Fora do escopo
- abas;
- imagens inline;
- Spartan;
- Nex;
- busca global;
- sincronização;
- contas;
- plugins;
- mobile;
- temas avançados;
- proxy;
- indexador;
- crawler.
MVP v0.2
Adicionar:
- Nex;
- busca na página;
- tags em favoritos;
- export/import bookmarks;
- cache opcional;
- modo offline para páginas salvas;
- melhor tela de erro;
- suporte a certificados de cliente Gemini;
- página inicial configurável;
- comando
moth gemini://...; - comando
moth --download URL.
MVP v0.3
Adicionar:
- Spartan;
- abas ou buffers;
- bookmarks por pasta/tag;
- leitor de feeds;
- coleção de cápsulas;
- painel de descoberta;
- modo arquivo local;
- render Markdown local;
- suporte inicial a plugins simples;
- tema Catppuccin/monocromático;
- pacote
.deb,.rpm, AppImage e Windows portable.
Roadmap sugerido
| Versão | Meta |
|---|---|
0.0.1 |
Abrir uma URL Gemini e imprimir no terminal |
0.0.2 |
Parser Gemtext |
0.0.3 |
UI Bubble Tea básica |
0.0.4 |
Links navegáveis |
0.0.5 |
Histórico e voltar |
0.0.6 |
Gopher |
0.0.7 |
Favoritos |
0.0.8 |
Downloads |
0.0.9 |
TOFU Gemini |
0.1.0 |
Primeiro MVP usável |
0.2.0 |
Nex |
0.3.0 |
Spartan experimental |
0.4.0 |
Pacotes e releases |
1.0.0 |
Estável para uso diário |
Comandos CLI
moth gemini://geminiprotocol.net/
moth gopher://gopher.floodgap.com/
moth --no-history gemini://example.org/
moth bookmark add gemini://example.org/ --tag smallweb
moth history
moth certs list
moth certs forget gemini://example.org/
UX
A UX deve ser calma.
Nada de tentar imitar navegador moderno.
Princípios de UX
- texto legível;
- links claros;
- atalhos previsíveis;
- erros humanos;
- downloads explícitos;
- nenhuma surpresa;
- nenhuma execução automática;
- tudo exportável;
- tudo compreensível.
Mensagem de erro ruim
ERR_TLS_CERT_MISMATCH
Mensagem de erro boa
O certificado deste servidor Gemini mudou.
Isso pode ser normal, mas também pode indicar interceptação.
Host:
gemini://example.org
Use:
[a] aceitar nova fingerprint
[c] cancelar
[?] entender este aviso
Página inicial
A página inicial pode mostrar:
- URL configurada;
- favoritos recentes;
- histórico recente;
- cápsulas sugeridas;
- ajuda rápida;
- últimos downloads.
Exemplo:
Moth
Home:
gemini://geminiprotocol.net/
Favorites:
1. Project Gemini
2. Floodgap Gopher
3. Nightfall Nex
Commands:
g open URL
B bookmarks
h history
? help
Sistema de plugins
Não implementar plugins no começo.
Mas deixar a arquitetura pronta.
Futuro:
- protocolo novo;
- conversor de formato;
- exportador;
- tema;
- comando;
- filtro de conteúdo.
Interface futura
type Plugin interface {
Name() string
Register(registry *Registry) error
}
Testes
Testar protocolos com fixtures locais.
Testes mínimos
- parse de URL Gemini;
- parse de resposta Gemini;
- parse de Gemtext;
- parse de Gopher menu;
- parse de Nex links;
- normalização de links relativos;
- redirect limit;
- certificado mudou;
- download com nome repetido;
- resposta maior que limite;
- timeout.
Testdata
testdata/
gemini/
simple.gmi
links.gmi
preformatted.gmi
redirects.txt
gopher/
menu.txt
text.txt
nex/
index.txt
Crawler opcional
Não coloque crawler no MVP.
Mas um crawler pequeno pode virar ferramenta separada:
moth-crawl gemini://example.org/ --depth 2 --output archive/
Uso:
- espelhar cápsulas;
- arquivar smallweb;
- gerar índice;
- encontrar links quebrados;
- criar coleção offline.
Isso combina muito com preservação digital.
Mas se entrar cedo, vai bagunçar o navegador.
Integração com permacomputação
Este projeto deve ter compromisso explícito com hardware modesto.
Metas técnicas
- rodar bem em 512 MB de RAM;
- funcionar em terminal simples;
- não depender de GPU;
- binário pequeno;
- sem Electron no MVP;
- sem telemetria;
- sem conta;
- sem cloud obrigatória;
- sem atualização forçada;
- configuração em arquivos legíveis.
Licença
Sugestão:
- AGPLv3, se você quer forçar compartilhamento de modificações em versões de rede;
- GPLv3, se quer manter copyleft forte;
- MIT, se quer máxima adoção e menos controle;
- Apache-2.0, se quer permissiva com proteção de patente.
Minha recomendação brutal:
Use GPLv3 ou AGPLv3.
Se o projeto é cyberativista e smallweb, MIT pode ser permissivo demais para empresas pegarem, embrulharem e devolverem nada.
README inicial
# Moth
A small hybrid browser for Gemini, Gopher, Nex, Spartan and other quiet protocols.
Moth is not a web browser.
It is a lantern for the small internet.
## Goals
- Lightweight
- Text-first
- Protocol-oriented
- Offline-friendly
- Privacy-respecting
- Useful on old machines
## Supported protocols
- Gemini
- Gopher
- Nex
- Spartan experimental
## Status
Pre-alpha.
Manifesto curto do projeto
A web não precisa ser pesada para ser viva.
Um documento não precisa de um império para existir.
Um computador velho não é lixo quando ainda pode carregar uma ideia.
Moth é uma lanterna para redes pequenas.
Tabela de decisão
| Decisão | Escolha |
|---|---|
| MVP | TUI |
| Linguagem | Go |
| UI | Bubble Tea |
| Estilo | Lip Gloss |
| Protocolos iniciais | Gemini + Gopher |
| Storage inicial | JSON |
| Storage futuro | SQLite |
| Desktop futuro | Tauri ou Fyne |
| Segurança Gemini | TOFU obrigatório |
| HTTP | abrir externamente |
| Imagens | baixar/abrir externamente |
| Plugins | só depois |
| Licença | GPLv3 ou AGPLv3 |
Plano de execução em 14 passos
- Criar repositório.
- Criar CLI mínima.
- Criar interface
Fetcher. - Implementar Gemini básico.
- Implementar parser Gemtext.
- Imprimir documento no terminal.
- Criar UI Bubble Tea.
- Adicionar navegação por links.
- Adicionar histórico.
- Implementar Gopher.
- Adicionar favoritos.
- Implementar downloads.
- Implementar TOFU.
- Lançar
v0.1.0.
Primeira tarefa real
Não comece desenhando interface.
Comece assim:
moth gemini://geminiprotocol.net/
O programa deve:
- conectar;
- validar TLS de forma mínima;
- enviar URL + CRLF;
- ler status;
- ler corpo;
- imprimir no terminal.
Só depois disso existe projeto.
Antes disso existe fantasia.
Fontes e referências
- Gemini Protocol: https://geminiprotocol.net/
- Gemini / Gemtext overview: https://en.wikipedia.org/wiki/Gemini_%28protocol%29
- RFC 1436 — The Internet Gopher Protocol: https://datatracker.ietf.org/doc/html/rfc1436
- Nex Protocol Specification: https://nightfall.city/nex/info/specification.txt
- Bubble Tea: https://github.com/charmbracelet/bubbletea
- Lip Gloss: https://github.com/charmbracelet/lipgloss
- Ratatui: https://ratatui.rs/
- Tauri: https://tauri.app/
- Permacomputing: https://permacomputing.net/
Detalhes recolhíveis
Notas de escopo para não destruir o projeto
O perigo deste projeto não é protocolo.
O perigo é vaidade.
Se você tentar fazer Gemini, Gopher, Nex, Spartan, HTTP, Markdown, RSS, imagens, abas, plugins, crawler, sincronização e desktop ao mesmo tempo, o projeto morre.
Faça um cliente Gemini feio.
Depois faça ele bonito.
Depois adicione Gopher.
Depois adicione Nex.
Depois pense em Spartan.
Depois pense em desktop.
Essa ordem salva o projeto.
Dicas finais
- Não implemente HTTP renderizado. Isso abre um inferno técnico desnecessário.
- Não comece por mobile. Mobile mata projeto pequeno com detalhe idiota.
- Não invente parser universal. Normalize cada protocolo para
Document. - Não confie em certificados silenciosamente. TOFU precisa ser explícito.
- Não execute downloads. Baixar é uma coisa; executar é outra.
- Não use Electron no MVP. Seria contraditório com a proposta.
- Não coloque Spartan no centro. Comece por Gemini e Gopher.
- Não confunda simples com malfeito. Smallweb pede cuidado, não gambiarra relaxada.