- Phase 1 — Form renderer dasar.
UiSchema+FieldNode+FieldType+BcRendererPropstypes, defaultFieldResolver(resolveField/resolveFields/resolveFieldType),BcRenderer.lite.tsxwith'form'/'detail'branches composing<BcForm>. Plain JS reactions (Level 0). 22 source-level + unit tests atcore/renderer/. - Phase 2 — Reaktivitas terintegrasi.
schema.reactionsforwarded into<BcForm>'s reactive engine (Level 1). All four ADR-004 effect kinds (DATA / VALIDATION / UI / VALUE) ride through unchanged via the existing wiring. - Phase 3 — Layout & nested.
'section'+'grid'grouping kinds with recursive<BcRenderer>calls;gridTemplateColumns: repeat(columns, ...).'list'kind composes<BcDataTable>.'custom'kind emits a sentinel<div data-bc-renderer-custom>for host-portal replacement. Repeater (array field) deferred to a follow-up sub-phase. - Phase 4 — BitCode JSON mapping — transformer lives in the BitCode engine, outside
@bitcode/uiscope. - Phase 5 — Custom resolver / Flutter track — opt-in extension. Hosts pre-process the schema into known field types before handing it to
BcRenderer(the renderer itself stays Mitosis-friendly with no runtime dynamic dispatch).
Platform low-code seperti BitCode tidak membangun UI dengan menulis kode
komponen manual per form. Ia menerima definisi JSON (views/*.json,
models/*.json) dan menghasilkan UI yang berjalan. Ini berbeda dengan
component library biasa (MUI/shadcn) yang dipakai via kode.
Kasus nyata di BitCode:
models/contact.json-> daftar field + label + tipe + validasi + reaksi.views/contact_list.json-> layout list, kolom, filter, aksi.views/contact_form.json-> layout form, section, tab, reaksi, tombol.- Engine membaca JSON dan menyajikan UI yang dapat dipakai pengguna akhir.
- Renderer di dalam go-json: go-json adalah bahasa/logika (expr-lang), bukan UI framework. JSON-nya tidak bisa render komponen (Go backend).
- Renderer di dalam BitCode core (monolit): merusak standalone
@bitcode/ui. Konsumen yang cuma mau schema-driven UI harus ikut menarik seluruh BitCode. - Ekspresi dievaluasi di frontend (default): go-json sudah authoritative di backend. Duplikat evaluator -> risiko drift.
- Standalone
@bitcode/ui(level 0-2 di ADR-004): konsumen bisa pakai schema-driven UI tanpa BitCode (seperti JsonForms / Formily / SurveyJS). - Single source of truth ekspresi: go-json di backend. Frontend terima hasil.
- Cross-platform: schema renderer harus portable (web via Mitosis, Flutter via track terpisah).
- JsonForms — renderer + schema (standalone, React/Angular/Material).
- Formily — schema + reactions (heavy, MobX).
- SurveyJS — JSON -> survey form (domain-specific).
- Filament — schema-driven forms via Livewire (PHP, server-rendered).
- Renderer berdiri sendiri di
@bitcode/uisebagai konsumen Level 3 di atas reactive engine (ADR-004). Konsumen bisa pakai tanpa BitCode. - Skema UI neutral (tidak domain-specific BitCode) — mirip JsonForms. BitCode memetakan definisi domain-nya ke skema UI ini.
- Ekspresi dievaluasi server-side oleh go-json; renderer terima hasil.
- Renderer tidak meng-render sendiri: ia mengkomposisi komponen yang sudah
ada di
@bitcode/ui+ reactive engine. Tidak ada layer rendering baru. - Ekstensibel via resolver: mapping tipe-skema -> komponen bisa diganti (untuk custom fields, tema, atau target non-web).
Keputusan rinci di bagian berikut.
Skema UI adalah dokumen netral (bukan domain BitCode). Konsumen standalone
punya skema sendiri (JsonForms-like); BitCode memetakan definisi domain
(models/*.json, views/*.json) ke skema ini.
interface UiSchema {
type: 'form' | 'list' | 'detail' | 'section' | 'grid' | 'custom';
fields?: FieldNode[]; // untuk form/list/detail
layout?: 'vertical' | 'horizontal' | 'grid';
columns?: number;
sections?: UiSchema[]; // nested
reactions?: Reaction[]; // dari ADR-004 (Level 1)
actions?: Action[]; // tombol/aksi form-level
}
interface FieldNode {
name: string;
label?: string;
type: string; // 'input' | 'select' | 'number' | 'date' | 'file' | 'lookup' | ...
required?: boolean;
disabled?: boolean;
visible?: string; // ekspresi (dievaluasi server-side)
options?: DataSource; // 4-layer (ADR-002)
validation?: ValidationRule[];
hint?: string;
reactions?: Reaction[];
}
- Tipe field = nama komponen di
@bitcode/ui(BcInput, BcSelect, dll). - Tidak ada "CRM"/"HRM" di skema. BitCode memetakan entitas CRM ke skema umum.
- Ekstensi
customuntuk field non-standar.
reactionspakai sintaks reaksi ADR-004 (fungsi JS atau string).- Ekspresi string (
visible: "status in ['draft','open']") dievaluasi server-side oleh go-json saat load skema atau saat recompute.
Renderer bukan layer rendering baru. Ia kompositor: menerjemahkan skema jadi
pohon komponen @bitcode/ui yang sudah ada, dibungkus ReactiveStore.
<BcRenderer
schema: UiSchema
values?: Record<string, unknown>
onChange?: (values) => void
onSubmit?: (values) => Promise<void>
resolver?: FieldResolver // opsional, ekstensibel
/>
- Parse skema -> daftar node.
- Resolve field (type -> komponen) via
FieldResolver. - Setup ReactiveStore dengan reaksi dari skema.
- Subscribe perubahan -> re-render node yang terdampak reaksi.
- Wire events (onChange, onSubmit, cascade) ke komponen.
interface FieldResolver {
resolve(type: string, node: FieldNode): ComponentType | null;
}
- Default resolver: peta tipe-skema -> komponen
@bitcode/ui('input'->BcInput,'select'->BcSelect,'date'->BcDateTime). - Custom resolver: konsumen bisa override untuk field non-standar atau target lain (mis. Flutter track, tema kustom).
- Nested rendering: section/tab di-resolve rekursif.
- Saat skema load: kirim ekspresi (visible, disabled, rules) ke go-json via BitCode endpoint; terima hasil (boolean/aturan) -> hydrate skema.
- Saat nilai berubah (reaksi): evaluasi ulang ekspresi terdampak di server, update skema ter-hydrate, re-render.
- Untuk standalone (tanpa BitCode): reaksi pakai fungsi JS, tanpa server.
- Web (React/Vue/Svelte/Solid/Angular) via Mitosis.
- React Native via NativeWind + komponen RN dari Mitosis target.
- Flutter (Tier C, track terpisah): BcRenderer Flutter yang mengonsumsi skema sama + field resolver Dart.
- Menyimpan definisi domain (
models/*.json,views/*.json) — domain concern. - Memetakan definisi domain ke
UiSchemanetral (transformer). - Men-feed skema ke
BcRendererdi frontend. - Mengevaluasi ekspresi (visible, disabled, rules) via go-json di backend.
- Menerima
UiSchema+ (opsional) endpoint ekspresi. - Merender komponen dari skema via resolver.
- Tidak tahu tentang CRM/HRM/model BitCode — domain-agnostic.
- Tidak mengevaluasi ekspresi (kecuali mode offline/standalone).
[BitCode JSON: models/contact.json]
│ (engine mapping)
▼
[UiSchema netral]
│ (API / embed)
▼
[BcRenderer(schema)]
│ (FieldResolver)
▼
[BcInput, BcSelect, ...] ← wrapped ReactiveStore (ADR-004)
│ (saat render, ekspresi dikirim)
▼
[go-json server] ─ evaluates ─► [hasil: boolean/rules] ─► [hydrate skema]
- BitCode endpoint
/api/expr/evaluate(atau batch) menerima{ expr, scope }. - go-json evaluasi, return
{ result }. - Renderer hydrate skema + re-render node terdampak.
- expr-js plug-in opsional untuk: form builder live-preview, offline mode (lihat ADR-004 Phase E).
<BcRenderer schema={mySchema} resolver={customResolver} />
- Skema didefinisikan manual (bukan dari BitCode).
- Reaksi = fungsi JS, tanpa server round-trip.
- Ini sama dengan JsonForms-style UX, zero BitCode dependency.
UiSchemaminimal (form + field node) + defaultFieldResolveruntuk komponen@bitcode/uiyang sudah ada.BcRenderersebagai kompositor.- AC: skema JSON sederhana -> form berfungsi; field dasar (input/select/ number/date) jalan; submit handler kerja.
- Wire
ReactiveStore(ADR-004) dalam renderer. - Reaksi dari skema (DATA/VALIDATION/UI/VALUE) aktif.
- AC: skema dengan reaksi cascading/conditional validasi/visibility jalan.
- Section, tab, grid, nested schema.
- Repeater (array field) di-render dari skema.
- AC: form kompleks (ERP-style) ter-render dari skema tunggal.
- Transformer BitCode JSON ->
UiSchema. - Endpoint ekspresi go-json + hydrate.
- AC: satu entitas ERP (contact/lead/invoice) ter-render dari definisi BitCode asli, dengan reaksi lintas-field bekerja.
- Custom resolver (field non-standar, tema).
- Flutter track (BcRenderer Flutter yang mengonsumsi skema sama).
- AC: field kustom ter-render via resolver custom; Flutter renderer mengonsumsi skema identik.
- Renderer standalone (tanpa BitCode, pakai skema manual) — AC Phase 1.
- 4 efek reaksi ADR-004 jalan dalam renderer — AC Phase 2.
- BitCode JSON -> UiSchema -> UI end-to-end — AC Phase 4.
- Ekspresi dievaluasi go-json server-side (single source of truth).
- Custom resolver bekerja; target non-web (Tier C) kontrak terdefinisi.
- BitCode jadi low-code sungguhan: definisi JSON -> UI yang berjalan.
@bitcode/uitetap standalone: renderer bisa dipakai tanpa BitCode, mirip JsonForms/Formily — menambah pasar library.- Single source of truth ekspresi (go-json): tidak ada evaluator duplikat, tidak ada drift frontend<->backend.
- Satu skema, banyak target: web (Mitosis) + Flutter (track terpisah) + potensi Lynx/RN — konsisten.
- Ekstensibel via resolver: field kustom, tema, atau target baru = plug-in, bukan rewrite.
- Skema netral + mapping BitCode = dua lapisan dokumen (domain + UI). Perlu tooling mapping yang teruji.
- Round-trip ekspresi ke server -> butuh latency management (cache, debounce, batch).
- Nested schema + repeater = kompleksitas rendering (rekursi, state).
- Skema netral kurang ekspresif untuk kasus BitCode tertentu -> mitigasi:
customtype + resolver; jangan memaksakan semua kasus ke skema standar. - Over-abstraction renderer (Formily-level) -> mitigasi: renderer = kompositor sederhana, bukan framework penuh; komponen tetap dumb.
- Flutter track butuh renderer Dart terpisah + resolver Dart -> mitigasi: kontrak skema + FieldResolver interface harus konsisten lintas bahasa.
- ADR-002 (3-layer, SSR/H2, DataSource), ADR-003 (taksonomi, BcForm P0), ADR-004 (ReactiveStore, reaksi, Evaluator interface).
packages/go-json(expr-lang authoritative di Go).- Prior art: JsonForms, Formily, SurveyJS, Filament (PHP), Retool (low-code).