Vitrine
Um programa de cima para baixo vira uma página web. Sem HTML, sem JavaScript, sem separar o que calcula do que mostra.
Vitrine é o framework de painéis e aplicações de dados do DataForge. Você escreve um programa de cima para baixo; ele vira uma página web.
adopt Arcane.Vitrine as V
action painel():
V.titulo("Vendas")
regiao := V.escolha("Região", ["Sul", "Sudeste", "Norte"])
V.metrica("Receita", "R$ 128.400", variacao := 12.5)
V.grafico_barras(vendas_de(regiao), x := "mes")
V.rodar(painel, porta := 8501)Isso é a aplicação inteira. Não há HTML, não há CSS, não há JavaScript, não há build, e não há separação entre o que calcula e o que mostra.
O modelo de execução#
A cada interação, o programa inteiro roda de novo — e o estado da sessão sobrevive.
clique → o programa roda do começo → a árvore vira HTML → a tela troca
↑ │
└────────── o estado da sessão continua ─────────────┘Parece desperdício e é o contrário. Quem escreve nunca pensa em callback, em diffing, nem em qual pedaço da tela atualizar: a linha de cima sempre aconteceu antes da linha de baixo, como em qualquer programa.
É por isso que um componente devolve o que quem escreve precisa. V.botao(…) devolve yes ou no; V.entrada(…) devolve o texto digitado. A linha seguinte já usa o valor:
given V.botao("Salvar"):
salvar(V.entrada("Nome"))
V.sucesso("Pronto.")Vitrine ou Kiln?#
Os dois são frameworks web, e a escolha é clara:
| Kiln | Vitrine | |
|---|---|---|
| Para | sites e APIs | painéis e aplicações de dados |
| Você escreve | rotas que devolvem o que quiser | um programa de cima para baixo |
| A página é | um template que você controla | a árvore que o programa montou |
| Cliente | o que você puser lá | ~4 KB, prontos |
| Exemplo | uma loja, uma API REST | um dashboard, um formulário interno |
A Vitrine roda sobre o Kiln: HTTP, rotas, arquivos estáticos, sessão, cabeçalhos de segurança e REST já existiam lá, testados. Reimplementá-los criaria duas implementações do mesmo protocolo para divergirem. V.montar() devolve o app Kiln por baixo, e nele você acrescenta rota, REST ou middleware.
Um painel completo#
adopt Arcane.Vitrine as V
V.app("Business Intelligence", icone := "📊")
mark @V.cache
action vendas():
yield Banco.consultar("SELECT mes, receita, meta FROM vendas")
action painel():
lado := V.lateral()
regiao := lado.escolha("Região", ["Sudeste", "Sul", "Norte"])
V.titulo("Dashboard de Vendas", icone := "📊")
colunas := V.colunas(4)
colunas[0].metrica("Receita", "R$ 850.000", variacao := 18.0)
colunas[1].metrica("Clientes", "12.450", variacao := 8.0)
colunas[2].metrica("Pedidos", "32.500", variacao := 14.0)
colunas[3].metrica("Conversão", "8.4%", variacao := 1.2)
V.cabecalho("Evolução")
V.grafico_linha(vendas(), x := "mes", y := ["receita", "meta"])
V.cabecalho("Dados")
V.frame(vendas())
V.exportar_csv(vendas())
V.pagina("/", painel)
V.rodar(porta := 8501)Começar#
dataforge vitrine new meupainel
cd meupainel
dataforge vitrine dev # http://127.0.0.1:8501O projeto criado já tem página, dados, testes e um forge.toml — e passa nos próprios testes antes de você tocar em qualquer coisa.
O painel completo do exemplo está em examples/vitrine_dashboard.df, e ele também se testa sozinho:
dataforge run examples/vitrine_dashboard.df # os testes
dataforge run examples/vitrine_dashboard.df -- --servir # no navegadorDe onde vêm os dados#
De lugar nenhum especial. A Vitrine desenha; quem lê os dados é o módulo que você já usaria num script — e é por isso que não há um "conector" a aprender.
adopt Arcane.Vitrine as V
adopt Arcane.Database as DB
adopt Arcane.Analytics as An
adopt Arcane.Cortex as ML
banco := DB.connect("vendas.db")
mark @V.cache
action vendas():
yield DB.query(banco, "SELECT mes, numero, receita FROM v")
action prever(mes):
modelo := ML.linear(vendas(), "receita", ["numero"])
yield ML.prever(modelo, [{"numero": mes}])[0]
action painel():
V.frame(vendas()) // do banco
V.grafico_barras(An.from_records(vendas()), x := "mes")
V.vault(An.describe(An.from_records(vendas()))) // estatística
V.metrica("Previsão", round(prever(4), 1)) // modelo| Para | Use | E passe para |
|---|---|---|
| banco relacional | `Arcane.Database` · Arcane.Forge | V.frame, V.tabela, qualquer gráfico |
| CSV, JSON, Excel | `Arcane.IO` · `Arcane.Excel` | o mesmo |
| estatística e DataFrame | `Arcane.Analytics` | um Frame entra direto |
| Parquet e Data Lake | `Arcane.Lago` | o mesmo |
| streaming | `Arcane.Stream` | com V.atualizar_a_cada(n) |
| aprendizado de máquina | `Arcane.Cortex` | V.metrica, V.grafico_dispersao |
| uma API de fora | `Arcane.Http` | sob mark @V.cache, sempre |
A mesma aplicação serve uma API#
V.montar() devolve o app Kiln por baixo. Acrescente rotas nele e o painel e a API vivem no mesmo processo, na mesma porta, lendo das mesmas ações em cache:
adopt Kiln
kiln := V.montar()
Kiln.get(kiln, "/api/vendas", lambda req: {"itens": vendas()})
Kiln.use(kiln, Kiln.cors())
Kiln.use(kiln, Kiln.rate_limit(120))
V.subir(porta := 8501)Vale para tudo do Kiln: CORS, limite de taxa, CSRF, cabeçalhos, validação de esquema, Kiln.resource com as sete rotas RESTful. Ver Middleware do Kiln — e `Arcane.API`, que exporta essas rotas para o Insomnia e o Postman.
Zero dependência, inclusive no navegador#
O gráfico é SVG escrito no servidor. O cliente são ~4 KB de JavaScript sem build e sem CDN — ele manda de volta o que o usuário fez e troca o miolo da página.
Não é purismo: uma biblioteca de gráficos vinda de CDN quebra qualquer aplicação que rode em rede fechada, que é exatamente onde painel de dados costuma rodar. E SVG imprime, escala e é legível por leitor de tela.
Onde continuar#
Componentes
texto, entrada, dadosOs 40 componentes, o que cada um devolve e quando usar formulário.
Layout
colunas, abas, cartõesPor que a área é um objeto, e não um bloco de contexto.
Estado e cache
sessão, global, TTL, LRUOs três lugares onde um valor mora, e quem enxerga cada um.
Gráficos
sete tipos, em SVGA forma curta e a construída, e o que os dados precisam parecer.
Páginas e segurança
rotas, login, permissõesMultipágina, parâmetros de URL, autenticação e autorização.
Acessibilidade e idioma
ARIA, teclado, i18nO que já vem pronto para teclado e leitor de tela, e como traduzir.
Testes
sem navegadorA sonda clica, digita e pergunta — e o pedido HTTP sem socket.
Produção
hot reload, métricas, pluginsSubir, observar, e o que colocar na frente.
Um projeto completo
banco, ETL, painel, testesAnálise de vendas de ponta a ponta, do CSV ao gráfico.
Referência
115 símbolosTudo o que sai de adopt Arcane.Vitrine, em uma tabela.