Skip to content

Repository files navigation

ubean logo

ubean

A Vue-first full-stack meta-framework built on Vite-Plus

中文文档


zread

Current status: v0.4.10 (preview). ubean is a usable, actively developed meta-framework. It is not yet marked production-stable: public APIs can still change between releases, and several subsystems (database layer, queue workers, cron scheduler) have not been load-tested against real-world traffic. See Status for the current state, suitable scenarios, and known limitations.


What is ubean?

ubean unites Vue SSR pages, Hono API routes, type-safe route metadata, and portable deployment presets into a single consistent development experience. It is built on Vite-Plus, borrowing the Inertia-style SSR page routing from void and the cross-platform deployment matrix from nitro. Vue 3 is the only frontend adapter — every routing, validation, and config decision is type-checked at build time. A single npm package ubean aggregates all @ubean/* subpackages behind dedicated subpath entries — an isomorphic main entry for client/shared code plus ubean/server / ubean/build / ubean/i18n / ubean/ssr / ubean/client / ubean/vite / ubean/scaffold for each consumption context.

Why another meta-framework?

Nuxt, Next.js, and SvelteKit already exist — what does ubean bring that is genuinely different? Three architectural commitments define its identity:

1. Vue-specific depth, not multi-framework breadth. ubean targets Vue 3 only. No React adapter, no Svelte renderer, no generic abstractions that sacrifice Vue-specific optimizations. This single-framework constraint enables deep integration — the definePage macro is compiled away at build time, Vue Router navigation guards work identically on client and SSR, and the SSR renderer (createVueRenderer from ubean/ssr) is purpose-built for Vue's @vue/server-renderer. The result is a smaller, faster runtime with zero abstraction overhead.

2. Hono as the HTTP core, not h3. Where Nuxt uses h3 (its own HTTP abstraction) and nitro uses h3 as the server handler, ubean chooses Hono — a lighter, more modern, type-friendly HTTP framework. Every API route is a Hono handler chain; every middleware composes through Hono's native middleware system; request validation plugs directly into hono-openapi to generate OpenAPI 3.1 without an intermediary layer. Hono's multi-runtime design (Node.js, Cloudflare Workers, Bun, Deno) also aligns naturally with ubean's preset system.

3. Explicit capability contracts, not silent degradation. Every deployment preset (node-server, cloudflare, etc.) declares its capability matrix. If a target platform does not support a feature, the build produces a diagnostic error — never a silent degradation. This philosophy runs through the whole framework: internalFetch dispatches framework handlers in-process without a network request (and explicitly does not support upload progress); the core only depends on the Standard Schema spec (not Zod); @ubean/icon requires users to install a separate @iconify-json/<collection> package instead of bundling the full @iconify/json dataset.

App Modes

ubean supports four application modes controlled by the mode field in ubean.config.ts. The default is fullstack, which produces client + SSR + server bundles. The other three modes skip unnecessary build steps to reduce output size and build time:

Mode Client SSR Server Prerender Typical Use Case
fullstack (default, ssr: true) Yes Yes Yes Optional Full-stack app with SEO needs
fullstack + ssr: false Yes No Yes No Full-stack app without SEO (admin panel)
spa Yes No No No Pure client-rendered, no server
ssg Yes Yes (static bundle) No Yes (forced) Static site / blog / docs (direct render)
backend No No Yes No Pure API service, no Vue pages

The ssr option only applies within fullstack mode — spa and backend always skip SSR, while ssg always requires it (for build-time rendering). Mode is orthogonal to preset (deployment platform) and routing mode (virtual / file generation), so you can freely combine mode: 'fullstack' with preset: 'cloudflare' and routing.mode: 'file'.

Features at a Glance

Layer Capability Key API Package
Routing File-based API routes (named HTTP method exports) defineHandler @ubean/routes
Routing File-based Vue SSR pages definePage macro @ubean/vue + @ubean/scan
Routing Route metadata (auth / cache / rateLimit) defineHandlerMeta @ubean/routes
Routing OpenAPI 3.1 validation + Scalar UI validator / describeRoute hono-openapi (re-exported)
Routing Type-safe route paths (generated) .ubean/routes.d.ts @ubean/build/codegen
Routing Dynamic route matchers ([param=matcher]) defineMatcher / createMatcherGuard @ubean/vue
App Vue app customization (plugins, guards, head) defineApp @ubean/client
App Hono app factory createUbeanApp @ubean/app
Server Database layer (multi-driver) defineDatabase / useDatabase @ubean/server
Server Storage (unstorage wrapper) useStorage / useKV @ubean/server
Server Cache (memory + external) useCacheStore / cachedEventHandler @ubean/server
Server Queue processing defineQueue @ubean/server
Server Scheduled tasks (cron) defineScheduled @ubean/server
Server WebSocket (crossws) defineWebSocket @ubean/server
Server SSE streaming SSE utilities @ubean/server
Server Rate limiting + CORS Middleware factories @ubean/server
Server Route rules (redirect / rewrite / headers / cache) routeRules config @ubean/server
Server In-process handler dispatch internalFetch @ubean/pages
Config Typed config definition defineConfig @ubean/config
Config Typed environment variables defineEnv @ubean/shared
Config Middleware definition defineMiddleware @ubean/routes
i18n vue-i18n 11 + compact locale routing useI18n / setLocale / t @ubean/i18n + @ubean/client
SSR Vue server-side renderer createVueRenderer @ubean/client/ssr
Islands Partial hydration boundaries ubeanIslandsPlugin @ubean/islands
DevTools RPC, AI assistant, API playground, CRUD scaffolding devtools: true config @ubean/devtools
Extension Better Auth integration + fallback auth: true config @ubean/auth
Extension Iconify + custom SVG collections icon: true config @ubean/icon
Extension PWA manifest + service worker pwa: true config @ubean/integrations/pwa
Extension Image optimization image: true config @ubean/image
Extension Content collections + Markdown content: true config @ubean/content
Extension Font optimization + self-hosting fonts: true config @ubean/integrations/fonts
Extension Electron desktop apps electron: true config @ubean/integrations/electron
Extension @vean/ui integration ui: true config @ubean/integrations/ui
Extension Pinia integration + SSR hydration pinia: true config @ubean/integrations/pinia

Package Entry Points

The ubean main package provides several subpath exports in addition to the default . entry. This design prevents browsers from pulling server-side dependencies through Vite's pre-bundling:

Subpath Purpose Typical Usage
ubean Isomorphic main entry (client-safe): shared/seo/pages/markdown + Vue client kernel + islands runtime + logger + defineConfig Config files, client & shared code
ubean/server Server aggregate (createUbeanApp/defineServer/defineHandler/useDatabase/validator…) src/server.ts, API routes
ubean/build Build-time tooling (prerender, static-render for SSG direct rendering, loadUbeanConfig, codegen presets, detectPreset, vite plugin implementations) Build scripts, CI, vite.config.ts
ubean/client Framework client runtime: kernel + createServerHead + Server Actions runtime + islands registry bridge Client code, SPA entry
ubean/i18n Server-side i18n (ALS t(), createI18nMiddleware) Handlers, build-time locale handling
ubean/ssr Vue SSR renderer (createVueRenderer) Custom SSR setup
ubean/vite Composite Vite plugin (build + vue + islands + server-actions) vite.config.ts
ubean/scaffold Scaffold library + machine-readable catalog studio / IDE tooling

Critical rule for newcomers: the ubean main entry is client-safe by design — client and shared code may import from it (or from ubean/client) freely. Server code must use ubean/server, which pulls in Hono and Node built-ins and must never be imported in browser code. Build-time tooling lives in ubean/build.

Client kernel layering: @ubean/vue is the lean client kernel (vue + vue-router only) that owns page routing (file-based scan, virtual modules, page cache, transitions, matchers); @ubean/client is the framework client runtime layered on top (app factories, unhead/SEO, i18n, data layer, islands hydration); the ubean/client subpath re-exports it. Standalone SPAs can depend on @ubean/vue directly without pulling in the framework build tooling.

Project Structure

Repository Layout

ubean is a 24-package monorepo managed by pnpm workspaces (packages/*, apps/*, examples/*). The public package ubean (packages/ubean/) is the aggregator that re-exports all @ubean/* subpackages. Each subpackage is independently built, type-checked, and consumable individually in advanced scenarios. See docs/README.md for the engineering documentation index.

packages/
├── ubean/          # Main package (npm: "ubean") — aggregator, re-exports all @ubean/*
│
│   ── Foundation / shared layer ──
├── shared/         # @ubean/shared — shared types, errors, env, utils, logger
├── vue/            # @ubean/vue — lean Vue client kernel & page-routing owner (vue + vue-router only)
├── markdown/       # @ubean/markdown — Markdown/MDX page parsing
├── seo/            # @ubean/seo — SEO meta management
├── pages/          # @ubean/pages — page data protocol (loader/action)
├── i18n/           # @ubean/i18n — @intlify/core + compact locale routing
│
│   ── Server runtime ──
├── routes/         # @ubean/routes — server routes + Server Actions (defineHandler, defineAction, ./runtime)
├── server/         # @ubean/server — server runtime (cache/db/queue/cron/ws/sse)
├── app/            # @ubean/app — Hono app factory (createUbeanApp)
│
│   ── Build-time tools ──
├── builder/        # @ubean/build — Vite plugins (./vite + ./vue + ./actions) + production + ./prerender + ./codegen
├── config/         # @ubean/config — config loader + module system
├── preset/         # @ubean/preset — platform presets (node/cloudflare + capabilities)
│
│   ── Route scanning ──
├── scan/           # @ubean/scan — project scanner + route metadata aggregator (delegates pages to @ubean/vue)
│
│   ── Client runtime ──
├── client/         # @ubean/client — framework client runtime (layered over @ubean/vue; ./ssr renderer)
│
│   ── Services / tools ──
├── islands/        # @ubean/islands — Islands partial hydration
├── cli/            # @ubean/cli — CLI commands + dev server
├── devtools/       # @ubean/devtools — devtools (RPC, AI, CRUD scaffolding)
│
│   ── Extensions ──
├── ai/             # @ubean/ai — AI integration (Vercel AI SDK orchestration)
├── auth/           # @ubean/auth — Better Auth integration + fallback
├── icon/           # @ubean/icon — Iconify integration + custom collections
├── image/          # @ubean/image — image optimization
├── content/        # @ubean/content — content collections
└── integrations/   # @ubean/integrations — pwa / fonts / electron / ui / pinia subpaths

apps/docs/          # Documentation site (source under src/content/{en,zh}/)
examples/           # ubean-test / client-only-spa / frontend-only / routing-file-mode / platform-drivers / ssg-catchall
docs/               # Repo-level engineering docs (ADR, glossary, product plan)

User App Layout

When you scaffold a ubean app, srcDir (default <rootDir>/src) follows a conventional directory structure. Every directory has a framework-recognized purpose — pages/ for Vue routes, routes/ for API endpoints, layouts/ for page wrappers, etc. This convention-based approach means a standard project needs zero configuration, while ubean.config.ts provides an escape hatch for customization:

my-app/
├── src/                        # Configurable srcDir (default: <rootDir>/src)
│   ├── pages/                  # File-based page routes (*.vue / *.md)
│   │   ├── (group)/            # Route groups — do not contribute to URL
│   │   ├── dashboard/
│   │   │   ├── index.vue
│   │   │   ├── profile.vue
│   │   │   └── settings.vue
│   │   ├── user/[id].vue       # Dynamic route params
│   │   ├── about.vue
│   │   └── index.vue
│   ├── routes/                 # API routes (void-style named exports)
│   │   ├── api/
│   │   │   ├── users/
│   │   │   │   ├── [id].ts     # export const GET / PATCH / DELETE
│   │   │   │   └── index.ts    # export const GET / POST
│   │   │   └── hello.ts
│   │   ├── sitemap.xml.ts
│   │   └── robots.txt.ts
│   ├── layouts/                # Page layouts (default.vue or default/index.vue)
│   ├── middleware/             # Route middleware (global.* / <prefix>/*.ts)
│   ├── crons/                  # Scheduled tasks (defineScheduled)
│   ├── locales/                # i18n messages (en.json, zh-CN.json)
│   ├── components/             # Business components
│   ├── composables/            # Auto-imported composables
│   └── app.ts                  # Optional: defineApp(options)
├── public/                     # Static assets
├── ubean.config.ts             # defineConfig({...})
├── env.d.ts
├── package.json
└── tsconfig.json

Quick Start

Note: ubean is currently a v0.4.10 preview. It can be used for real projects, but expect occasional breaking changes between releases. See Status for details.

Scaffold a New Project

# Using pnpm (recommended)
pnpm dlx ubean init my-app

# Or with npm / yarn / bun
npx ubean init my-app

The init wizard will prompt you for template (unify [default, full-stack with islands/i18n/layouts/middleware] / minimal / starter / blog), preset (standard / node / cloudflare), and package manager.

Manual Setup

mkdir my-app && cd my-app
pnpm init
pnpm add ubean vue

Create ubean.config.ts:

import { defineConfig } from 'ubean';

export default defineConfig({
  srcDir: 'src',
  preset: 'standard'
});

Add scripts to package.json:

{
  "scripts": {
    "dev": "ubean dev",
    "build": "ubean build",
    "preview": "ubean preview",
    "prepare": "ubean prepare",
    "typecheck": "vue-tsc --noEmit"
  }
}

Development Commands

Command Description
pnpm dev Start the dev server with HMR
pnpm build Build for production (client + server + optional SSR)
pnpm preview Preview the production build locally
pnpm prepare Generate type definitions to .ubean/ (auto-installs missing built-in modules)
pnpm typecheck Type-check the project with vue-tsc

Enabling Built-in Modules

Built-in modules (icon, pwa, auth, image, fonts, electron, ui, pinia) are opt-in via ubean.config.ts. When you enable one, the corresponding @ubean/* package is required:

import { defineConfig } from 'ubean';

export default defineConfig({
  ui: true, // @ubean/integrations/ui — auto-injects @vean/ui styles.css + UiResolver
  icon: true, // @ubean/icon — Iconify integration
  pwa: true, // @ubean/integrations/pwa — manifest + service worker
  auth: true, // @ubean/auth — Better Auth integration
  electron: true // @ubean/integrations/electron — desktop app (auto-disables SSR)
});

Running ubean prepare will auto-detect and install any missing built-in module packages using your project's package manager (pnpm / yarn / bun / npm). Use ubean prepare --no-install to skip auto-install (e.g. in CI). If a module is enabled but not installed when running ubean dev or ubean build, a clear warning is logged so you know the module was silently skipped rather than puzzling over why ui: true has no effect.

Architecture Direction

ubean's core implementation follows six boundaries:

  1. Pure function core. Configuration merging, file scanning, route parsing, code generation, and type inference are all pure functions. No I/O, no Hono instances, no Vite plugins — those live behind explicit adapter boundaries. This makes the build pipeline testable without mocking the entire dev server.

  2. Explicit side-effect boundaries. Everything that touches the file system, network, Hono, Vite, or Hookable is isolated in dedicated layers. The core layer cannot call fs.readFile or app.use() directly — it produces data structures consumed by the plugin/runtime layer.

  3. No bundled browser HTTP client. ubean does not ship a fetch wrapper in the browser bundle. For browser HTTP requests, use @soybeanjs/fetch (createRequest / toFlatRequest / createTypedClient). For typed clients, consume the generated .ubean/routes.d.ts paths types.

  4. In-process dispatch over network round-trips. internalFetch invokes framework handlers directly within the same process — no HTTP request is created. This is faster and avoids auth context leakage, but it explicitly does not support upload progress tracking.

  5. Declare capabilities, do not silently degrade. Every preset publishes a capability matrix. Unsupported features produce build-time diagnostics, never runtime surprises. A Cloudflare Workers preset that cannot run a WebSocket handler tells you at build time, rather than silently dropping the feature.

  6. Strict TypeScript, functional style. ubean follows TypeScript functional programming conventions — no class hierarchies for framework APIs, composition over inheritance, and every public define* function returns a typed object consumed structurally by the build pipeline.

Status

ubean is at v0.4.10, an active preview. The originally targeted release line (v0.1) has long since been superseded — the current milestone reflects a much more complete framework.

Current State

The v0.4 series supports Node.js (node-server) and Cloudflare Workers as first-class presets. Bun, Deno, Vercel, and Netlify are outside the current support commitment but arrive progressively through the preset capability matrix. The core feature set is implemented and passes type-checks and basic tests:

  • Routing: routes/ API file routing with named GET / POST / PUT / PATCH / DELETE / OPTIONS / HEAD exports wrapped by defineHandler; pages/ Vue SSR pages, layouts, route groups, reuse routes, parallel/intercepting routes, dynamic param matchers, special pages, and typed navigation; defineHandlerMeta for route metadata (requiresAuth, cache, rateLimit); validator / describeRoute / resolver from hono-openapi for request validation and OpenAPI 3.1 generation; generated paths types at .ubean/routes.d.ts.
  • App: defineApp options-based customization (including router.setup for global navigation guards on both client and SSR), definePage macro, defineMiddleware, defineEnv, defineScheduled (cron), defineQueue. i18n is ubean.config.ts i18n + vue-i18n 11 (setLocale from ubean / ubean/client; useI18n directly from vue-i18n; server-side ALS t() from ubean/i18n).
  • Server: Built-in database layer (defineDatabase / useDatabase), storage (useStorage / useKV), cache (useCacheStore / cachedEventHandler), rate limiting, CORS, route rules (redirect / rewrite / headers / cache), and SSG prerendering — with a lightweight direct render path for mode: 'ssg' (no HTTP pipeline, 404.html output, i18n route expansion). WebSocket (defineWebSocket), SSE streaming, and internalFetch (dispatches framework handlers in-process without a network request).
  • DevTools: RPC, AI assistant, API playground, and CRUD scaffolding.
  • Extension packages: @ubean/auth (Better Auth with fallback), @ubean/icon (Iconify integration), @ubean/image, @ubean/content, and @ubean/integrations (PWA / fonts / Electron desktop apps via vite-plugin-electron with default main/preload entries and auto SSR disable / @vean/ui with UiResolver and styles.css auto-injection / Pinia SSR hydration).

Suitable Scenarios

Use ubean today for:

  • Full-stack apps on Node.js or Cloudflare Workers where Vue SSR + Hono API routes in one framework fits your needs.
  • Admin panels and internal tools (fullstack + ssr: false), SPAs, static sites / blogs / docs (ssg), and pure API services (backend).
  • Evaluation and prototyping — it is worth trying before committing a large codebase.

Known Limitations

  • Public API stability: pre-v1, backport-hard breaking changes can land between releases. Pin an exact version and audit upgrades.
  • Load hardening: several subsystems — especially the database layer, queue workers (defineQueue), and cron scheduler (defineScheduled) — have not been load-tested or hardened against production traffic. They pass type-checks and basic tests but should not be trusted for high-throughput critical workloads without your own stress testing.
  • Platform breadth: currently Node.js and Cloudflare Workers are first-class presets; other platforms arrive incrementally through the capability matrix.

Development

Requirements: Node.js >= 22 and pnpm 11.24.0.

pnpm install
pnpm typecheck
pnpm lint
Command Description
pnpm typecheck Type-check the project with vue-tsc
pnpm lint Run Vite-Plus/OXC and Vue ESLint checks (auto-fix: pnpm lint:fix)
pnpm test Run the test suite (vitest)
pnpm dev Watch-build the ubean aggregator package (example dev server: pnpm --filter ubean-test dev)
pnpm build Build all subpackages
pnpm upkg Check dependency updates
pnpm commit Create a commit with the project commit-message tool

Planning and Contributions

  • The documentation index contains the architecture reference, historical design records, and pending proposals.
  • Usage guides and API references live in skills/ubean/SKILL.md and the docs site under apps/docs/src/content.
  • AGENTS.md is the canonical quick reference for AI assistants and contributors — package list, core APIs, conventions, and common pitfalls.
  • Each feature should include unit tests, a real fixture, and the applicable dev, build, preview, or browser end-to-end verification.
  • Changes to public APIs, preset capabilities, or generated types must update the plan, tests, and documentation together.

License

MIT License

Releases

Packages

Contributors

Languages