Type-Safe React
Without JSX
A production-ready library that replaces JSX with function-based composition — direct CSS-in-props, context-based theming, node-level memoization, and React Server Components support on Next.js.
1// The MeoNode Way
2Div({
3 padding: '24px',
4 background: 'theme.primary',
5 borderRadius: '12px',
6 children: H1('Hello World', {
7 fontSize: '2rem'
8 })
9})Type-safe API
RSC Ready
Theme-driven
Standard React
One Language. One Mental Model.
No context switching between XML and JavaScript. No angle brackets. Just pure functions and full TypeScript inference.
Function-Based Composition
Node(Component, { ... }) is a normal function call. TypeScript validates props directly against the component's signature — no JSX factory overhead, no ambient type declarations.
Zero Context Switching
Stay in expression position throughout. No bouncing between JSX grammar and JavaScript logic. No IIFEs, no extracted variables — just functions calling functions.
Surgical Memoization
Memoize any node with a dependency array. Empty array [] makes a node static — render once, never update. RSC compatible. Standard React, optimized.
Function Calls, Not Syntax Sugar
Every component is a function. Props are type-checked at the call site. Children pass naturally. Layout composes like Lego.
TodoApp.ts
1import {
2 Column, Row, H1, Text, Button,
3 Input, ThemeProvider, Component
4} from '@meonode/ui'
5import { useState } from 'react'
6
7// Type-safe reusable component
8interface TodoItemProps {
9 text: string
10 completed: boolean
11 onToggle: () => void
12}
13
14const TodoItem = Component<TodoItemProps>(({ text, completed, onToggle }) =>
15 Row({
16 gap: 12,
17 alignItems: 'center',
18 padding: '12px 16px',
19 backgroundColor: completed ? 'theme.accent' : 'theme.base.medium',
20 borderRadius: 8,
21 children: [
22 Button(completed ? 'Y' : 'O', {
23 onClick: onToggle,
24 backgroundColor: completed ? 'theme.secondary' : 'theme.base.deep',
25 color: completed ? 'theme.secondary.content' : 'theme.text.tertiary',
26 borderRadius: '50%',
27 width: 28,
28 height: 28,
29 padding: 0,
30 }),
31 Text(text, {
32 textDecoration: completed ? 'line-through' : 'none',
33 color: completed ? 'theme.text.tertiary' : 'theme.text.primary',
34 flex: 1,
35 }),
36 ],
37 })
38)
39
40// Main app with theme
41export const TodoApp = () => {
42 const [todos, setTodos] = useState([
43 { id: 1, text: 'Learn MeoNode', completed: true },
44 { id: 2, text: 'Build something amazing', completed: false },
45 ])
46
47 return ThemeProvider({
48 theme: {
49 mode: 'dark',
50 system: {
51 primary: { default: '#FF6B6B', content: '#4A0000' },
52 secondary: { default: '#6BCB77', content: '#0A3B0F' },
53 accent: { default: '#4ECDC4', content: '#1A4A47' },
54 base: { default: '#1A1A24', content: '#F0F0F5', medium: '#2A2A38', deep: '#12121A' },
55 text: { primary: '#F0F0F5', tertiary: '#9DA3B0' },
56 },
57 },
58 children: Column({
59 gap: 16,
60 padding: 24,
61 maxWidth: 480,
62 children: [
63 H1('My Todos', { fontSize: '1.75rem' }),
64 ...todos.map(todo =>
65 TodoItem({
66 key: todo.id,
67 text: todo.text,
68 completed: todo.completed,
69 onToggle: () => setTodos(prev =>
70 prev.map(t => t.id === todo.id
71 ? { ...t, completed: !t.completed }
72 : t
73 )
74 ),
75 })
76 ),
77 ],
78 }),
79 }).render()
80}Every HTML Element as a Function
From layout primitives to form inputs. Every HTML element exposed as a type-safe function. Children-first for content. Props-first for containers.
Layout & Containers
Div, Column, Row, Grid, Center, Fixed, Relative, Absolute, Sticky, Root
Typography
H1-H6, Text, Span, P, Label, Code, Pre, Blockquote
Forms & Inputs
Input, Button, Textarea, Select, Option, Label, Form, Fieldset
Lists & Tables
Ul, Ol, Li, Table, Thead, Tbody, Tr, Td, Th
Media & Embeds
Img, Video, Audio, Iframe, Canvas, Svg, Source
Interactive
A, Button, Details, Summary, Dialog, Menu
Document Structure
Header, Footer, Main, Nav, Section, Article, Aside
Theme & Portal
ThemeProvider, StyleRegistry, PortalProvider, PortalHost
Context-Based Theming with Automatic Value Resolution
Define your theme object once. Wrap your app with ThemeProvider. Reference tokens anywhere using string paths — 'theme.primary', 'theme.base.content'. No prop drilling. No context consumers. The styling engine resolves values automatically.
Light / Dark / Custom modes
CSS properties as direct props — no style={{ }} wrapper
Pseudo-classes & media queries via css prop
Numbers auto-converted to px
Theme Tokens
primary.default
#FF6B6B
primary.content
#4A0000
secondary.default
#6BCB77
secondary.content
#0A3B0F
accent.default
#4ECDC4
accent.content
#1A4A47
warning.default
#FFE66D
warning.content
#665A00
base.default
#1A1A24
base.content
#F0F0F5
Works Where React Works
Drop MeoNode into any React project — Next.js, Vite, or plain React. JSX components and MeoNode nodes compose seamlessly in both directions.
Next.js
Next.js
Vite
Vite
React
React
TS
TypeScript
Page.ts
1import { Root, Center } from '@meonode/ui'
2
3export default function Page() {
4 return Root({
5 minWidth: '100dvw',
6 minHeight: '100dvh',
7 children: Center({
8 flex: 1,
9 children: Span('Welcome to MeoNode UI!')
10 })
11 }).render()
12}Ready to Ditch the Angle Brackets?
Install @meonode/ui today and experience the most natural way to build type-safe React applications.
npm install @meonode/ui react react-dom