Build with Eidos File 1.0
Eidos 1.0 has four interoperable layers:
File Format → Runtime → Adapter → UI
Most applications should compose the published Runtime and UI packages rather than reimplement every layer. Implement a layer only when you are building a conforming alternative.
The frozen English specifications are normative:
Choose your layer
| If you are building… | Start with |
|---|---|
| A Node service or headless data tool | @eidos.space/eidos-file and a Node ConnectionPort |
| A browser application | Runtime in a Dedicated Worker, a browser Adapter, and @eidos.space/eidos-file-ui |
| A visual React viewer or editor | @eidos.space/eidos-file-ui on top of a conforming Host and Runtime |
| A storage or UI implementation | The corresponding 1.0 specification and interoperability tests |
| An Agent workflow or script | The eidos CLI and Eidos Skill |
Install the reference packages
pnpm add @eidos.space/eidos-file@1.0.0 \
@eidos.space/eidos-file-ui@1.0.0 react react-dom
Import @eidos.space/eidos-file-ui/styles.css once.
Building for an Agent or automation rather than embedding the packages? Follow the CLI and Skill setup instead.
Runtime and Adapter
The following code is a composition outline, not a standalone quickstart. Your Adapter or host supplies connection, environment, and cancellation.
Give Runtime.open or Runtime.create an EA-Connection-1.0
ConnectionPort. The reference Browser binding is
SQLiteWasmConnectionPort; Desktop uses BetterSqlite3ConnectionPort.
import { Runtime, type ConnectionPort } from "@eidos.space/eidos-file"
const { service, hostBridge } = await Runtime.open(
connection satisfies ConnectionPort,
environment,
"readwrite",
{ cancellation, deadlineMilliseconds: 30_000 }
)
Only service becomes RuntimeClient. hostBridge stays inside trusted
Adapter/product composition. In browsers, keep Connection and Runtime in a
Dedicated Worker and expose the service through
AdapterTransportRuntimeClient; do not send SQLite or raw handles to Window.
Your product implements HostServices for opaque source/destination tokens,
permission, save/CAS, conflict, recovery and assets. Host receives the trusted
bridge; UI does not.
React viewer
import { useEffect, useMemo, type ReactNode } from "react"
import type { HostServices } from "@eidos.space/eidos-file"
import {
EidosFileUIProvider,
type AssetPresenter,
} from "@eidos.space/eidos-file-ui"
import { EidosUIKernel } from "@eidos.space/eidos-file-ui/kernel"
import {
EidosStandardView,
EidosUIRuntimeProvider,
} from "@eidos.space/eidos-file-ui/runtime-platform"
function Viewer({
host,
sourceToken,
assetPresenter,
}: {
host: HostServices
sourceToken: string
assetPresenter: AssetPresenter<ReactNode>
}) {
const kernel = useMemo(() => new EidosUIKernel(host), [host])
useEffect(() => {
void kernel.openSource({ sourceToken, access: "read" })
return () => {
void kernel.close()
}
}, [kernel, sourceToken])
return (
<EidosFileUIProvider locale="en">
<EidosUIRuntimeProvider kernel={kernel} assetPresenter={assetPresenter}>
<EidosStandardView />
</EidosUIRuntimeProvider>
</EidosFileUIProvider>
)
}
The kernel negotiates Host and Runtime, then loads a snapshot and its revision-bound schema before rendering. Grid, Gallery and Kanban consume columnar Runtime results. They never reproduce File filtering, Formula, Lookup, Relation, aggregate or grouping semantics.
EidosFileUIProvider supports locale="en" and locale="zh", plus host
messages or translate overrides. Locale changes UI copy, accessibility
labels, input affordances, and formatting only. Canonical option names and
user-authored Table, Field, and View names remain File data and are never
translated.
EidosStandardView is the reference read-only viewer composition. Full editors use the shared EidosFileEditorShell and editor components so Browser and Desktop keep one interaction hierarchy. See the @eidos.space/eidos-file-ui package guide for the editor composition surface.
File-entry URIs are never presentation URLs. Relative, https:, and canonical
inline image Data URLs all go through HostServices.resolveAsset; only an
injected AssetPresenter consumes the returned lease token. Hosts without a
session-scoped relative root omit that capability. Open/download is an
explicit leased action, and ordinary URL fields never auto-fetch.
Required interoperability checks
- run the same Runtime contract over Browser WASM and Desktop better-sqlite3;
- verify tagged values, nested transactions, snapshots, cancellation and error mapping at the Connection boundary;
- verify prepared-commit receipts before COMMIT on transported mutations;
- verify snapshot/schema/page cursor binding and revision invalidation in UI;
- treat disabled optional capabilities as absent optional methods, not stubs.
- verify invalid Base64/media/size, the 1 MiB inline boundary, missing relative root, lease expiry/fallback, and zero direct URI fetch/navigation.