Authoring Model
One authority
Section titled “One authority”Every visual component is authored in a file ending in the project’s resolved UI suffix (canonical default .ui.tsx). The source file is canonical. Studio never saves a derived JSON document over developer-owned TSX.
export interface ProfileUIProps { name: string; avatarUrl: string; isActive: boolean; onOpen: () => void;}
export function ProfileUI(props: ProfileUIProps) { return ( <article> <img src={props.avatarUrl} alt="" /> <h2>{props.name}</h2> {props.isActive && <span>Online</span>} <button onClick={props.onOpen}>Open</button> </article> );}UI responsibility
Section titled “UI responsibility”A file ending in the resolved UI suffix may describe:
- explicit JSX structure and intrinsic elements;
- typed local props contracts;
- literal values and supported prop expressions;
- callback event props;
- named
ReactNodecomposition slots; - conditions, nullish fallback, and supported ternaries.
It does not own hooks, effects, stores, requests, mutations, routing, or business logic.
That includes identifier Hooks such as useProfile(), property Hooks such as
React.useState(), and browser/runtime APIs such as fetch,
XMLHttpRequest, WebSocket, localStorage, and sessionStorage. Put that
behavior in the matching Connector/runtime chain and pass only values and event
callbacks into UI through typed props.
Every UI also blocks external runtime behavior such as state, router, request,
query-lifecycle, and callable utility modules. Its external imports are limited
to type-only contracts, styles/assets, safe React JSX support, and
presentational bindings used exclusively as JSX tags.
Presentational assets are CSS-family files; images/icons; web fonts; audio; and
video (svg/png/jpeg/gif/webp/avif/ico, woff/woff2/ttf/otf/eot,
mp3/wav/ogg, and mp4/webm). Arbitrary data or executable module extensions
are not treated as assets.
This remains true for src/shared/ui. A Shared UI Primitive is not a smaller
Feature: it has no Connector or runtime chain. It receives all data, event
callbacks, and ReactNode composition through typed props, so another pure UI
can reuse it without inheriting hidden state or network behavior.
Connector responsibility
Section titled “Connector responsibility”Connectors adapt application behavior to pure UI:
export function HomeConnector() { const launch = useLaunchProject(); return <HomeUI navigation={<NavigationSlot />} onLaunch={launch} />;}This boundary keeps visual contracts reusable and allows the compiler to derive a safe read model without executing arbitrary application modules.
Reusable visual behavior belongs in a Shared Widget instead of a Shared UI Primitive. A widget has required UI + Connector and the same optional Hook → Store → Logic → API chain used by Feature owners. Consumers compose its Connector, never its private UI or runtime implementation.
Only an owner’s matching Connector imports and renders that owner UI. A parent
or sibling imports the child Connector, never the child .ui.tsx. The only
cross-owner exception is a pure UI composing the public UI boundary of a
canonical Shared UI Primitive. Direct child UI imports fail with SRIJIKA4116
and SRIJIKA-ARCH-DIRECT-CHILD-UI.
Passive Types
Section titled “Passive Types”The file ending in the resolved Types suffix (canonical default .types.ts) is a passive contract rather than a runtime layer. Keep only
interfaces, type aliases, import type, export type, and an optional empty
export {}. Do not declare/export runtime constants or functions, and do not
refer to runtime values with typeof or computed value expressions. Consumers
must use import type/export type; violations fail with SRIJIKA4117 and
SRIJIKA-ARCH-PASSIVE-TYPES.
Logic responsibility
Section titled “Logic responsibility”*.logic.ts is framework-free and deterministic. Keep business rules, pure
validation/authorization, deterministic transforms, aggregation, and
orchestration through the matching API here. Passive Types and pure utility
libraries are valid.
React/Hook lifecycle, React Query/query-cache lifecycle, router lifecycle,
client-state lifecycle, browser globals, and request transport are not Logic.
Move them to Hook, Connector, Store, or API. Direct/aliased transport calls and
request modules such as node:http, node:https, undici, cross-fetch,
node-fetch, and ofetch fail too. These violations fail with SRIJIKA4118 and
SRIJIKA-ARCH-LOGIC-RUNTIME-CONCERN without removing pure validation or
transformation from Logic.
Provable project imports
Section titled “Provable project imports”Governed Feature and Shared sources must have a complete, statically provable
module graph. Computed import() or require() targets fail with
SRIJIKA4119. Declared or reserved project aliases that do not resolve through
root JSONC tsconfig.json to a scanned governed source fail with
SRIJIKA4120; a Vite-only alias is not portable. Missing or outside-root
relative/src/... source imports fail with SRIJIKA4121. CSS and static-asset
imports remain valid, and external packages use bare specifiers.
Safe edits
Section titled “Safe edits”Supported quick fixes and visual controls produce bounded AST edits. A save includes the last-read content hash. If VS Code changed the source in the meantime, Studio rejects the stale write rather than discarding newer work.