Author: | calebporzio |
---|---|
Views Total: | 24 views |
Official Page: | Go to website |
Last Update: | June 4, 2025 |
License: | MIT |
Preview:

Description:
Sprout is a zero-dependency JavaScript library that transforms JSON data into reactive DOM elements. using native browser APIs.
It uses standard HTML <template>
elements with data attributes to create reactive interfaces that automatically update when underlying data changes.
Features
- Declarative Templates: Uses native HTML
<template>
elements with data attributes - Automatic Reactivity: Re-renders when
data-json
attribute changes - Minimal Bundle Size: Lightweight footprint for performance-conscious applications
- Browser-Native: Leverages MutationObserver and template elements
- Keyed Rendering: Efficient list updates with optional key-based diffing
How to use it:
1. Install Sprout and import it into your project.
# NPM $ npm install @sprout-js/sprout
<script type="module"> import '@sprout-js/sprout'; </script>
2. Create reactive templates using the is="🌱"
attribute and data-json
for data binding:
is="🌱"
: Identifies a<template>
as a Sprout root component. This is where Sprout starts its work.data-json
: Supplies the JSON data string to the root template. Changes to this attribute trigger re-renders.data-for="{item in items}"
: Iterates over an array.items
should be an array in your data context, anditem
is the name you’ll use to reference each element in the loop. The special variable_
can be used to refer to the current data context. If yourdata-json
is an array itself,data-for="{item in _}"
iterates that array.data-if="{condition}"
: Renders the content of the template if the condition evaluates to a truthy value.data-unless="{condition}"
: Renders the content of the template if the condition evaluates to a falsy value.data-key="{expression}"
: Provides a unique key for items in adata-for
loop. This is crucial for performance and maintaining state if your list items can be reordered or have their own internal state. I’ve found that using a unique ID from your data (data-key="{item.id}"
) is generally the best practice here.
<template is="🌱" data-json='{"title": "User Dashboard", "users": [{"name": "Alice", "role": "admin"}, {"name": "Bob", "role": "user"}]}'> <div class="dashboard"> <h1>{title}</h1> <template data-for="{user in users}"> <div class="user-card {user.role}"> <span>{user.name}</span> <template data-if="{user.role === 'admin'}"> <badge>Admin</badge> </template> </div> </template> </div> </template>
3. Sprout monitors the data-json
attribute of the root template. If you update this attribute with a new JSON string, Sprout automatically re-renders the template.
const newData = [{ ... }]; templateElement.setAttribute('data-json', JSON.stringify(newData));
FAQs
Q: Can I nest Sprout templates within each other?
A: Yes, nested templates work as expected. Inner templates inherit the parent’s data context unless they define their own data-json
attribute.
Q: What happens if JSON parsing fails?
A: Sprout includes basic error handling that falls back to rendering nothing if JSON.parse()
throws. In production applications, I recommend validating data before setting the data-json
attribute to avoid silent failures.
Q: Can I use async data or fetch results?
A: Absolutely. Fetch your data, stringify it, and set the data-json
attribute. The library doesn’t care about data sources. I frequently use this pattern with API endpoints that return user lists or configuration objects.
Q: How do I handle form inputs and user interactions?
A: Sprout focuses on rendering, not event handling. Attach event listeners using standard DOM APIs after the template renders. The comment markers help identify the rendered content boundaries for event delegation patterns.