
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
Twiggle is a tiny, focused frontend library designed for building user interfaces. It provides core primitives for JSX rendering and reactive state management, aiming for clarity and a minimal runtime footprint.
Twiggle is a tiny, focused frontend library designed for building user interfaces. It provides core primitives for JSX rendering and reactive state management, aiming for clarity and a minimal runtime footprint.
Twiggle is an innovative, minimalist frontend library that empowers developers to construct dynamic and responsive user interfaces with unparalleled clarity and efficiency. Unlike larger, more opinionated frameworks, Twiggle focuses on providing essential primitives: a custom JSX runtime for declarative UI composition, a robust reactive state management system for predictable data flow. Its design philosophy prioritizes a minimal runtime footprint and direct manipulation of the DOM, making it an ideal choice for projects where performance and control are paramount. Twiggle is perfect for learning the intricacies of frontend frameworks, building small to medium-sized applications, or integrating into existing projects where a lightweight, yet powerful, UI solution is needed.
Twiggle offers a carefully curated set of features, each designed to be powerful yet easy to understand and use:
Custom JSX Runtime:
Minimal DOM Renderer:
Reactive State Primitive:
createState<T>(initialValue: T): Easily create state variables that hold any type of data.get(): Retrieve the current value of a state variable.set(newValue: T): Update the state, triggering automatic re-renders of components that depend on it.runSideEffect(fn: () => void): A powerful mechanism to define side effects that automatically re-run when any observed state changes, providing a clean way to manage complex interactions and data flows.To integrate Twiggle into your project, you can easily install it using your preferred Node.js package manager:
npm install twiggle
# or using yarn
yarn add twiggle
# or using pnpm
pnpm add twiggle
Get your first Twiggle application up and running in minutes. This example demonstrates a simple counter application using Twiggle's state management and JSX rendering.
1. Create your main application file (e.g., src/main.tsx):
// src/main.tsx
import { render, createState } from 'twiggle'
function Counter() {
const count = createState(0)
const increment = () => {
count.set(count.get() + 1)
}
return (
<div>
<h1>Counter App</h1>
<p>Count: {count.get()}</p>
<button onclick={increment}>Increment</button>
</div>
)
}
const root = document.getElementById('root')
if (root) {
render(<Counter />, root)
}
2. Ensure your index.html has a root element:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>Twiggle App</title>
</head>
<body>
<div id="root"></div>
<script
type="module"
src="/src/main.tsx"
></script>
</body>
</html>
3. Configure your vite.config.ts (if using Vite):
Make sure you have vite-plugin-twiggle installed and configured in your Vite setup to handle JSX transformations correctly.
// vite.config.ts
import { defineConfig } from 'vite'
import twiggle from 'vite-plugin-twiggle'
export default defineConfig({
plugins: [twiggle()],
esbuild: {
jsx: 'automatic',
jsxDev: true, // Set to false for production
jsxImportSource: 'twiggle/client', // Ensure this points to Twiggle's client-side JSX runtime
},
})
4. Run your development server:
npm run dev
Your Twiggle application should now be running in your browser!
Understanding these core concepts will help you leverage Twiggle's full potential:
Twiggle's approach to UI construction is centered around JSX, a syntax extension for JavaScript. When your code is compiled, JSX elements are transformed into calls to Twiggle's createElement function.
type: This argument determines the kind of element to create. It can be:
string (e.g., 'div', 'span', 'p') to create standard HTML DOM elements.'Fragment' to create a DocumentFragment, useful for grouping multiple children without adding an extra node to the DOM tree.function (your component) which will be invoked with props and is expected to return a DOM node or fragment.props: An object containing attributes, event handlers, and children for the element.
children: A special prop that can be a string, number, another Twiggle Element, or an Array of these types.onclick, oninput, onchange), aligning with native DOM event attributes.The render(element, parent) function is the entry point for mounting your Twiggle application into the DOM.
element: The Twiggle element (or component instance) you wish to render.parent: The target HTML DOM element where your Twiggle application will be attached.The current implementation is intentionally straightforward: it clears the parent.innerHTML and then appends the element. This direct approach contributes to Twiggle's small bundle size and high performance.
Twiggle's state management is built around a simple yet effective reactive primitive, allowing for explicit control over data flow and UI updates.
createState<T>(initialValue: T): This function initializes a new reactive state variable. It returns an object with two methods:
get(): T: Retrieves the current value of the state. When called within a runSideEffect, it automatically registers the effect as a subscriber to this state.set(newValue: T): Updates the state variable to newValue. This action triggers all registered side effects that depend on this state to re-execute.runSideEffect(fn: () => void): This function is central to Twiggle's reactivity. It executes the provided fn function. During its execution, any createState().get() calls are observed, and the fn is registered as a subscriber to those state variables. Consequently, whenever any of those subscribed state variables are updated via set(), the fn will automatically re-execute, ensuring your UI or other logic remains synchronized with your application's state.
This minimal reactive system, based on an effect stack and per-state subscriber lists, offers a transparent and easy-to-reason-about approach to reactivity, without the complexity of a full-blown reactive framework.
For those interested in contributing to Twiggle or exploring its internal architecture, follow these steps to set up your development environment:
Clone the Monorepo: Twiggle is developed as part of a monorepo. Begin by cloning the entire repository from GitHub:
git clone https://github.com/hrutavmodha/twiggle.git
cd twiggle
Install Dependencies:
Navigate to the twiggle package directory and install all its development and runtime dependencies:
cd packages/twiggle
npm install
Start Development Server:
To run the example/dev server for the twiggle package and see changes live:
npm run start
Build the Package: To compile the Twiggle library for distribution:
npm run build
Twiggle uses Vitest for its testing framework. To run the test suite and ensure all components are functioning as expected:
cd packages/twiggle
npm run test
You can also run the tests with a UI for a more interactive experience:
npm run test:ui
We warmly welcome contributions to Twiggle! Your efforts help improve the library for everyone. Please refer to the main CONTRIBUTING.md file in the monorepo root for comprehensive guidelines on how to contribute effectively to the Twiggle project.
Before submitting a pull request, please ensure that you have:
Twiggle is open-source software, freely available under the terms of the MIT License.
FAQs
Twiggle is a tiny, focused frontend library designed for building user interfaces. It provides core primitives for JSX rendering and reactive state management, aiming for clarity and a minimal runtime footprint.
We found that twiggle demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer 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
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.