Como seu código fica
Em uma migração conduzida por agentes, o Buildprint primeiro cria a base do seu projeto: seus tipos de dados, conjuntos de opções, chamadas do API Connector e estilos. Depois, os agentes escrevem suas páginas e fluxos de trabalho sobre essa base. Os agentes escolhem como dividir cada página em arquivos, então os arquivos exatos variam de um app para outro.
Os exemplos nesta página usam um app com um tipo de dados Project e um conjunto de opções Project Status.
Onde cada parte do seu app Bubble fica
No Bubble | No seu código |
|---|---|
Página |
|
Elemento reutilizável |
|
Tipo de dados |
|
Regras de privacidade |
|
Conjunto de opções |
|
Fluxo de trabalho de backend |
|
Chamada do API Connector |
|
Estilos |
|
Textos do app |
|
Estrutura de pastas
Um projeto com Next.js e Supabase fica assim:
my-app/
├── AGENTS.md Instructions for coding agents
├── .buildprint/ Screenshots and notes that the agents use to check their work
├── supabase/migrations/ Creates your database tables
└── src/
├── app/ Your pages
│ └── dashboard/
│ ├── page.tsx The page
│ ├── actions.ts Actions that run on the server
│ ├── _components/ Parts of the page
│ └── workflows/ The page's workflows
├── components/
│ ├── reusable/ Your reusable elements
│ └── ui/ Buttons, inputs and other Bubble elements
├── db/schema/ Your data types
├── privacy/ Your privacy rules
├── options/ Your option sets
├── workflows/ Your backend workflows, in one folder for each area
├── integrations/ Your API Connector calls, in one folder for each API
├── i18n/ Your app texts
└── styles/ Your colors, fonts and named stylesUm projeto com Convex tem uma pasta convex/ em vez de supabase/ e src/db/. Seus tipos de dados e fluxos de trabalho de backend ficam nela.
Exemplo: um tipo de dados
O tipo de dados Project tem os campos Name, Owner, Status, Due date e Budget. No Supabase, ele se torna uma tabela:
// Bubble data type ID: custom.project
export const project = pgTable(
"project",
{
id: text("id").primaryKey(),
// Bubble built-in field: Slug
slug: text("slug"),
// Bubble built-in field: Created By
createdBy: text("created_by"),
// Bubble field ID: budget_number
budget: doublePrecision("budget"),
// Bubble field ID: due_date_date
dueDate: timestamp("due_date", { withTimezone: true }),
// Bubble field ID: name_text
name: text("name"),
// Bubble field ID: owner_user
owner: text("owner"),
// Bubble field ID: status_option_project_status
status: text("status"),
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
modifiedAt: timestamp("modified_at", { withTimezone: true }).notNull().defaultNow(),
},
(table) => [index("idx_project_owner").on(table.owner)],
);Cada campo mantém um comentário com seu ID do Bubble, para que você possa encontrá-lo no seu app Bubble.
Cada registro mantém seu ID do Bubble. Os vínculos entre registros continuam iguais depois que você migra seus dados.
Seu app pesquisa projetos por proprietário, então o Buildprint adiciona um índice para isso. Um índice torna essa pesquisa rápida.
No Convex, o mesmo tipo de dados fica assim:
export const project = defineTable({
bubbleId: v.optional(v.string()),
slug: v.optional(v.string()),
createdBy: v.optional(v.id("users")),
budget: v.optional(v.number()),
due_date: v.optional(v.number()),
name: v.optional(v.string()),
owner: v.optional(v.id("users")),
status: v.optional(v.string() /* option set option.project_status */),
modifiedAt: v.number(),
})
.index("by_bubbleId", ["bubbleId"])
.index("by_owner", ["owner"]);Exemplo: um conjunto de opções
O conjunto de opções Project Status tem as opções Active e Archived, além de um atributo Color:
// Bubble option set ID: option.project_status
export const projectStatus = {
bubbleId: "option.project_status",
label: "Project Status",
attributes: {
color: { bubbleId: "color_text", label: "Color" },
},
values: [
{ key: "active", label: "Active", bubbleId: "value.active", attributes: { color: "#16a34a" } },
{ key: "archived", label: "Archived", bubbleId: "value.archived", attributes: { color: "#6b7280" } },
],
} as const;
export type ProjectStatusValue = (typeof projectStatus.values)[number]["key"];Seu código usa o conjunto de opções da mesma forma que o Bubble. Por exemplo, projectStatus.values é a lista de todos os status.
Páginas e fluxos de trabalho
Os agentes escrevem cada página e fluxo de trabalho manualmente. Eles reproduzem o comportamento do seu app Bubble e, em seguida, acrescentam provas de que funciona. Por exemplo, capturas de tela ou resultados de testes. Leia Mantenha o mesmo comportamento para saber como eles verificam isso.
Para orientar os agentes sobre como você quer que o código fique, adicione suas regras a AGENTS.md. Por exemplo: "Coloque cada formulário em seu próprio arquivo."