# xuda-cli

`xuda-cli` is the local development CLI for Xuda app projects.

It lets you:

- create and run a Xuda app locally
- author the app in friendly source files such as `App.xu`, `components/*.xu`, and `tables/*.json5`
- compile those source files into runtime JSON docs
- keep the runtime docs in one canonical location: `node_modules/.project_data/`
- optionally sync cloud project docs down into source files and push local changes back up

## Quick Start

Create a new app:

```bash
npm create xuda-cli@latest my-app
cd my-app
npm install
npm run dev
```

Typical `package.json` scripts:

```json
{
  "scripts": {
    "dev": "xuda-cli dev",
    "sync": "xuda-cli sync"
  }
}
```

Install common plugins with normal npm install:

```bash
npm install @xuda.io/xuda-framework-plugin-tailwind
npm install @xuda.io/xuda-dbs-plugin-xuda
```

There is no plugin subcommand in `xuda-cli`.

## Commands

```bash
xuda-cli dev
xuda-cli sync
xuda-cli --help
```

`xuda-cli dev`

- loads your project from the current directory
- compiles source files into `node_modules/.project_data/`
- serves the app locally
- watches `.xu` and supported `.json5` files and regenerates runtime docs on save

`xuda-cli sync`

- requires `api_key` in `xuda.config.js`
- downloads cloud docs into `node_modules/.project_data/`
- creates missing local `.xu` and `.json5` source files from those docs
- recompiles local source back into `node_modules/.project_data/`
- uploads changed docs back to the cloud

## Mental Model

The app has three important layers:

1. `index.html`
   This is the document shell. It owns the `<head>`, metadata, fonts, and the HTML node where your root app mounts.

2. `App.xu`
   This is the root Xuda screen. It is compiled as the program id `app`.

3. `node_modules/.project_data/`
   This is the generated runtime document set that the Xuda runtime reads.

If `xuda.config.js` uses:

```js
module.exports = {
  entry: 'index.html'
};
```

then `index.html` is served first, and `App.xu` is automatically mounted into `#app` unless you already mounted another component into that HTML entry.

If `entry` is omitted, `xuda-cli` defaults to `app`.

Recommended rule:

- keep `index.html` as the page shell
- keep `App.xu` as the root Xuda screen
- add feature screens under `components/`

## How `xuda-cli` Technology Works

`xuda-cli` is not just a file server. It is a source compiler, runtime packager, local app host, and optional cloud sync tool.

When you work on a Xuda app, the technology flow looks like this:

1. Authoring layer
   You write human-friendly source files such as `App.xu`, `components/*.xu`, `data/get/*.xu`, and `tables/*.table.json5`.

2. Compile layer
   `xuda-cli` parses those source files and converts them into the JSON document model that the Xuda runtime already understands.

3. Runtime docs layer
   The compiled output is written to `node_modules/.project_data/`. This is the canonical runtime doc folder used by the local app.

4. Runtime host layer
   `xuda-cli dev` serves your `index.html`, runtime assets, compiled component scripts, and the generated document set.

5. Browser/runtime execution layer
   The browser loads the Xuda runtime, mounts `App.xu` or the configured entry program, and executes fields, actions, events, datasources, and panels.

6. Optional cloud sync layer
   If `api_key` is configured, `xuda-cli sync` can pull remote docs into the local project, create missing source files, and push changed docs back to the cloud.

### Source-first philosophy

The intended developer experience is:

- source files are the place humans edit
- `node_modules/.project_data/` is generated runtime output
- the runtime reads generated docs
- sync can import older or remote docs into source files, but source remains the preferred authoring format

### What gets compiled

`xuda-cli` compiles:

- `.xu` files into component or logic-unit docs
- `.table.json5` files into table docs
- `.route.json5` files into route docs
- `.agent.json5` files into AI agent docs

### What stays runtime-facing

The local runtime still consumes the classic Xuda document shape:

- `progUi`
- `progFields`
- `progEvents`
- `progDataSource`
- `tableFields`
- `tableIndexes`
- `routeMenu`
- `agentConfig`

That means `xuda-cli` gives you a friendlier source format without requiring a brand-new runtime protocol.

### SSR and render profiles

`xuda-cli` supports:

- `ssr: 'none'`
- `ssr: 'first_page'`
- `ssr: 'full'`

In practice:

- `none`
  normal client rendering
- `first_page`
  first-page SSR with client takeover
- `full`
  fuller SSR with hydration-friendly behavior

### Plugin model

Plugins are standard npm dependencies, not copied folders and not special CLI subcommands.

Use plugins for:

- UI frameworks such as `@xuda.io/xuda-framework-plugin-tailwind`
- database behavior such as `@xuda.io/xuda-dbs-plugin-xuda`

### Why the project keeps both `index.html` and `App.xu`

They solve different problems:

- `index.html`
  document shell, metadata, fonts, mount element
- `App.xu`
  root Xuda UI, fields, actions, panels, and app behavior

This separation keeps the app structure predictable and makes it easier to scale into multiple routed or panel-based screens.

## Project Layout

This is the official source layout:

```text
my-app/
  package.json
  xuda.config.js
  index.html
  App.xu

  components/
    **/*.xu

  globals/
    **/*.xu

  data/
    get/**/*.xu
    set/**/*.xu
    batch/**/*.xu

  apis/
    **/*.xu

  scripts/
    **/*.xu

  alerts/
    **/*.xu

  tables/
    **/*.table.json5

  routes/
    **/*.route.json5

  ai-agents/
    **/*.agent.json5

  node_modules/
    .project_data/
```

Rules:

- `App.xu` is the reserved root app file
- `components/` is for UI components
- `globals/` is for shared state units
- `data/get/`, `data/set/`, and `data/batch/` are for logic units
- `tables/`, `routes/`, and `ai-agents/` are structured JSON5 resources
- `node_modules/.project_data/` is generated runtime output, not your source of truth

## What Lives in `index.html`

Use `index.html` for:

- the page title
- meta tags
- favicons
- fonts
- external scripts if you need them
- the root mount element

Minimal example:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Xuda App</title>
  </head>
  <body>
    <main id="app"></main>
  </body>
</html>
```

## `xuda.config.js`

`xuda.config.js` controls entry, server, and sync-related settings.

Example:

```js
module.exports = {
  entry: 'index.html',
  port: 3000,
  ssr: 'none',
  api_key: '',
  build_id: ''
};
```

Supported fields:

- `entry`
  The app entry. Usually `index.html`. Defaults to `app`.
- `port`
  Local dev port. Defaults to `3000`.
- `ssr`
  One of `none`, `first_page`, or `full`.
- `api_key`
  Optional. Required for `npm run sync`.
- `build_id`
  Optional remote build target. If provided, it requires `api_key`.

## `package.json`

`package.json` is the source of app package metadata:

- `name`
- `version`
- `description`

Minimal example:

```json
{
  "name": "my-app",
  "version": "0.1.0",
  "description": "Starter Xuda app",
  "scripts": {
    "dev": "xuda-cli dev",
    "sync": "xuda-cli sync"
  },
  "dependencies": {
    "@xuda.io/xuda-framework-plugin-tailwind": "latest",
    "@xuda.io/xuda-dbs-plugin-xuda": "latest"
  },
  "devDependencies": {
    "xuda-cli": "latest"
  }
}
```

## Source File Types

`xuda-cli` supports these authored source types:

| Location | File type | Xuda unit |
| --- | --- | --- |
| `App.xu` | `.xu` | root `component` |
| `components/**/*.xu` | `.xu` | `component` |
| `globals/**/*.xu` | `.xu` | `globals` |
| `data/get/**/*.xu` | `.xu` | `get_data` |
| `data/set/**/*.xu` | `.xu` | `set_data` |
| `data/batch/**/*.xu` | `.xu` | `batch` |
| `apis/**/*.xu` | `.xu` | `api` |
| `scripts/**/*.xu` | `.xu` | `javascript` |
| `alerts/**/*.xu` | `.xu` | `alert` |
| `tables/**/*.table.json5` | `.json5` | `table` |
| `routes/**/*.route.json5` | `.json5` | `route` |
| `ai-agents/**/*.agent.json5` | `.json5` | `ai_agent` |

## Xuda Building Blocks At A Glance

Each block exists for a different responsibility. A good Xuda app is usually clearer when each concern has its own unit instead of pushing everything into one giant component.

| Building block | Main responsibility | Best used for |
| --- | --- | --- |
| `component` | UI and interaction | screens, panels, forms, dashboards, reusable views |
| `globals` | shared app state | signed-in user, campus, feature flags, shared filters |
| `get_data` | reading data | list loads, record queries, reusable data fetches |
| `set_data` | writing data | create, update, delete, persistence workflows |
| `batch` | record-by-record processing | rebuild jobs, migration flows, recalculation |
| `api` | response-oriented logic | API outputs, summaries, machine-readable endpoints |
| `javascript` | custom JS logic | formatting, transformations, reusable computation |
| `alert` | user messaging | toasts, success notices, warnings, error feedback |
| `table` | data model definition | fields, indexes, database-facing schema metadata |
| `route` | navigation model | menus, destinations, route planning |
| `ai_agent` | assistant configuration | app-specific AI helpers and future agent workflows |

### How to choose the right block

Use `component` when:

- the user sees it
- it owns UI state or user interactions
- it renders template markup

Use `globals` when:

- more than one screen needs the same state
- the value is app-wide rather than screen-local

Use `get_data` when:

- the main job is to read from a datasource
- you want loading logic to stay outside UI components

Use `set_data` when:

- the main job is to persist a change
- you want writes to have a named, reusable unit

Use `batch` when:

- you are processing many rows or records
- the workflow is iterative and not just a simple read/write

Use `api` when:

- the result should be shaped as a clean response
- the unit feels more like an endpoint than a screen

Use `javascript` when:

- you need custom code but do not want it scattered through actions
- the logic is reusable and named

Use `alert` when:

- the app needs consistent messaging
- a message should be reusable across multiple screens or workflows

Use `table` when:

- a datasource refers to real table-backed storage
- you need fields and indexes with a stable id

Use `route` when:

- the app has named destinations or menu structure
- you want a navigation model that is visible in source

Use `ai_agent` when:

- the app needs a configured assistant resource
- you want that assistant defined as a first-class app asset

## `.xu` Blocks

`xuda-cli` reads `.xu` files as block-based source files.

Supported component blocks:

- `<meta lang="json5">`
- `<params lang="json5">`
- `<fields lang="json5">`
- `<actions lang="json5">`
- `<events lang="json5">`
- `<datasource lang="json5">`
- `<template>`
- `<script>`
- `<style>`
- `<mount>`

Supported non-UI logic blocks:

- `globals`
  `<meta>`, `<fields>`, `<events>`, optional `<datasource>`
- `get_data`, `set_data`, `batch`
  `<meta>`, `<params>`, `<fields>`, `<events>`, `<datasource>`
- `api`
  `<meta>`, `<params>`, `<fields>`, `<events>`, `<datasource>`, `<response>`
- `javascript`
  `<meta>`, `<params>`, `<code>`
- `alert`
  `<meta>`, `<params>`, `<alert>`

Block rule:

- the object blocks are JSON5-style object literals
- unquoted keys are fine
- arrays and nested objects are fine
- `App.xu` does not need a `<mount>` block
- ordinary components only need `<mount>` when you want them mounted directly into an HTML file

## Template Language

Inside `<template>`, `xuda-cli` gives you a friendly source format and compiles it into Xuda runtime markup.

### Friendly tag aliases

- `<single-view>` becomes `xu-single-view`
- `<multi-view>` becomes `xu-multi-view`
- `<panel>` becomes `xu-panel`

### Friendly attributes

- `bind="field_v"` becomes `xu-bind`
- `if="@some_flag_v"` becomes `xu-exp:xu-render`
- `for="@items_v"` becomes `xu-exp:xu-for`
- `for-key="name"` becomes `xu-for-key`
- `for-val="name"` becomes `xu-for-val`
- `:content="@title_v"` becomes `xu-exp:xu-content`
- `:rows_in="@rows_v"` becomes `xu-exp:rows_in`
- `@click="saveItem"` becomes `xu-on:click`
- `@click.stop="saveItem"` becomes `xu-on:click` with `stopPropagation`
- `@submit.prevent="saveItem"` becomes `xu-on:submit` with `preventDefault`

Recommended rule:

- write explicit `<single-view>` or `<multi-view>` wrappers even though the compiler can add a root wrapper for you

Example:

```xml
<template>
  <single-view>
    <section class="screen">
      <input bind="search_v" placeholder="Search students">
      <button @click="togglePanel">Toggle panel</button>

      <div if="@show_panel_v">
        <panel program="student_details" />
      </div>
    </section>
  </single-view>
</template>
```

## Component Example

`component` is the main UI building block in Xuda.

Use it for:

- full screens
- dashboards
- forms
- reusable panels
- feature views such as students, tasks, profiles, or settings

A component usually owns:

- visible layout
- local screen state
- UI-triggered workflows
- panel composition
- optional client-side mount logic and styles

Example `components/StudentList.xu`:

```xml
<meta lang="json5">
{
  id: "student_list",
  menuTitle: "Student List",
  uiFramework: "@xuda.io/xuda-framework-plugin-tailwind"
}
</meta>

<fields lang="json5">
{
  show_panel_v: { type: "boolean", value: false },
  student_count_v: { type: "number", value: 3 }
}
</fields>

<actions lang="json5">
{
  togglePanel: [
    { action: "update", name: { value: "@show_panel_v: !@show_panel_v" } }
  ]
}
</actions>

<template>
  <single-view>
    <section class="p-6 space-y-4">
      <h1>Students</h1>
      <p :content="'Count: ' + @student_count_v"></p>
      <button class="rounded-full px-4 py-2 bg-sky-600 text-white" @click="togglePanel">
        Toggle details
      </button>

      <div if="@show_panel_v">
        <panel program="student_details" />
      </div>
    </section>
  </single-view>
</template>
```

### Optional direct HTML mount

If you want a component mounted directly into an HTML file, add a `<mount>` block:

```xml
<mount>
{
  id: "marketing_hero",
  file: "landing.html",
  selector: "#hero"
}
</mount>
```

Rules:

- `App.xu` is always the root app and does not need `<mount>`
- components used only through `<panel program="...">` do not need `<mount>`
- for non-root components, the program id resolves in this order:
  - `meta.id`
  - `mount.id`
  - file basename

## Globals Example

`globals` is the shared-state building block.

Use it for:

- signed-in operator identity
- campus or tenant context
- theme preferences
- shared filters or flags used across multiple screens

Do not use globals for:

- page-specific transient UI state that only one component needs
- presentation concerns that belong inside a component

Example `globals/SchoolGlobals.xu`:

```xml
<meta lang="json5">
{
  id: "school_globals",
  menuTitle: "School Globals"
}
</meta>

<fields lang="json5">
{
  campus_name_v: { type: "string", value: "Boston Campus" },
  dark_mode_v: { type: "boolean", value: false }
}
</fields>
```

Use globals for shared state and app-wide values.

## Datasource Format

Use the readable wrapper format inside `<datasource lang="json5">`.

### `none`

```xml
<datasource lang="json5">
{
  type: "none"
}
</datasource>
```

### Table datasource

```xml
<datasource lang="json5">
{
  type: "table",
  table: "student_profiles_table",
  filter: {
    mode: "index",
    activeIndex: "campus_idx",
    indexes: {
      campus_idx: {
        campus: {
          from: "@campus_in",
          to: "@campus_in"
        }
      }
    }
  },
  output: "students_out",
  direction: "asc",
  realtime: true,
  limit: 25
}
</datasource>
```

### Query datasource

```xml
<datasource lang="json5">
{
  type: "table",
  table: "student_tasks_table",
  filter: {
    mode: "query",
    query: {
      $and: [
        { status: "Open" },
        { campus: "Boston Campus" }
      ]
    }
  },
  output: "tasks_out"
}
</datasource>
```

### Array / JSON / CSV datasource

```xml
<datasource lang="json5">
{
  type: "json",
  source: {
    url: "https://example.com/students.json"
  },
  output: "students_out"
}
</datasource>
```

Rules:

- `type` can be `none`, `table`, `array`, `json`, or `csv`
- for table sources, use `table`, `filter`, `sort`, `direction`, `realtime`, `limit`, `skip`, and `output`
- for array/json/csv, use `source.field` or `source.url`
- if you need raw unsupported datasource keys, use:

```xml
<datasource lang="json5" mode="raw">
{
  "dataSourceType": "table",
  "dataSourceTableId": "student_profiles_table"
}
</datasource>
```

## `get_data` Example

`get_data` is the read-focused building block.

Use it when:

- the unit's main purpose is loading data
- you want one reusable place for filters, limits, sorting, and output mapping
- a component should call a named loader instead of owning query details directly

Typical outputs:

- rows into an output field
- filtered subsets of a table
- external JSON / CSV / array-based data

Example `data/get/LoadStudentClasses.xu`:

```xml
<meta lang="json5">
{
  id: "load_student_classes",
  menuTitle: "Load Student Roster"
}
</meta>

<params lang="json5">
{
  in: {
    campus_in: "string"
  },
  out: {
    students_out: "array"
  }
}
</params>

<datasource lang="json5">
{
  type: "table",
  table: "student_profiles_table",
  filter: {
    mode: "index",
    activeIndex: "campus_idx",
    indexes: {
      campus_idx: {
        campus: {
          from: "@campus_in",
          to: "@campus_in"
        }
      }
    }
  },
  output: "students_out",
  direction: "asc",
  realtime: true,
  limit: 25
}
</datasource>
```

## `set_data` Example

`set_data` is the write-focused building block.

Use it when:

- the unit's main purpose is to create, update, or delete records
- you want persistence to have a visible, testable home in source
- several screens might share the same write behavior

Typical uses:

- saving a profile
- deleting a row
- creating a new record
- updating status or workflow state

Example `data/set/SaveStudentProfile.xu`:

```xml
<meta lang="json5">
{
  id: "save_student_profile",
  menuTitle: "Save Student Profile",
  crudMode: "U",
  allowCreate: true
}
</meta>

<params lang="json5">
{
  in: {
    student_id_in: "string",
    full_name_in: "string",
    email_in: "string",
    campus_in: "string"
  }
}
</params>

<datasource lang="json5">
{
  type: "table",
  table: "student_profiles_table"
}
</datasource>
```

Use `set_data` units to represent write behavior clearly in source instead of hiding persistence inside a component.

## `batch` Example

`batch` is the iterative processing building block.

Use it when:

- one action needs to process many rows
- a workflow should run `before_record` or `after_record`
- you are rebuilding, migrating, enriching, or recalculating data

Example `data/batch/RebuildClassRoster.xu`:

```xml
<meta lang="json5">
{
  id: "rebuild_class_roster",
  menuTitle: "Rebuild Class Roster"
}
</meta>

<events lang="json5">
{
  before_record: [
    { action: "delay", name: { value: "1" } }
  ]
}
</events>

<datasource lang="json5">
{
  type: "table",
  table: "student_profiles_table",
  output: "students_out"
}
</datasource>
```

## `api` Example

`api` is the response-oriented building block.

Use it when:

- the result should be returned as a structured response
- the unit behaves more like an endpoint or service response than a screen
- you want a clean place to translate fields and datasource results into a JSON-style payload

An `api` unit often combines:

- params
- datasource
- optional events
- response serialization in `<response>`

Example `apis/StudentClassesApi.xu`:

```xml
<meta lang="json5">
{
  id: "student_classes_api",
  menuTitle: "Student Classes API"
}
</meta>

<params lang="json5">
{
  out: {
    students_out: "array"
  }
}
</params>

<datasource lang="json5">
{
  type: "table",
  table: "student_profiles_table",
  output: "students_out"
}
</datasource>

<response>
({ ok: true, count: (@students_out || []).length, rows: @students_out })
</response>
```

## `javascript` Example

`javascript` is the custom-code building block.

Use it when:

- an expression becomes too large or too reusable to leave inline
- a transformation deserves a name
- you want custom logic without hiding it in component actions

Good uses:

- string normalization
- custom scoring
- reusable formatting
- derived value computation

Example `scripts/NormalizeStudentName.xu`:

```xml
<meta lang="json5">
{
  id: "normalize_student_name",
  menuTitle: "Normalize Student Name"
}
</meta>

<params lang="json5">
{
  in: {
    raw_name_in: "string"
  },
  out: {
    normalized_name_out: "string"
  }
}
</params>

<code>
return (@raw_name_in || "")
  .trim()
  .toLowerCase()
  .replace(/\b\w/g, (letter) => letter.toUpperCase());
</code>
```

## `alert` Example

`alert` is the reusable messaging building block.

Use it when:

- a toast or feedback message should be consistent across the app
- several workflows need the same success or error message
- you want user messaging to live in its own source file instead of being embedded in UI logic

Example `alerts/StudentSaved.xu`:

```xml
<meta lang="json5">
{
  id: "student_saved",
  menuTitle: "Student Saved"
}
</meta>

<alert lang="json5">
{
  alertDisplay: "toast",
  alertType: "success",
  alertTitle: "Student saved",
  createLog: false
}
</alert>
```

## Table Example

`table` is the data model building block.

Use it when:

- your app stores structured records
- `get_data` or `set_data` units target database-backed tables
- you need indexes that match real query patterns

Tables usually define:

- field ids
- field types
- indexes
- stable resource ids used by datasource units

Example `tables/student-profiles.table.json5`:

```json5
{
  id: "student_profiles_table",
  menuTitle: "Student Profiles Table",
  fields: [
    { field_id: "student_id", type: "string" },
    { field_id: "full_name", type: "string" },
    { field_id: "email", type: "string" },
    { field_id: "campus", type: "string" }
  ],
  indexes: [
    { id: "campus_idx", name: "Campus", keys: ["campus"] }
  ]
}
```

## Route Example

`route` is the navigation-structure building block.

Use it when:

- the app has named destinations
- you want menu structure to be explicit in source
- you want navigation to be modeled as an app asset, not just ad hoc button logic

Routes do not replace components. They describe how components and destinations are presented as a navigable app.

Example `routes/app.route.json5`:

```json5
{
  id: "app_route",
  menuTitle: "App Route",
  menu: [
    { title: "Overview", prog: "app" },
    { title: "Students", prog: "student_list" },
    { title: "Profiles", prog: "profile_center" }
  ]
}
```

## AI Agent Example

`ai_agent` is the assistant-resource building block.

Use it when:

- the app needs a defined AI helper
- agent configuration should live beside the rest of the app source
- you want AI capabilities to be visible as part of the app architecture

This is especially useful when an app has:

- a help assistant
- a scheduling assistant
- a support or triage assistant
- a future copiloting feature that should be modeled early

Example `ai-agents/class-helper.agent.json5`:

```json5
{
  id: "class_helper",
  menuTitle: "Class Helper",
  config: {
    provider: "openai",
    model: "gpt-5"
  }
}
```

## Root App Example

Minimal `App.xu`:

```xml
<meta lang="json5">
{
  menuTitle: "Hello Xuda",
  uiFramework: "@xuda.io/xuda-framework-plugin-tailwind"
}
</meta>

<template>
  <single-view>
    <section class="min-h-screen grid place-items-center p-8 text-center">
      <div class="space-y-4">
        <img class="w-20 h-20 mx-auto rounded-2xl shadow-xl" src="/favicon.ico" alt="Xuda logo">
        <h1>Hello from xuda-cli</h1>
        <p>Start with App.xu, then add feature units under the typed folders.</p>
      </div>
    </section>
  </single-view>
</template>
```

## Client Script and Styles

Component `<script>` blocks are compiled into client-side mount modules.

Example:

```xml
<script>
export default function mount(ctx) {
  console.log('mounted', ctx.mount.id);
}
</script>
```

If the default export returns a function, that function is used as a disposer on unload.

Component `<style>` blocks are collected into the generated component stylesheet served by the app.

## Naming and Id Rules

Rules:

- `App.xu` always compiles to program id `app`
- for other `.xu` files, the id resolves from:
  - `meta.id`
  - `mount.id`
  - file basename
- for structured resources, the id resolves from:
  - `id`
  - `_id`
  - file basename
- duplicate ids are not allowed

## Plugins

Install plugins as npm dependencies in the app project.

Typical setup:

```bash
npm install @xuda.io/xuda-framework-plugin-tailwind
npm install @xuda.io/xuda-dbs-plugin-xuda
```

Typical usage:

- `@xuda.io/xuda-framework-plugin-tailwind`
  Use it through `uiFramework` in component metadata
- `@xuda.io/xuda-dbs-plugin-xuda`
  Use it by authoring `table`, `get_data`, and `set_data` resources

Example:

```xml
<meta lang="json5">
{
  uiFramework: "@xuda.io/xuda-framework-plugin-tailwind"
}
</meta>
```

## Generated Runtime Docs

`xuda-cli` always compiles runtime docs into:

```text
node_modules/.project_data/
```

Important rules:

- the runtime reads from `node_modules/.project_data/`
- you author source in `.xu` and `.json5` files, not in generated docs
- saving a supported source file regenerates the matching runtime JSON docs
- legacy `project_data/` or root `.project_data/` can still be imported during migration, but they are not the live runtime target

You should treat `node_modules/.project_data/` as generated output.

## Sync and Cloud Projects

If `api_key` exists in `xuda.config.js`, you can run:

```bash
npm run sync
```

`sync` does this:

1. verifies the app exposes the required CPI methods
2. verifies the current API key can use those methods
3. downloads remote docs into `node_modules/.project_data/`
4. creates missing local source files from those docs
5. recompiles local source back into `node_modules/.project_data/`
6. uploads changed docs back to the cloud

Required exposed CPI methods:

- `get_app_system_api_methods`
- `get_app_api_keys`
- `get_project_docs`
- `update_app_info_doc_to_db_couch`

Important sync rule:

- source import is non-destructive by default, so existing local source files are skipped instead of being overwritten

## Recommended Workflow

For new apps:

1. Create the app with `npm create xuda-cli@latest my-app`
2. Install dependencies with `npm install`
3. Keep `index.html` small and use it only as the page shell
4. Build the actual app in `App.xu`
5. Move feature screens into `components/`
6. Put shared state into `globals/`
7. Put reads and writes into `data/get/` and `data/set/`
8. Put tables into `tables/`
9. Install plugins with npm instead of looking for a CLI plugin command
10. Treat `node_modules/.project_data/` as generated output

## A Typical Xuda App Architecture

A practical Xuda app often looks like this:

- `App.xu`
  root shell, login state, high-level navigation, main panels
- `components/`
  feature screens and reusable panels
- `globals/`
  shared identity, workspace, or preference state
- `data/get/`
  named loaders for tables and filtered reads
- `data/set/`
  named save/delete/update units
- `data/batch/`
  background-style or iterative processing
- `apis/`
  app-facing or machine-facing responses
- `scripts/`
  custom transformations and helpers
- `alerts/`
  reusable user feedback
- `tables/`
  data shape and indexes
- `routes/`
  destination map and menu structure
- `ai-agents/`
  future-facing or current assistant definitions

If you keep each concern in the right block, the app is usually:

- easier to read
- easier to debug
- easier to reuse
- easier to sync with cloud docs later

## Example App

For a full multi-screen sample, see the published example package:

```text
xuda-studant-app-example
```

That example includes:

- login flow
- overview dashboard
- students screen
- tasks screen
- profiles screen
- route resource
- globals
- get_data
- set_data
- batch
- api
- javascript
- alert
- ai agent
- database-backed examples
- Tailwind-based styling

## Troubleshooting

### I can run the app, but I do not see `app.json`

Run `npm run dev` from the project root. `xuda-cli` writes generated runtime docs when it loads the project.

### Do I need both `index.html` and `App.xu`?

Yes, usually.

- `index.html` is the document shell
- `App.xu` is the root Xuda UI

### Can I remove `App.xu` and start from a component under `components/`?

You can build reusable screens under `components/`, but the recommended root is still `App.xu`.

### Where should I put business logic?

Use dedicated source units:

- `get_data` for reads
- `set_data` for writes
- `batch` for record iteration
- `api` for API-style outputs
- `javascript` for custom JS logic
- `alert` for messaging/feedback

## Summary

Use `xuda-cli` like this:

- `index.html` for the page shell
- `App.xu` for the root app
- typed folders for every Xuda building block
- npm-installed plugins
- `node_modules/.project_data/` as the only live runtime doc folder
- `npm run dev` for local development
- `npm run sync` when `api_key` is configured and you want cloud sync
