Sistema de arquivos
Quando você clona uma branch, a CLI grava um app Bubble normalizado e 'fragmentado'. Este artigo é a referência para o que reside em cada lugar, que forma assume e o que você não deve tocar.
O sistema de arquivos não é um dump JSON fiel do seu app Bubble. É uma projeção projetada para edição: campos voláteis são removidos, campos derivados são recalculados ao aplicar e vários campos são elevados para a estrutura de diretórios.
Layout de nível superior
my-app/ # app root (one per Bubble app)
.buildprint/ # internal state — never edit
app.json # { schemaVersion, appId, tokenRef }
remote.git/ # shared bare repo
test/ # branch workspace (git worktree)
.git # gitlink into the shared bare repo
.gitignore # ignores /.buildprint/
app.json # top-level Bubble scalars
settings/
data_types/
option_sets/
styles/
pages/
element-definitions/
mobile-views/
global-elements/
api/A raiz do app (app root) é compartilhada por todas as branches de um app Bubble. Cada branch do Bubble se materializa como uma pasta irmã dentro dela. O nome da pasta da branch deve corresponder à branch do git em checkout — veja Workspace para o ciclo de vida e travas de segurança.
Conteúdo da pasta da branch
Cada diretório dentro de uma pasta de branch mapeia para um conceito do Bubble:
app.json— escalares de nível superior para o app (nome, plano, padrões). Campos que pertencem a outros lugares foram removidos.settings/— configurações do Bubble.settings/client-safe.jsoncontém o corpo principal das configurações;settings/api-connector/<plugin-id>/plugin.jsonesettings/api-connector/<plugin-id>/calls/<call-id>.jsoncontêm definições do conector de API.data_types/<type-id>/type.json— uma pasta por tipo de dado. A lista de campos está embutida no corpo.option_sets/<set-id>/option-set.json— uma pasta por conjunto de opções. Os valores estão embutidos, ordenados porsort_factor.styles/— estilos agrupados por tipo de elemento:styles/<ElementType>/<style-id>.json. Tokens de design são elevados para arquivos irmãos:styles/tokens.json,styles/defaults.json,styles/fonts.json.pages/<page-id>/— uma pasta por página. Arquivo de corpopage.json; elementos sobelements/; workflows sobworkflows/(veja abaixo).element-definitions/<id>/— elementos reutilizáveis. Mesma estrutura das páginas; arquivo de corpo éreusable.json.mobile-views/<id>/— telas móveis. Mesma estrutura das páginas.global-elements/<id>/— elementos globais (superfícies de todo o app). Mesma estrutura das páginas.api/— workflows de backend, opcionalmente agrupados em pastas de workflow do Bubble (veja Pastas de workflow abaixo).
Páginas, reutilizáveis, visualizações móveis, elementos globais
Estes quatro diretórios usam a mesma estrutura. O arquivo de corpo na raiz da pasta contém as propriedades da entidade; elementos filhos e workflows vivem em subdiretórios irmãos.
pages/<page-id>/
page.json # page properties + children manifest
elements/
<element-key>/
element.json # element properties, type, style, states
<child-element-key>/ # nested folder per child element
element.json
<grandchild-key>/
element.json
workflows/
<workflow-id>/
workflow.json # trigger and metadata
actions/
0.json # integer filenames = insertion order
1.json
2.jsonPastas de elementos
O nome da pasta é a chave de mapa (map key) do elemento (a chave que ele possui dentro do objeto
elementsdo pai), não o campoiddentro do corpo. Estes podem diferir; referências em outras partes do app usam a chave de mapa.Elementos filhos vivem como subpastas de seu pai. A árvore no disco reflete a árvore de contenção no Bubble.
Workflows e ações
Cada workflow ganha sua própria pasta contendo
workflow.json(gatilho, metadados) e uma pastaactions/com um arquivo por ação.Os nomes dos arquivos de ação são inteiros em formato de string —
0.json,1.json,2.json. Eles codificam a ordem de execução.Intervalos na sequência são válidos e preservados literalmente (algumas estruturas do Bubble usam intencionalmente chaves inteiras esparsas).
Pastas de workflow
O Bubble permite agrupar workflows em pastas nomeadas. No disco, uma pasta de workflow é um diretório com um config.json ao lado dos workflows que ele contém:
api/
<folder-id>/
config.json # { "name": "Billing" }
<wf-id>/
workflow.json
actions/0.json
<wf-id>/ # workflow with no parent folder
workflow.json
actions/0.jsonOs metadados da pasta vivem em
config.json. Para renomear uma pasta, edite esse arquivo.Para mover um workflow entre pastas, mova o próprio diretório do workflow.
Pastas de workflow sob
api/não podem ser aninhadas — apenas um nível. A regra de verificaçãoapi-folder-flatimpõe isso.Os corpos dos workflows não carregam um campo
wf_folder— a pasta pai é derivada da árvore de diretórios. Adicionar esse campo aoworkflow.jsonnão faz nada; reorganize as pastas em vez disso.
A mesma estrutura se aplica em pages/<page-id>/workflows/, element-definitions/<id>/workflows/, mobile-views/<id>/workflows/ e global-elements/<id>/workflows/.
Estilos
Os estilos são divididos por tipo de elemento. Cada subdiretório contém um arquivo JSON por estilo:
styles/
Button/
primary.json
secondary.json
Text/
heading.json
body.json
tokens.json # color_tokens, color_tokens_user
defaults.json # default_styles, default_icon_set
fonts.json # font_tokens, font_tokens_user, fontsOs três arquivos elevados no topo de styles/ foram movidos para fora de settings/ para que os tokens de design residam em um único lugar previsível.
Forma canônica de JSON
Cada arquivo JSON que a CLI grava passa por um único formatador canônico. As regras:
UTF-8 com finais de linha LF e uma nova linha no final.
Indentação de dois espaços. Um valor por linha em objetos; um elemento por linha em arrays não triviais.
Sem tabulações, sem caracteres CR, sem espaços em branco no final.
Chaves de objeto que não são inteiras são classificadas alfabeticamente. Mapas com chaves inteiras (
actionsde workflow,statesde elemento,TextExpression.entries) preservam a ordem de inserção.
A saída idêntica em bytes para a mesma entrada mantém os diffs de sync limpos e conflitos de mesclagem mínimos. Se você editar um arquivo manualmente e a formatação mudar, a regra de verificação canonical-form sinalizará — execute novamente o comando que produziu o arquivo ou passe-o por um formatador JSON.
IDs e nomes de arquivos
Buildprint gera seus próprios IDs.
Novos IDs vêm de
buildprint utils generate-ids <n>(um por linha, ordem lexicográfica, entre 1 e 100 por vez). Chame isso antes de criar entidades manualmente.Apps existentes podem conter dois formatos de ID do Bubble (short-uid e timestamp-random). Os leitores lidam com ambos; os gravadores sempre emitem a forma canônica do Buildprint.
Chaves com o prefixo
_bp_oubp-prefix são reservadas para a CLI. Ocasionalmente, você verá arquivos de marcação internos e sentinelas (por exemplo,bp_dir.jsonou uma pastabp_no_type/sob estilos) — trate-os como internos e não os edite manualmente.
Manifestos de filhos
Todo pai que contém elementos mantém um manifesto de seus filhos em seu arquivo de corpo:
{
"children": ["hdr_0001", "content_0002", "footer_0003"]
}A invariante: o conjunto de subpastas filhas sob elements/ deve corresponder ao conjunto de chaves listadas em children, e a ordem em children é a ordem de exibição canônica. Entradas pendentes ou pastas órfãs são erros sinalizados pela regra de verificação children-manifest.
A ordem de renderização é separada: properties.order (ordem flex) e properties.zindex (empilhamento) descrevem preocupações de CSS e residem em elementos individuais quando definidos. A CLI não inventa valores para estes — apenas o Bubble faz isso.
O que não editar
.buildprint/— o repositório git bare compartilhado e a configuração do app. Gitignorado no worktree. Não mexa nisso.Internos do
.git/— trate o worktree como qualquer outro checkout do git.Campos elevados - qualquer coisa que tenha sido movida de um arquivo de corpo para a estrutura de diretórios. Escrever
properties.wf_folderde volta noworkflow.json, outypede volta em um corpo de estilo, não tem efeito e pode disparar erros de verificação.Campos voláteis - se você vir um campo perdido como
last_change,creation_date,_id,screenshotouuid_counterreaparecer após uma edição manual, remova-o. A CLI os remove na fragmentação e não os regenerará.Arquivos de marcação internos — sentinelas sob pastas ou arquivos
__bp_*. Eles existem para que a CLI possa lidar com casos especiais (colisões sem distinção entre maiúsculas e minúsculas, estilos sem tipo). Não os crie nem os renomeie.
Modelo Git
A pasta da branch é um git worktree real apoiado pelo repositório bare em <app-root>/.buildprint/remote.git/. Você pode usar git status, git diff, git log, git add e git commit normalmente.
Vale a pena conhecer quatro refs:
refs/heads/<branch>— seus commits locais. É aqui que você edita.refs/remotes/buildprint/<branch>— o último commit local que foi aplicado com sucesso ao Bubble. Usegit log buildprint/<branch>..HEADpara ver o que está localmente à frente.refs/bubble/<branch>— o snapshot mais recente do Bubble (reside no repositório bare).buildprint syncatualiza esta ref e a mescla em sua branch.refs/published/<branch>— ref de controle interno dentro do repositório bare, espelhada parabuildprint/<branch>pelogit fetch.