Moon Flower Society > Navegador Híbrido Smallweb

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.


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:

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:


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:


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:

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:

Pontos críticos em Gemini

O maior detalhe não é renderizar texto. Isso é fácil.

O ponto crítico é segurança:

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:

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:

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:

  1. criar interface Fetcher;
  2. implementar Gemini;
  3. implementar Gopher;
  4. implementar Nex;
  5. só então adicionar Spartan;
  6. 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:

Desvantagens:

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:

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:

Desvantagens:

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:

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

Política para imagens

No MVP:

Futuro:


Storage

O navegador precisa persistir:

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:


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:

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:

Problema:

Caminho 2: Fyne

Melhor se você quiser:

Problema:

Caminho 3: GTK

Melhor se você quiser:

Problema:

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

Fora do escopo


MVP v0.2

Adicionar:


MVP v0.3

Adicionar:


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

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:

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:

Interface futura

type Plugin interface {
    Name() string
    Register(registry *Registry) error
}

Testes

Testar protocolos com fixtures locais.

Testes mínimos

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:

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


Licença

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.


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

  1. Criar repositório.
  2. Criar CLI mínima.
  3. Criar interface Fetcher.
  4. Implementar Gemini básico.
  5. Implementar parser Gemtext.
  6. Imprimir documento no terminal.
  7. Criar UI Bubble Tea.
  8. Adicionar navegação por links.
  9. Adicionar histórico.
  10. Implementar Gopher.
  11. Adicionar favoritos.
  12. Implementar downloads.
  13. Implementar TOFU.
  14. Lançar v0.1.0.

Primeira tarefa real

Não comece desenhando interface.

Comece assim:

moth gemini://geminiprotocol.net/

O programa deve:

  1. conectar;
  2. validar TLS de forma mínima;
  3. enviar URL + CRLF;
  4. ler status;
  5. ler corpo;
  6. imprimir no terminal.

Só depois disso existe projeto.

Antes disso existe fantasia.


Fontes e referências


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

View the original Markdown file


Ideas | What changed | RSS | About | Text version

Pablo Murad <pablomurad@pm.me>