zudo-text

検索したい単語を入力

いつでも検索バーを開ける

@takazudo/app-scaffold

Computes the initial content files a brand-new workspace is seeded with, and writes the per-app-instance config.json v2 workspace binding.

Epic #4204 pivoted the app off local-workspace directories (D14: "the workspace model is the single source of truth post-pivot"). S24 (#4228) repurposed this package accordingly: the disk scaffolder (scaffoldApp, scaffoldWorkspace, and the on-disk presets/<name>/template/ tree it copied) is gone. What remains is computeScaffold() — a PURE, filesystem-free function that returns the content files consumed by the cloud-first genesis flow (runGenesisScaffold in @takazudo/backend-bridge) — plus writeAppConfig(), unaffected by the pivot.

Main Exports

import { presetPins, getPresetPins, isPresetName } from "@takazudo/app-scaffold";
import { computeScaffold } from "@takazudo/app-scaffold";
import {
  writeAppConfig,
  validateAppName,
  APP_NAME_PATTERN,
} from "@takazudo/app-scaffold";
import type {
  PresetName,
  PresetPin,
  StepStatus,
  StepResult,
  WriteAppConfigOptions,
} from "@takazudo/app-scaffold";

computeScaffold()

Computes the content-file map (Record<workspaceRelativePath, content>) a fresh workspace is seeded with for a given preset — pure, synchronous, and filesystem-free so a browser / iOS client can call it with no local storage.

function computeScaffold(presetName?: PresetName): Record<string, string>;
import { computeScaffold } from "@takazudo/app-scaffold";

const files = computeScaffold("standard");
// { ".zudotext.settings.json": "...", "CLAUDE.md": "...", "inbox/1.md": "..." }

Preset content tiers

PresetAdds
minimal.zudotext.settings.json (synced settings document) + CLAUDE.md
standardminimal + an inbox seed note (inbox/1.md)
fullstandard + a sample inline-AI skill (.zudotext/skills/example-skill.md) + a sample pin note (pins/notes/sample-note.md)

.zudotext.settings.json is defaultSettings reified via validateSettings() with local bootstrap identity blanked (stripLocalBootstrapIdentity()) — the same document shape every writer of the synced settings document must produce (epic #4204 D3).

.gitignore is deliberately absent from the map — it is a machine-local skeleton file each device recreates itself; there is no synced counterpart.

presetPins / getPresetPins()

Access preset pin configurations (the sidebar directory pins a preset's workspace ships with) without loading a full preset:

// Record mapping preset name → PresetPin[]
const presetPins: Record<PresetName, PresetPin[]>;

// Type-safe accessor with runtime check
function getPresetPins(name: PresetName): PresetPin[];

function isPresetName(value: string): value is PresetName;

writeAppConfig()

Writes the per-app-instance runtime config — ~/.config/zudotext/<name>/config.json, schema v2 ({"workspace":{"id":…}}, epic #4204 D2). One app instance binds to exactly one cloud workspace; the schema carries no local content-directory path.

function writeAppConfig(options: WriteAppConfigOptions): StepResult;
interface WriteAppConfigOptions {
  /** App-instance name (e.g. `ztoffice`). */
  appName: string;
  /** Cloud workspace this app instance binds to. */
  workspaceId: string;
  /** Overwrite an existing config.json instead of skipping. */
  force?: boolean;
  /** Override the home directory used to compute the config path. */
  homedir?: string;
}

The Rust mirror is write_app_config in tauri-app/core/src/generator/app_config.rs, which also owns the read side (read_app_binding) used at startup.

validateAppName()

Returns true if an app name matches APP_NAME_PATTERN (lowercase alphanumeric + hyphens).

function validateAppName(name: string): boolean;
const APP_NAME_PATTERN: RegExp;

CLI

See pnpm generate --help (backed by scripts/generate-app.ts) for the developer CLI that drives computeScaffold() + writeAppConfig() end to end.

Dependencies

  • @takazudo/app-defaults — for defaultSettings, validateSettings(), and stripLocalBootstrapIdentity()