
Research
/Security News
jscrambler npm Package Compromised in Supply Chain Attack
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.
@page-speed/blocks
Advanced tools
High-performance rendering runtime for @opensite/ui components with pre-compiled Tailwind CSS and tree-shakable architecture
High-performance rendering runtime for @opensite/ui components with pre-compiled Tailwind CSS, RouterProvider integration for Pressable components, and tree-shakable architecture.
@page-speed/pressable directly for proper Tailwind stylingpnpm add @page-speed/blocks
# or
npm install @page-speed/blocks
# or
yarn add @page-speed/blocks
pnpm add react react-dom @opensite/ui @page-speed/img @page-speed/video @page-speed/pressable @page-speed/router
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} />;
}
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
/>
);
}
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
}
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.
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>
);
});
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";
<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
}
// 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
// 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
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.
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",
};
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>
);
});
import { renderToString } from "react-dom/server";
import { EnhancedBlocksRenderer } from "@page-speed/blocks";
const html = renderToString(
<EnhancedBlocksRenderer blocks={blocks} />
);
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} />;
}
If migrating from @opensite/blocks:
// Before
import { BlocksRenderer } from "@opensite/blocks";
// After
import { EnhancedBlocksRenderer } from "@page-speed/blocks";
// Before
<BlocksRenderer blocks={blocks} />
// After
<EnhancedBlocksRenderer blocks={blocks} />
@page-speed/pressable for button/link components, ensuring proper Tailwind styling.See ARCHITECTURE.md for detailed architecture documentation.
BSD-3-Clause - see LICENSE for details.
FAQs
High-performance rendering runtime for @opensite/ui components with pre-compiled Tailwind CSS and tree-shakable architecture
The npm package @page-speed/blocks receives a total of 14 weekly downloads. As such, @page-speed/blocks popularity was classified as not popular.
We found that @page-speed/blocks demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

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.

Research
/Security News
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.

Research
/Security News
A malicious .NET package is typosquatting the Braintree SDK to steal live payment card data, merchant API keys, and host secrets from production apps.

Security News
/Research
Compromised Injective SDK npm version 1.20.21 exfiltrates wallet private keys and mnemonics through fake telemetry functionality.