# Entities and blocks

> Concept: Item types, document-backed and non-document blocks, aliases, load sources, nesting rules, and file type resolution.

- Repository: macro-inc/macro
- GitHub: https://github.com/macro-inc/macro
- Human docs: https://grok-wiki.com/public/docs/macro-inc-macro-bb988e1a448e
- Complete Markdown: https://grok-wiki.com/public/docs/macro-inc-macro-bb988e1a448e/llms-full.txt

## Source Files

- `js/app/packages/core/block.ts`
- `js/app/packages/core/constant/allBlocks.ts`
- `js/app/packages/block-md/definition.ts`
- `js/app/packages/block-project/definition.ts`
- `js/app/packages/service-clients/service-storage/client.ts`
- `rust/cloud-storage/models_soup/src/lib.rs`

---

---
title: "Entities and blocks"
description: "Concept: Item types, document-backed and non-document blocks, aliases, load sources, nesting rules, and file type resolution."
---

Macro maps storage-service items and repository-defined block definitions into Solid block instances. The frontend resolves an entity-like item to a `BlockName` or `BlockAlias`, creates a `Source`, runs the selected block definition’s `load(source, intent)`, and exposes the loaded data through block-scoped signals.

## Core identifiers

| Identifier | Purpose |
| --- | --- |
| `BlockName` | Concrete block type from `BlockRegistry`, such as `pdf`, `md`, `code`, `image`, `canvas`, `chat`, `project`, `channel`, `email`, `video`, `automation`, and `unknown`. |
| `BlockAlias` | Pseudo-block type that preserves UX semantics while reusing a base block implementation. Current aliases are `task` and `csv`. |
| `ItemType` | Storage/client item category: cloud storage item types (`document`, `chat`, `project`) plus `channel`, `email`, `channel_message`, `call`, and `automation`. |
| `Source` | Runtime loading input. Remote sources are `dss` and `sync-service`; local/intermediate sources include `blob`, `buffer`, `opfs`, `gen`, and `preload`. |
| `SoupItem` | Backend aggregate enum for list/search results: documents, chats, projects, email threads, channels, calls, CRM companies, and foreign entities. |

<Warning>
`BlockRegistry` contains `write` and `contact`, but this checkout does not include `block-write/definition.ts` or `block-contact/definition.ts`. Treat them as registry-level names, not loadable block implementations, until definition modules are added.
</Warning>

## Block definitions

Block definitions are collected with `import.meta.glob('../../block-*/definition.ts')`. Each definition provides:

```ts
defineBlock({
  name,
  description,
  component,
  accepted,
  load,
  defaultFilename?,
  aliases?,
  liveTrackingEnabled?,
  syncServiceEnabled?,
  editPermissionEnabled?,
})
```

| Block | Accepted file types | Primary load source | Notes |
| --- | --- | --- | --- |
| `pdf` | `pdf`, `docx` | `dss` | Fetches binary document data, downloads the blob, and initializes pdf.js. |
| `md` | `md` | `sync-service` | Uses backend-owned sync-service content and Loro state. Alias: `task`. |
| `code` | Code extensions from `FileTypeMap` where `app === 'code'` | `dss` | Loads text via `getTextDocument`. Alias: `csv`. |
| `image` | `png`, `jpg`, `jpeg`, `gif`, `svg`, `webp` | `dss` | Fetches binary data and builds a DSS file wrapper. |
| `canvas` | `canvas` | `dss` | Fetches binary canvas data and builds a DSS file wrapper. |
| `video` | Video extensions when `ENABLE_VIDEO_BLOCK` is enabled | `dss` | Fetches metadata and a presigned playback URL for supported formats. |
| `unknown` | none | `dss` | Metadata-only fallback for unsupported document file types. |
| `project` | none | `dss` | Special-cases `root` and `trash`; otherwise fetches project metadata. |
| `chat` | none | `dss` | Fetches chat data from cognition and synthesizes document-like metadata. |
| `channel` | none | `dss` | Loads by channel id only. |
| `email` | none | `dss` | Fetches and caches an email thread. |
| `call` | none | `dss` | Enabled only when `ENABLE_CALLS()` returns true. |
| `automation` | none | `dss` | Loads an automation schedule id. |

## Document-backed and non-document blocks

`NonDocumentBlockTypes` marks blocks that do not correspond to document file content:

```ts
[
  'call',
  'chat',
  'channel',
  'project',
  'email',
  'contact',
  'automation',
]
```

Everything else normally behaves as document-backed content. Aliases are not listed as non-document blocks: `task` resolves to `md`, and `csv` resolves to `code`, so both remain document-backed.

`blockNameToItemType()` converts blocks back to item types for history and storage operations:

| Block or alias | Item type |
| --- | --- |
| `chat` | `chat` |
| `call` | `call` |
| `channel` | `channel` |
| `project` | `project` |
| `email` | `email` |
| `automation` | `automation` |
| all other blocks and aliases | `document` |

## Aliases

Aliases are declared inside block definitions, not in a separate routing table.

| Alias | Base block | Default filename | Meaning |
| --- | --- | --- | --- |
| `task` | `md` | `New Task` | A markdown document with task subtype metadata. |
| `csv` | `code` | `New CSV` | A text/code document presented as a CSV-specific entity. |

Alias handling has two layers:

1. `fileTypeToBlockName()` may return the alias when the input is an alias or when an item `subType.type` is an alias.
2. `resolveBlockAlias()` flattens aliases to the concrete block implementation before mounting or calling block methods.

Split-layout URLs preserve aliases with `aliasContext`, so a route can encode `/task/:id` while the mounted implementation is still the `md` block. Duplicate split checks compare resolved block names, preventing the same item from opening twice as both `/md/:id` and `/task/:id`.

## File type resolution

`allBlocks.ts` builds lookup tables from every block definition’s `accepted` map:

| Lookup | Output |
| --- | --- |
| `blockAcceptedMimetypeToFileExtension` | MIME type to first registered extension. |
| `blockAcceptedFileExtensionToMimeType` | Extension to MIME type. |
| `blockAcceptedFileExtensionSet` | All accepted extensions. |
| `blockNameToFileExtensions` | Block name to accepted extensions. |
| `blockNameToMimeTypes` | Block name to accepted MIME types. |
| `fileTypeToBlockName()` | Block name, alias, or `unknown`. |
| `fileTypeToResolvedBlockName()` | Concrete block name with aliases flattened. |

Resolution order for `fileTypeToBlockName(input, icon?)`:

1. Missing input returns `unknown`.
2. `channel_message` maps to `channel`.
3. With `ENABLE_DOCX_TO_PDF`, `docx` and `write` map to `pdf` for behavior, but `icon: true` returns `write`.
4. Alias names return the alias.
5. Registered block names return themselves.
6. Accepted file extensions map to their owning block.
7. Unrecognized input returns `unknown`.

`itemToBlockName(item, icon?)` gives document subtypes precedence over file types. If `item.subType.type` is a known alias, it returns that alias; otherwise it resolves `item.fileType`, then falls back to `item.type`.

## Load sources and lifecycle

The orchestrator’s default source resolver returns `sync-service` when a block definition has `syncServiceEnabled`; otherwise it returns a `dss` source with the id and optional upload metadata from router state.

```text
item or route
  -> block/file-type resolution
  -> createBlockInstance(type, id)
  -> Source: sync-service or dss
  -> definition.load(source, 'initial')
  -> BlockLoader signals
```

`BlockLoader` rejects nested preload results during initial load, records load errors as `UNAUTHORIZED`, `MISSING`, `GONE`, or `INVALID`, and publishes common fields when present:

| Loaded field | Published signal behavior |
| --- | --- |
| `dssFile` | Sets block file signal. |
| `text` | Sets block text signal. |
| `userAccessLevel` | Sets user access; defaults to `view` when absent. |
| `documentMetadata` | Sets document metadata. |
| `projectMetadata` | Converted into a document-metadata-shaped value for shared UI. |
| `loroManager` | Sets collaborative document state manager. |
| `syncSource` | Registered for cleanup on unmount. |

Markdown is the main sync-service-backed block. It requires the storage location to be `syncServiceContent`; object-storage markdown content is treated as invalid because markdown initialization and persistence are backend-owned.

## Backend entity shape

The Rust `SoupItem` enum is the backend list/search aggregate. Each variant can produce a canonical `Entity` with an entity type and string id. Documents with `SoupDocumentSubType::Task` report property entity type `Task`; ordinary documents report `Document`.

Property references are only available for documents, projects, email threads, and chats. Channels, calls, CRM companies, and foreign entities intentionally return no property reference in `to_entity_reference()`.

## Nesting rules

Nested blocks are gated by `ValidNestingCombinations` and checked through `canNestBlock(name, parentName)`. The rule is keyed by child block and stores allowed parent blocks.

| Child block | Allowed parent blocks |
| --- | --- |
| `canvas` | `md` |
| `pdf` | `md` |
| `code` | `md` |
| all other registered children | none |

Alias-aware callers resolve aliases before checking nesting. For example, `task` resolves to `md`, and `csv` resolves to `code`; a CSV/code preview can be nested in markdown if the caller resolves it to `code`.

## Creation and upload paths

Document creation and upload use storage-service client methods:

| Method | Endpoint | Use |
| --- | --- | --- |
| `createDocument()` | `POST /documents` | Generic object-storage document upload. Supports `fileType`, `mimeType`, `isTask`, `teamId`, and related metadata. |
| `createMarkdownDocument()` | `POST /documents/create_markdown` | Backend-initialized markdown sync-service document. |
| `createTask()` | `POST /documents/create_task` | Backend-initialized task document with task properties. |

Upload file type inference first uses an explicit `options.fileType`, then MIME-to-extension lookup from block definitions, then the filename extension when the MIME type is empty. The backend owns object-created finalization and sync-service initialization after upload.

## Related pages

<CardGroup>
  <Card title="Docs" href="/product/docs">
    Real-time collaborative markdown documents.
  </Card>
  <Card title="Tasks" href="/product/tasks">
    Task documents and task-specific properties.
  </Card>
  <Card title="Files" href="/product/files">
    Stored files and upload behavior.
  </Card>
</CardGroup>
