Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@page-speed/blocks

Package Overview
Dependencies
Maintainers
2
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@page-speed/blocks

High-performance rendering runtime for @opensite/ui components with pre-compiled Tailwind CSS and tree-shakable architecture

latest
Source
npmnpm
Version
0.1.5
Version published
Weekly downloads
13
Maintainers
2
Weekly downloads
 
Created
Source

@page-speed/blocks

High-performance rendering runtime for @opensite/ui components with pre-compiled Tailwind CSS, RouterProvider integration for Pressable components, and tree-shakable architecture.

Features

  • Performance-First: Optimized for minimal bundle size and maximum runtime performance
  • Tree-Shakable: Granular exports allow importing only what you need
  • Flexible Styling: Works with both pre-compiled CSS and runtime Tailwind
  • Registry-Based: Extensible component registry for custom renderers
  • RouterProvider Integration: Automatic RouterProvider wrapping for Pressable components
  • Direct Pressable Usage: Uses @page-speed/pressable directly for proper Tailwind styling
  • TypeScript: Full type safety with comprehensive type definitions
  • React 18+: Built for modern React with hooks and concurrent features

Installation

pnpm add @page-speed/blocks
# or
npm install @page-speed/blocks
# or
yarn add @page-speed/blocks

Peer Dependencies

pnpm add react react-dom @opensite/ui @page-speed/img @page-speed/video @page-speed/pressable @page-speed/router

Quick Start

Basic Usage

import { BlocksRenderer } from "@page-speed/blocks";
import type { Block } from "@page-speed/blocks/types";

const blocks: Block[] = [
  {
    _id: "1",
    _type: "Box",
    styles: "p-4 bg-gray-100",
    content: "Hello World",
  },
];

function App() {
  return <BlocksRenderer blocks={blocks} />;
}

The EnhancedBlocksRenderer automatically wraps your blocks with RouterProvider from @page-speed/router, ensuring Pressable components work correctly:

import { EnhancedBlocksRenderer } from "@page-speed/blocks";
import type { Block } from "@page-speed/blocks/types";

const blocks: Block[] = [
  {
    _id: "1",
    _type: "Button",
    props: {
      variant: "default",
      size: "lg",
      onClick: () => console.log("Clicked!"),
    },
    content: "Click Me",
  },
];

function App() {
  return <EnhancedBlocksRenderer blocks={blocks} />;
}

Manual Provider Control

If your app already has a RouterProvider, you can disable the automatic wrapping:

import { EnhancedBlocksRenderer } from "@page-speed/blocks";

function App() {
  return (
    <EnhancedBlocksRenderer
      blocks={blocks}
      disableRouter={true}  // App already has RouterProvider
    />
  );
}

Core Concepts

Block Structure

Blocks are the fundamental building units, compatible with Chai design payloads:

interface Block {
  _id: string;              // Unique identifier
  _type: string;            // Component type (maps to renderer)
  _parent?: string | null;  // Parent block ID (null for root)
  styles?: string;          // Tailwind CSS classes
  content?: string;         // Text content
  props?: Record<string, any>; // Component-specific props
  // ... additional properties
}

Built-in Renderers

The library includes optimized renderers for common component types that use @page-speed/pressable directly:

// Automatically registered block types:
- Pressable, PressableButton, PressableLink, CTAButton, ActionButton
- Button, SubmitButton, FormButton
- Link, NavLink, CTALink, ExternalLink

These renderers ensure proper Tailwind styling by using the Pressable component from @page-speed/pressable directly instead of pass-through components.

Component Registry

Extend the library with custom renderers:

import { registerBlockRenderer } from "@page-speed/blocks/registry";

registerBlockRenderer("MyComponent", ({ block, context }) => {
  return (
    <div className={block.styles}>
      {block.content}
      {context.renderChildren(block._id)}
    </div>
  );
});

Tree-Shakable Imports

Import only what you need for optimal bundle size:

// Specific imports (recommended)
import { EnhancedBlocksRenderer } from "@page-speed/blocks/core/enhanced";
import { BlocksProvider } from "@page-speed/blocks/core/provider";
import { registerBlockRenderer } from "@page-speed/blocks/registry";
import type { Block } from "@page-speed/blocks/types";

// Custom renderers
import {
  pressableRenderer,
  buttonRenderer,
  linkRenderer
} from "@page-speed/blocks/renderers";

// Main export (includes all core functionality)
import {
  EnhancedBlocksRenderer,
  BlocksRenderer,
  registerBlockRenderer,
  initializeDefaultRenderers
} from "@page-speed/blocks";

API Reference

Components

<EnhancedBlocksRenderer />

The main component for rendering blocks with automatic RouterProvider wrapping:

interface EnhancedBlocksRendererProps {
  blocks: Block[];           // Array of blocks to render
  className?: string;        // Optional CSS class for wrapper
  wrapper?: React.ComponentType<{ children: React.ReactNode }>;
  disableRouter?: boolean;   // Disable RouterProvider if app already has one
}

<BlocksRenderer />

Base renderer without RouterProvider (for advanced use cases):

interface BlocksRendererProps {
  blocks: Block[];
  className?: string;
  wrapper?: React.ComponentType<{ children: React.ReactNode }>;
}

<BlocksProvider />

Provider component for wrapping blocks with necessary context:

interface BlocksProviderProps {
  children: React.ReactNode;
  disableRouter?: boolean;  // Optional: disable router provider
}

Registry Functions

// Register a custom renderer for a block type
registerBlockRenderer(type: string, renderer: BlockRenderer): void

// Get renderer for a specific type
getBlockRenderer(type: string): BlockRenderer | undefined

// Check if a renderer exists
hasBlockRenderer(type: string): boolean

// Remove a renderer
unregisterBlockRenderer(type: string): void

// Clear all custom renderers
clearRegistry(): void

// Get all registered types
getRegisteredTypes(): string[]

// Register multiple renderers at once
registerRenderers(renderers: Record<string, BlockRenderer>): void

// Initialize default renderers (auto-called in browser)
initializeDefaultRenderers(): void

Utility Functions

// Parse design payload string to blocks
parseDesignPayload(payload: string | DesignPayload): Block[]

// Get root blocks (no parent)
getRootBlocks(blocks: Block[]): Block[]

// Get child blocks of a parent
getChildBlocks(blocks: Block[], parentId: string): Block[]

// Build element props from block
buildElementProps(block: Block): Record<string, any>

// Extract className from styles string
extractClassName(styles?: string): string

// Extract background styles
extractBackgroundStyle(styles?: string): React.CSSProperties | undefined

Pre-compiled CSS Support

For production environments, use pre-compiled Tailwind CSS:

// In your HTML/layout
<link rel="stylesheet" href="https://cdn.example.com/tailwind.css" />

// Then use BlocksRenderer normally
<EnhancedBlocksRenderer blocks={blocks} />

The library automatically works with pre-compiled styles, ensuring all button variants and component styles are properly applied.

Pressable Component Integration

The library includes direct integration with @page-speed/pressable for proper button and link styling:

// This will use the optimized Pressable renderer
const buttonBlock: Block = {
  _id: "btn-1",
  _type: "Button",
  props: {
    variant: "default",
    size: "lg",
    onClick: () => console.log("Clicked!"),
  },
  content: "Click Me",
};

// Links also use Pressable
const linkBlock: Block = {
  _id: "link-1",
  _type: "Link",
  props: {
    href: "/about",
    variant: "link",
  },
  content: "Learn More",
};

Advanced Usage

Custom Block Renderer

import { registerBlockRenderer } from "@page-speed/blocks";
import { Pressable } from "@page-speed/pressable";

registerBlockRenderer("CustomCTA", ({ block, context }) => {
  const { href, label, icon } = block.props || {};

  return (
    <Pressable
      href={href}
      variant="default"
      size="lg"
      className="my-custom-class"
    >
      {icon && <Icon name={icon} />}
      {label || block.content}
      {context.renderChildren(block._id)}
    </Pressable>
  );
});

Server-Side Rendering

import { renderToString } from "react-dom/server";
import { EnhancedBlocksRenderer } from "@page-speed/blocks";

const html = renderToString(
  <EnhancedBlocksRenderer blocks={blocks} />
);

Dynamic Block Loading

import { BlocksRenderer, parseDesignPayload } from "@page-speed/blocks";

async function loadAndRenderBlocks() {
  const response = await fetch("/api/blocks");
  const payload = await response.json();
  const blocks = parseDesignPayload(payload);

  return <BlocksRenderer blocks={blocks} />;
}

Migration from @opensite/blocks

If migrating from @opensite/blocks:

  • Replace imports:
// Before
import { BlocksRenderer } from "@opensite/blocks";

// After
import { EnhancedBlocksRenderer } from "@page-speed/blocks";
  • Use EnhancedBlocksRenderer for automatic RouterProvider:
// Before
<BlocksRenderer blocks={blocks} />

// After
<EnhancedBlocksRenderer blocks={blocks} />
  • The library automatically uses @page-speed/pressable for button/link components, ensuring proper Tailwind styling.

Browser Support

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+
  • React 17+ required

Contributing

See ARCHITECTURE.md for detailed architecture documentation.

License

BSD-3-Clause - see LICENSE for details.

Keywords

react

FAQs

Package last updated on 04 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts