Moon Flower Society > Navegador Híbrido Smallweb
Documentação de ideia para construir um navegador híbrido para Gemini, Gopher, Nex, Spartan e outros protocolos da smallweb.
Posted July 2, 2026. Markdown. Tags: smallweb, gemini, gopher, nex, spartan, navegador, permacomputação, tui, go, rust.
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.
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:
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:
MothNome 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:
LanternBurrowCapsuleSmallgateGloomMurmurNighthostWayfarerPeregrineHollowCriar 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.
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.
Ele não deve começar como:
Isso mataria o projeto.
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.
| 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 é 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:
gemini://;1965;text/gemini, também chamado de Gemtext;O maior detalhe não é renderizar texto. Isso é fácil.
O ponto crítico é segurança:
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 |
Blocos principais:
| Sintaxe | Bloco |
|---|---|
# |
Heading 1 |
## |
Heading 2 |
### |
Heading 3 |
=> |
Link |
* |
Lista |
> |
Citação |
| ``` | Bloco preformatado |
| texto | Parágrafo |
Gopher é mais antigo e ainda mais simples.
Ele funciona como um sistema de documentos e menus distribuídos.
Características importantes:
gopher://;70;| 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 |
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 é um protocolo simples de recuperação distribuída de documentos, inspirado por Gopher e Gemini.
Características importantes:
1900;=> como links;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 deve ser tratado como protocolo experimental no projeto.
Não coloque Spartan como base do MVP.
A regra prática:
Fetcher;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.
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.
| 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 |
Go é uma escolha pragmática.
Vantagens:
Desvantagens:
Mesmo assim, para este projeto, Go é provavelmente o caminho mais rápido para sair do papel.
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 |
Escolha Rust se o objetivo for:
Não escolha Rust se você quer MVP rápido e pouca fricção.
Rust é ótimo, mas ele cobra pedágio.
Python pode servir para protótipo, mas eu não faria o produto final nele.
Vantagens:
Desvantagens:
Python pode ser usado para scripts auxiliares, testes de crawler e conversores.
A primeira interface deve ser TUI.
Nada de abrir com GUI antes de provar o core.
┌────────────────────────────────────────────────────────────────────┐
│ 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 │
└────────────────────────────────────────────────────────────────────┘
| 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 |
A arquitetura deve ter separação radical entre:
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
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
}
type Registry struct {
fetchers map[string]Fetcher
}
func (r *Registry) Register(fetcher Fetcher) {
for _, scheme := range fetcher.Schemes() {
r.fetchers[scheme] = fetcher
}
}
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.
A renderização deve ser simples.
Nada de tentar simular HTML.
No MVP:
Futuro:
O navegador precisa persistir:
Boa para MVP:
~/.config/moth/config.toml
~/.local/share/moth/bookmarks.json
~/.local/share/moth/history.json
~/.local/share/moth/certs.json
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)
);
Este projeto parece simples, mas segurança ainda importa.
Não por causa de “exploit hollywoodiano”.
Por causa de erro besta.
| 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 |
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.
O navegador não deve renderizar HTTP.
Ele deve:
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:
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]
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ê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 |
| 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 |
Não exagere.
Para o MVP, use poucas dependências:
bubbletea
bubbles
lipgloss
toml
sqlite ou json
O resto entra depois.
| 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 |
Depois do MVP TUI, há três caminhos.
Melhor se você quiser:
Problema:
Melhor se você quiser:
Problema:
Melhor se você quiser:
Problema:
Comece com TUI.
Só faça desktop quando o core estiver bom.
O MVP deve ser pequeno e realista.
Adicionar:
moth gemini://...;moth --download URL.Adicionar:
.deb, .rpm, AppImage e Windows portable.| 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 |
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/
A UX deve ser calma.
Nada de tentar imitar navegador moderno.
ERR_TLS_CERT_MISMATCH
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
A página inicial pode mostrar:
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
Não implementar plugins no começo.
Mas deixar a arquitetura pronta.
Futuro:
type Plugin interface {
Name() string
Register(registry *Registry) error
}
Testar protocolos com fixtures locais.
testdata/
gemini/
simple.gmi
links.gmi
preformatted.gmi
redirects.txt
gopher/
menu.txt
text.txt
nex/
index.txt
Não coloque crawler no MVP.
Mas um crawler pequeno pode virar ferramenta separada:
moth-crawl gemini://example.org/ --depth 2 --output archive/
Uso:
Isso combina muito com preservação digital.
Mas se entrar cedo, vai bagunçar o navegador.
Este projeto deve ter compromisso explícito com hardware modesto.
Sugestão:
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.
# 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.
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.
| 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 |
Fetcher.v0.1.0.Não comece desenhando interface.
Comece assim:
moth gemini://geminiprotocol.net/
O programa deve:
Só depois disso existe projeto.
Antes disso existe fantasia.
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.
Document.View the original Markdown file
Ideas | What changed | RSS | About | Text version
Pablo Murad <pablomurad@pm.me>