# ncblock

> [!NOTE]
> Nothing to see here. This is **extreme** alpha and currently only works for an unreleased product.

SDK for building Notion custom view blocks.

A custom view runs as a sandboxed `<iframe>` inside a Notion block on iOS, Android, and desktop. The only channel between your view and Notion is a `postMessage` bridge — this SDK wraps it in typed React hooks plus a small framework-neutral runtime API for non-React renderers.

> **Pre-release.** Breaking changes may land at any time before 1.0.

## Quick start

```tsx
// src/index.tsx
import { NotionCustomBlock } from "ncblock/react";
import ReactDOM from "react-dom/client";
import { App } from "./App";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <NotionCustomBlock>
    <App />
  </NotionCustomBlock>,
);
```

```tsx
// src/App.tsx
import { useBlockId, useTheme } from "ncblock/react";

export function App() {
  const blockId = useBlockId();
  const theme = useTheme();
  return <div data-theme={theme}>Hello from {blockId}.</div>;
}
```

`<NotionCustomBlock>` runs the SDK ↔ host handshake (sends `ready` with the manifest, awaits `init`) and only mounts `children` once it resolves. Inside the wrapper, every hook returns non-nullable values — there's no separate gating component to write. It also runs `useCustomBlockAutoResize` for you by default; pass `autoResize={false}` to opt out.

## Reference

API surface, one page per category. Import framework-neutral APIs from `ncblock`; import React hooks and components from `ncblock/react`. Hover docs in your editor cover the per-field detail; these pages cover usage shape and the gotchas.

- [`docs/lifecycle.md`](./docs/lifecycle.md) — `<NotionCustomBlock>`, `useCustomBlockInit`, `initCustomBlock`, `customBlock.autoResize`, `NotInIframeError`, `useCustomBlockAutoResize`. The handshake, the React wrapper, sizing.
- [`docs/block-location.md`](./docs/block-location.md) — `useBlockId`, `useParent`, `usePage`, `useTheme`. Where the block sits in the document tree and the host's color scheme.
- [`docs/data-sources.md`](./docs/data-sources.md) — `useDataSource`, `useManifest`, `customBlock.getManifest`, the row, property, and date-value types, plus a worked example.
- [`docs/pages.md`](./docs/pages.md) — `pages.create / get / update / delete`, parent variants (including the recommended `data_source_key`), property input shapes.
- [`docs/users.md`](./docs/users.md) — `users.list / get`, the `NotionUser` shape, paging.
- [`docs/manifest.md`](./docs/manifest.md) — `custom_blocks.json`, the Vite plugin, manifest types.

## Forbidden APIs

No top-level navigation, `window.open`, or auth redirects. No direct network requests — cross-origin work goes through the host (and is exposed via SDK hooks).

## Bridge protocol

The bridge speaks a versioned `postMessage` protocol. You shouldn't need protocol-level details to build a view. If you're implementing a host, see [`HOST.md`](./HOST.md).
