
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
juxscript
Advanced tools
JUX is a headless UI authoring framework. Build reactive web applications with 100% JavaScript — no HTML templates, no JSX, no markup of any kind.
Think of it like a more reactive Streamlit, but for the web, written entirely in JavaScript. Author your UI top-down, procedurally — components appear in the order you call them.
npx juxscript create my-app
cd my-app
npm run dev
// jux/index.jux
import { jux } from 'juxscript';
jux.h1('greeting', { content: 'Hello, World!' });
jux.p('intro', { content: 'Welcome to JUX — no HTML required.' });
jux.btn('click-me', { content: 'Click me' });
That's it. Three lines render a heading, a paragraph, and a button. The order you write them is the order they appear on the page.
pageState connects components automaticallynpx juxscript create my-app
cd my-app
npm run dev
This scaffolds a new project, installs dependencies, and starts a hot-reload dev server.
npm install juxscript
npx juxscript init # creates jux/ directory and juxconfig.js
npm run dev
JUX files use the .jux extension but are plain JavaScript. Tell VS Code:
// .vscode/settings.json
{
"files.associations": {
"*.jux": "javascript"
},
"javascript.validate.enable": false
}
jux NamespaceEvery component is accessed through the jux object. Import it once and everything you need is there.
import { jux } from 'juxscript';
jux.h1('page-title', { content: 'Dashboard' });
jux.h2('section', { content: 'Overview' });
jux.p('description', { content: 'Here is your summary.' });
jux.span('note', { content: 'Updated just now' });
jux.pre('code-block', { content: 'const x = 42;' });
jux.input('username', { label: 'Username', placeholder: 'Enter name...' });
jux.email('email', { label: 'Email' });
jux.password('pass', { label: 'Password' });
jux.number('quantity', { label: 'Quantity', value: '1' });
jux.select('color', {
label: 'Favourite colour',
options: [
{ label: 'Red', value: 'red' },
{ label: 'Green', value: 'green' },
{ label: 'Blue', value: 'blue' }
]
});
jux.checkbox('agree', { label: 'I agree to the terms' });
jux.radio('size', {
label: 'Size',
options: [
{ label: 'Small', value: 'sm' },
{ label: 'Medium', value: 'md' },
{ label: 'Large', value: 'lg' }
]
});
jux.btn('save', { content: 'Save', variant: 'default' });
jux.btn('delete', { content: 'Delete', variant: 'destructive' });
jux.btn('cancel', { content: 'Cancel', variant: 'outline' });
jux.a('home-link', { content: 'Home', href: '/' });
// c(width, height, padding, borderRadius)
const card = jux.c('100%', 'auto', '1rem', '8px');
// Render something inside the card
jux.p('card-text', { content: 'I live inside the card', target: card.id });
jux.list('todo-list', {
items: [
{ id: 'a', content: 'Buy milk', icon: '🛒' },
{ id: 'b', content: 'Write code', icon: '💻' }
],
selectable: true
});
jux.table('users-table', {
columns: [
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email' },
{ key: 'role', label: 'Role' }
],
items: [
{ name: 'Alice', email: 'alice@example.com', role: 'Admin' },
{ name: 'Bob', email: 'bob@example.com', role: 'User' }
]
});
jux.nav('main-nav', {
items: [
{ id: 'nav-home', icon: '🏠', label: 'Home', path: '/' },
{ id: 'nav-settings', icon: '⚙️', label: 'Settings', path: '/settings' }
]
});
const tabs = jux.tabs('page-tabs');
tabs.addTab({ id: 'overview', label: 'Overview', content: 'Overview content here.' });
tabs.addTab({ id: 'details', label: 'Details', content: 'Details content here.' });
tabs.activeTab('overview');
tabs.render('#app');
const api = await jux.data('my-api', { url: '/api/users' });
// api.value contains the response
console.log(api.getValue());
jux.include('/css/shadcn.css'); // inject a stylesheet link
jux.style('custom', 'body { margin: 0; }'); // inject inline CSS
pageStatepageState is JUX's reactivity layer. Every component you create is automatically registered in pageState, keyed by its id. Read values, react to events, and update the DOM — all from plain JavaScript.
import { jux, pageState } from 'juxscript';
jux.input('search', { label: 'Search' });
jux.p('result', { content: '' });
// Whenever 'search' changes, update 'result'
pageState.__watch(() => {
pageState['result'].content = 'You typed: ' + pageState['search'].value;
});
jux.btn('submit-btn', { content: 'Submit' });
jux.p('status', { content: 'Waiting...' });
pageState.__watch(() => {
if (pageState['submit-btn'].click) {
pageState['status'].content = 'Submitted! ✅';
}
});
Available event flags: click, change, input, blur, focus, keydown, keyup, hover, active, focused.
Reactions re-run whenever any pageState value they read changes — just like a spreadsheet. Chain them freely:
jux.input('first-name', { label: 'First name' });
jux.input('last-name', { label: 'Last name' });
jux.p('full-name', { content: '' });
// Reacts to either input changing
pageState.__watch(() => {
const first = pageState['first-name'].value;
const last = pageState['last-name'].value;
pageState['full-name'].content = `${first} ${last}`.trim();
});
Because authoring is top-down procedural code, you can use plain if statements:
jux.input('promo-code', { label: 'Promo code' });
pageState.__watch(() => {
if (pageState['promo-code'].value === 'JUXROCKS') {
jux.p('promo-msg', { content: '🎉 10% discount applied!' });
}
});
jux.p('hint', { content: 'Fill in all fields first.' });
pageState.__watch(() => {
pageState['hint'].visible = pageState['username'].value === '';
});
c (Container)c is a lightweight container that handles sizing and layout without any CSS classes.
import { jux, c } from 'juxscript';
// c(width, height, padding, borderRadius)
const sidebar = c('260px', '100vh', '1rem', '0');
const main = c('calc(100% - 260px)', '100vh', '2rem', '0');
// Nest components inside a container using target
jux.h2('sidebar-title', { content: 'Menu', target: sidebar.id });
jux.h1('page-heading', { content: 'Welcome', target: main.id });
Copy ready-made components into your project with:
npx juxscript comp sidebar
Available presets:
| Preset | Description |
|---|---|
sidebar | Collapsible sidebar with nav sections |
More presets coming soon. Contribute your own to components/.
JUX ships with a bar chart component you can drop into any page.
import { juxBarChart } from './bar.jux';
juxBarChart('revenue-chart', [
{ x: 4200, label: 'Jan' },
{ x: 5800, label: 'Feb' },
{ x: 3900, label: 'Mar' },
{ x: 7100, label: 'Apr' }
], {
title: 'Monthly Revenue',
subtitle: 'USD, 2024',
orientation: 'horizontal',
colors: 'blue',
width: 600,
showValues: true
}).render('#app');
juxBarChart('visitors', [
{ x: 1200, label: 'Mon' },
{ x: 980, label: 'Tue' },
{ x: 1540, label: 'Wed' }
], {
orientation: 'vertical',
colors: 'green',
width: 500
}).render('#app');
| Option | Default | Description |
|---|---|---|
orientation | 'horizontal' | 'horizontal' or 'vertical' |
colors | 'green' | Palette name or array of hex colours |
title | '' | Chart title |
subtitle | '' | Chart subtitle |
width | 500 | Width in pixels |
aspectRatio | '16:9' | '16:9', '4:3', '1:1', '21:9', etc. |
showValues | false | Show value labels on bars |
ticks | 4 | Number of axis tick marks |
animate | true | Animate bars on load |
import { jux } from 'juxscript';
// Named palettes
jux.palette('green'); // greens
jux.palette('blue'); // blues
jux.palette('multi'); // multi-colour
// Or pass a custom array
colors: ['#6366f1', '#8b5cf6', '#a78bfa']
// jux/dashboard.jux
import { jux, pageState } from 'juxscript';
import { juxBarChart } from './bar.jux';
// ── Layout ─────────────────────────────────────────────────────
jux.h1('dash-title', { content: 'Sales Dashboard' });
jux.p('dash-subtitle', { content: 'Real-time overview' });
// ── Filters ────────────────────────────────────────────────────
jux.select('period', {
label: 'Period',
options: [
{ label: 'This week', value: 'week' },
{ label: 'This month', value: 'month' },
{ label: 'This year', value: 'year' }
]
});
// ── Chart ──────────────────────────────────────────────────────
juxBarChart('sales-chart', [
{ x: 3200, label: 'Mon' },
{ x: 4100, label: 'Tue' },
{ x: 2900, label: 'Wed' },
{ x: 5300, label: 'Thu' },
{ x: 4800, label: 'Fri' }
], { title: 'Sales This Week', colors: 'blue', width: 600 }).render('#app');
// ── Table ──────────────────────────────────────────────────────
jux.table('top-products', {
columns: [
{ key: 'name', label: 'Product' },
{ key: 'sales', label: 'Sales' },
{ key: 'rev', label: 'Revenue' }
],
items: [
{ name: 'Widget A', sales: 320, rev: '$6,400' },
{ name: 'Widget B', sales: 210, rev: '$4,200' }
]
});
// ── Reactivity ─────────────────────────────────────────────────
jux.p('selected-period', { content: 'Showing: This week' });
pageState.__watch(() => {
const p = pageState['period'].value;
if (p) pageState['selected-period'].content = 'Showing: ' + p;
});
npx juxscript create <name> # Scaffold a new project
npx juxscript init # Init JUX in an existing directory
npx juxscript serve # Start production server
npx juxscript serve --hot # Start dev server with hot reload
npx juxscript build # Build for production
npx juxscript comp [name] # Add a component preset
npx juxscript comp [name] -f # Force overwrite (backs up existing)
my-app/
├── jux/
│ ├── index.jux ← entry page (rendered at /)
│ ├── about.jux ← rendered at /about
│ └── sidebar/ ← component presets live here
│ └── index.jux
├── public/
│ └── styles.css
├── juxconfig.js
└── package.json
juxconfig.js)export const config = {
directories: {
src: 'jux',
public: 'public',
dist: '.jux-dist'
},
server: {
port: 3000,
host: 'localhost'
}
};
pageState reactivity systemjux comp)FAQs
A JavaScript UX authorship platform
We found that juxscript 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.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.