Getting started
If you have not read the product overview and package split yet, start with Introduction.
This guide builds a minimal editor with Vite + TypeScript + Viewfly where you can type and press Enter for new lines: @textbus/core supplies the model and kernel, @textbus/platform-browser handles browser mounting and input, and @textbus/adapter-viewfly renders the document as a Viewfly tree. If you use Vue or React, you do not need Viewfly—see the Vue adapter and React adapter.
What you'll learn
- Install the smallest useful set of npm packages
- Configure decorators and JSX for this stack
- Wire
ViewflyAdapterandBrowserModule, create an instance withnew Textbus, thenrender
1. Scaffold the project and install dependencies
Create a Vite project locally (Vanilla + TypeScript template):
# Vanilla + TypeScript template — easy to add Viewfly JSX
npm create vite@latest my-textbus-editor -- --template vanilla-ts
cd my-textbus-editor
npm installInstall Textbus and Viewfly packages (pin versions to the current 5.x line on npm; ranges below are illustrative):
# reflect-metadata: decorator metadata; the rest are core, browser layer, Viewfly adapter, and runtime
npm install reflect-metadata @textbus/core @textbus/platform-browser @textbus/adapter-viewfly @viewfly/core @viewfly/platform-browser
npm install -D vite typescript @types/nodePoint the entry file to src/App.tsx (if it is still main.ts, rename it and update index.html so the script loads /src/App.tsx).
2. Configure TypeScript and Vite
The kernel relies on decorator metadata, and this walkthrough uses Viewfly JSX. Set tsconfig.json to at least:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
// Viewfly: react-jsx automatic runtime, resolve via @viewfly/core
"jsx": "react-jsx",
"jsxImportSource": "@viewfly/core",
// Decorators + emitDecoratorMetadata: required for Textbus DI
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
// Matches decorator field init order (same as this repo’s examples)
"useDefineForClassFields": false,
"skipLibCheck": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"]
},
"include": ["src"]
}import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
// Match tsconfig jsxImportSource
jsx: 'automatic',
jsxImportSource: '@viewfly/core'
},
optimizeDeps: {
esbuildOptions: {
// Pre-bundle deps with the same Viewfly JSX settings
jsx: 'automatic',
jsxImportSource: '@viewfly/core'
}
}
})Setting useDefineForClassFields to false avoids odd interactions between some decorators and class fields (aligned with the examples in this repository).
3. Page HTML
Root index.html exposes the Viewfly mount #root; App.tsx renders #editor-host (.tb-editor-host needs enough min-height—240px in this sample—or the editing surface is hard to click or focus:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Textbus minimal sample</title>
<style>
body {
margin: 0;
padding: 1rem;
}
/* Editor host needs height so it is easy to click and focus */
.tb-editor-host {
min-height: 240px;
border: 1px solid #ccc;
border-radius: 4px;
}
</style>
</head>
<body>
<!-- Viewfly mount -->
<div id="root"></div>
<!-- Entry: first line of App.tsx must be import 'reflect-metadata' -->
<script type="module" src="/src/App.tsx"></script>
</body>
</html>4. Components, adapter, and entry
This example uses three files: App.tsx, components/root.component.tsx, and components/paragraph.component.tsx (place them under src/ or your preferred layout). In the view: only the slot render factory (the second argument passed to adapter.slotRender) must wrap kernel children with createVNode; DOM outside slots can use Viewfly JSX (see TodoRowView in Component basics).
You can edit the sample below and switch to Preview to try it; for a project identical to the steps above, still copy the code into your own repo and install/configure TypeScript and Vite as described.
5. Run and verify
# Open the dev URL printed in the terminal; confirm typing works and Enter inserts a new line
npm run devOpen the local URL in a browser and click the editing area—you should be able to type; Enter inserts a new paragraph (handled by onBreak in ParagraphComponent; see Component events & lifecycle for hooks overview).
FAQ
reflect-metadatamust load first in the entry: otherwise decorator metadata may be incomplete and dependency injection can fail at runtime. Keepimport 'reflect-metadata'as the first statement inApp.tsx(before other@textbus/*imports).- JSX and
jsxImportSource:tsconfig.jsonandvite.config.tsshould both pointjsxImportSourceat@viewfly/core, or view components will not compile correctly. - Destroying the instance: if you need to tear down the editor when the page unmounts, call
destroy()on theTextbusinstance (this sample does not show routing; wire this up when integrating into an SPA).
What's next
- Grow from this project: read the Basics section in order from Component basics through Document parsing & compatibility
- Terminology: Concepts
- Plugins and kernel extension: Modules & extensions
- Collaboration: Collaboration
