📄 Papyrus (papyr.js) — HTML Made Stupid Simple
Write HTML like you're writing a text message.

Papyrus is an ultra-lightweight, blazing-fast JavaScript library designed to build modern interactive HTML interfaces with absolute zero complexity and zero terminal setups. By bypassing the Virtual DOM, Papyrus delivers direct DOM manipulation with reactive state tracking, enterprise-grade security, and a delightfully simple API.
Papyrus v2.0 introduces a state-of-the-art Agile Modular Architecture, featuring automatic dependency-tracking reactivity, built-in enterprise vault encryption, HTML5 SPA routing, reactive mathematical computations, and advanced physics-based animations—all without a single npm dependency.
[!IMPORTANT]
Read the Official Master Manual (DOCS.md) for a complete, in-depth guide covering fundamentals, reactive data types, database CRUD engines, security ciphers, styling utilities, and a side-by-side comparison cheat sheet mapping Vanilla JS patterns directly to boilerplate-free Papyr.js.
📚 Table of Contents
⚡ Core Philosophy
- One Function. One Rule. Zero Complexity: If you know standard HTML tags and JavaScript objects, you already know Papyrus.
- XSS-Immune Secure Engine: Transparently sanitizes strings, removing dangerous script vectors and pseudo-protocols dynamically.
- No NPM or Terminal Overhead Required: include a single CDN link inside a bare HTML file and hit refresh.
- CSS Spotlight Design System: Loaded with premium dark grids, radial glows, glassmorphism panel states, and fluid scroll animations out of the box.
- Enterprise-Ready Reactivity: Fine-grained dependency tracking with zero virtual DOM overhead—direct DOM updates.
✨ Features
Core Features
- ⚡ Ultra-fast DOM creation — Direct element generation without Virtual DOM
- 🔋 Automatic reactivity — State tracking with computed properties and subscribers
- 🔐 Enterprise security — Built-in XSS sanitization and encrypted storage vault
- 🎨 Premium UI components — Pre-built modals, cards, forms, tables, and animations
- 📱 Mobile-first responsive — Automatic breakpoint handling and mobile optimizations
- 🧮 Reactive math engine — Build dynamic financial models and dashboards
- 💾 Multi-engine persistence — LocalStorage, SessionStorage, Firebase, SQLite support
- 🎬 Physics & animation engine — Particle systems, spring physics, gesture controls
- 🎙️ Speech & vision API — Built-in speech recognition and image processing
- 🤖 AI/ML toolkit — Classifiers, QR scanning, computer vision integration
- 🌐 HTML5 SPA routing — Client-side routing with dynamic parameters
- 🔌 Plugin system — Extend with custom plugins and hooks
- 0️⃣ Zero dependencies — Single 12KB gzipped library with no external libraries
🚀 Installation
CDN (Fastest Setup)
<script src="https://papyrus-js.vercel.app/papyr-complete.js"></script>
Modular CDN (Load Only What You Need)
<script src="https://papyrus-js.vercel.app/papyr-core.js"></script>
<script src="https://papyrus-js.vercel.app/papyr-ui.js"></script>
<script src="https://papyrus-js.vercel.app/papyr-advanced.js"></script>
📦 Bundle Size Breakdown (v3.0)
papyr.js (Core) | 140.96 KB | 25.33 KB | Reactivity, DOM, Router, storage |
papyr.min.js (Core Min) | 51.63 KB | 13.78 KB | Reactivity, DOM, Router, storage |
papyr-ui.min.js (UI Min) | 111.15 KB | 29.62 KB | Components, Layout, Design, styling |
papyr-advanced.min.js (Adv Min) | 78.62 KB | 23.09 KB | Physics, Charts, ML |
papyr-complete.min.js (Comp Min) | 157.07 KB | 44.55 KB | All features compiled |
Lazy-Loaded Dependencies
Advanced features like 3D scenes lazy-load heavy external code (like Three.js) dynamically from CDNs only when used, keeping the baseline package sizes minimal.
⏱️ Quick Start (60 seconds)
1️⃣ Create an HTML File
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Papyrus App</title>
<script src="https://papyrus-js.vercel.app/papyr-complete.js"></script>
</head>
<body>
<div id="app"></div>
<script>
let count = papyr.state(0);
let App = papyr.div(
papyr.h1("Hello Papyr! 🚀"),
papyr.button(
() => `Clicked ${count.value} times`,
{ onclick: () => count.value++ }
)
);
papyr.mount('#app', App);
</script>
</body>
</html>
That's it! Open in your browser and watch it work.
🎯 Core Concepts
1. Reactive State
let count = papyr.state(0);
console.log(count.value);
count.value++;
count.subscribe(newValue => {
console.log("Count changed to:", newValue);
});
2. Computed Properties
let price = papyr.state(100);
let taxRate = papyr.state(0.08);
let totalPrice = papyr.computed(() => {
return price.value * (1 + taxRate.value);
});
console.log(totalPrice.value);
price.value = 200;
console.log(totalPrice.value);
3. Conditional Rendering
let isLoggedIn = papyr.state(false);
let UI = papyr.div(
papyr.if(
isLoggedIn,
papyr.p("Welcome back!"),
papyr.p("Please log in.")
)
);
4. List Rendering
let todos = papyr.state([
{ id: 1, text: "Learn Papyr" },
{ id: 2, text: "Build app" }
]);
let TodoList = papyr.div(
papyr.for(todos, (todo) =>
papyr.div(
papyr.p(todo.text),
papyr.button("Done", { onclick: () => {
todos.value = todos.value.filter(t => t.id !== todo.id);
}})
)
)
);
5. Reactive Math
let salary = papyr.state(50000);
let bonus = papyr.state(5000);
let tax = papyr.state(0.2);
let netIncome = papyr.computed(() => {
let gross = papyr.math.sum(salary, bonus).value;
let taxAmount = papyr.math.mul(gross, tax).value;
return papyr.math.sub(gross, taxAmount).value;
});
📖 API Reference
DOM Creation
papyr.div(...) | Create <div> element | HTMLElement |
papyr.h1-h6(...) | Create headings | HTMLElement |
papyr.p(text, options) | Create <p> | HTMLElement |
papyr.button(text, options) | Create <button> | HTMLElement |
papyr.input(type, placeholder, options) | Create <input> | HTMLElement |
papyr.form(...children) | Create form wrapper | HTMLElement |
papyr.span(...) | Create <span> | HTMLElement |
papyr.a(text, href, options) | Create <a> link | HTMLElement |
papyr.img(src, alt, options) | Create <img> | HTMLElement |
State Management
papyr.state(initialValue) | Create reactive state | StateObject |
papyr.computed(fn) | Create computed property | ComputedObject |
papyr.if(condition, trueNode, falseNode) | Conditional rendering | HTMLElement |
papyr.for(array, renderFn) | List rendering | HTMLElement |
Layout Helpers
papyr.flex.row(...children) | Flex-row layout |
papyr.flex.col(...children) | Flex-column layout |
papyr.flex.center(...children) | Centered flex layout |
papyr.flex.between(...children) | Space-between layout |
papyr.grid(...children) | CSS grid layout |
papyr.container(...children) | Max-width container |
Components
papyr.card(title, content, footer) | Card widget |
papyr.modal(content, title) | Modal dialog |
papyr.toast(message, type, duration) | Toast notification |
papyr.tabs(tabArray) | Tabbed interface |
papyr.carousel(images) | Image carousel |
papyr.table(...args) | Data table |
Storage & Security
papyr.storage.set(key, value) | Store JSON in LocalStorage |
papyr.storage.get(key) | Retrieve from LocalStorage |
papyr.storage.secureSet(key, value, password) | Encrypted storage |
papyr.storage.secureGet(key, password) | Retrieve encrypted data |
papyr.security.sanitize(html) | Remove XSS vectors |
Database
papyr.crud(collectionName, initialData) | Create persistent CRUD DB |
papyr.db(collectionName, engine) | Access multi-engine DB |
Engines: 'local', 'session', 'firebase', 'sqlite'
Math Engine
papyr.math.sum(...args) | Reactive sum |
papyr.math.sub(a, b) | Reactive subtraction |
papyr.math.mul(...args) | Reactive multiplication |
papyr.math.div(a, b) | Reactive division |
papyr.math.avg(...args) | Reactive average |
papyr.math.percent(val, total) | Percentage calculation |
papyr.math.round(val, decimals) | Precision rounding |
Routing
papyr.route(path, componentFn) | Define route |
papyr.navigate(path) | Navigate to route |
papyr.useParams() | Get route parameters |
Animations
papyr.animate(el, properties, duration) | Animate element |
papyr.animate.fade(el, duration) | Fade in/out |
papyr.animate.slide(el, duration) | Slide animation |
papyr.animate.zoom(el, duration) | Zoom animation |
papyr.animate.spring(el, properties, config) | Spring physics |
papyr.parallax(selector, speed) | Parallax effect |
Media & Advanced
papyr.particles(options) | Particle system |
papyr.physics(options) | Physics engine |
papyr.chart(type, data, options) | Chart rendering |
papyr.ai.scan(image) | QR/barcode scanning |
papyr.ai.speak(text, options) | Text-to-speech |
papyr.ai.listen(options) | Speech recognition |
papyr.clipboard.copy(text) | Copy to clipboard |
papyr.file.open() | File picker |
papyr.camera.request() | Camera access |
Utilities
papyr.mount(selector, component) | Mount component to DOM |
papyr.fragment(...children) | Fragment wrapper (no DOM node) |
papyr.html(htmlString) | Parse HTML string |
papyr.delay(ms) | Sleep/delay promise |
papyr.copy(text) | Copy text to clipboard |
papyr.debug(true/false) | Enable debug mode |
papyr.noConflict() | Release global namespace |
🔒 Security Best Practices
⚠️ Important Security Notes
Papyrus includes built-in XSS protection, but you should follow these practices:
- Use
papyr.security.sanitize() for user input:
let userInput = "<img src=x onerror='alert(1)'>";
let safeHTML = papyr.security.sanitize(userInput);
- Be aware of encryption limitations:
[!WARNING]
Storage "Secure" Sync Methods Are Obfuscation, NOT Encryption
The synchronous secureSet() and secureGet() methods use XOR + Base64 obfuscation, which provides ZERO cryptographic security against malicious memory inspection or storage extraction. This is suitable only for basic obfuscation.
Real Encryption: Use Async Methods (AES-256-GCM)
For actual cryptographic security (e.g. session tokens or sensitive data), you MUST use the asynchronous methods which leverage browser-native Web Crypto API AES-GCM 256-bit with PBKDF2:
await papyr.storage.secureSetAsync("token", userToken, myPassword);
let userToken = await papyr.storage.secureGetAsync("token", myPassword);
- Set Content Security Policy headers:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://papyrus-js.vercel.app;
style-src 'self' 'unsafe-inline';
- Secure storage recommendations:
papyr.storage.secureSet("user-session", token, secretKey);
papyr.storage.set("secret", secretValue);
- Sanitize all dynamic content:
papyr.p("User: " + userInput);
papyr.html(userInput);
papyr.html(papyr.security.sanitize(userInput));
Security Tier Levels
papyr.security.setTier('basic');
papyr.security.setTier('standard');
papyr.security.setTier('enterprise');
🚀 Advanced Examples
1. Building a Todo App
let todos = papyr.crud("todos", []);
let TodoApp = papyr.div(
papyr.h1("📝 My Todos"),
papyr.form(
papyr.input("text", "Add a todo...", {
id: "todo-input",
onkeypress: (e) => {
if (e.key === "Enter") {
let input = document.getElementById("todo-input");
if (input.value) {
todos.insert({ text: input.value, done: false });
input.value = "";
}
}
}
})
),
papyr.for(todos.state, (todo) =>
papyr.div(
papyr.flex.between(
papyr.p(todo.text),
papyr.button("Done", {
onclick: () => todos.delete(todo.id)
})
)
)
)
);
papyr.mount("#app", TodoApp);
2. Interactive Dashboard with Math
let revenue = papyr.state(50000);
let expenses = papyr.state(30000);
let growth = papyr.state(0.12);
let profit = papyr.math.sub(revenue, expenses);
let projectedRevenue = papyr.computed(() =>
papyr.math.mul(revenue, papyr.math.sum(1, growth)).value
);
let Dashboard = papyr.div(
papyr.h1("💰 Business Dashboard"),
papyr.flex.row(
papyr.card("Revenue", () => "$" + revenue.value),
papyr.card("Expenses", () => "$" + expenses.value),
papyr.card("Profit", () => "$" + profit.value)
),
papyr.card("Projected Revenue", () => "$" + projectedRevenue.value)
);
papyr.mount("#app", Dashboard);
3. SPA with Routing
papyr.route("/", () => papyr.div(papyr.h1("Home")));
papyr.route("/about", () => papyr.div(papyr.h1("About")));
papyr.route("/user/:id", () => {
let params = papyr.useParams();
return papyr.div(papyr.h1(`User ${params.id}`));
});
let Nav = papyr.div(
papyr.a("Home", "/"),
papyr.a("About", "/about")
);
papyr.mount("#app", papyr.div(Nav, papyr.router()));
4. Animation & Physics
let box = papyr.div("🎁", {
style: { width: "50px", height: "50px", background: "teal" }
});
papyr.animate.spring(box, {
translateX: 200,
rotate: 360
}, {
tension: 0.4,
friction: 0.1
});
let particles = papyr.particles({
count: 100,
life: 2,
velocity: { x: [-5, 5], y: [-5, 5] }
});
papyr.mount("#app", papyr.div(box, particles));
📱 Mobile Responsiveness
Papyrus automatically handles responsive design:
let ResponsiveLayout = papyr.div(
papyr.flex.col(
papyr.div({ class: "sidebar" }, "Menu"),
papyr.div({ class: "content" }, "Main Content")
)
);
⚙️ Performance Optimization
Tips for Maximum Performance
- Use
papyr.computed() wisely:
let expensive = papyr.computed(() => complexCalculation(value));
papyr.p(() => complexCalculation(value.value));
for (let i = 0; i < 100; i++) items.value.push(i);
items.value = [...items.value, ...Array.from({length: 100}, (_, i) => i)];
- Use fragments for large lists:
let BigList = papyr.fragment(
...largeArray.map(item => papyr.p(item))
);
- Lazy-load advanced features:
if (needsPhysics) {
let physics = papyr.physics({ gravity: 10 });
}
Performance Benchmarks
| State creation | < 0.1ms |
| DOM element creation | < 0.5ms |
| State update + re-render | < 2ms |
| 1000-item list render | ~50ms |
| Computed value update | < 0.1ms |
🌐 Browser Support
| Chrome | ✅ Full | 60+ |
| Firefox | ✅ Full | 55+ |
| Safari | ✅ Full | 11+ |
| Edge | ✅ Full | 79+ |
| IE11 | ⚠️ Limited | Polyfills needed |
| Mobile Chrome | ✅ Full | 60+ |
| Mobile Safari | ✅ Full | 11+ |
🔥 Reactive Mathematical Studio (papyr.math)
Build complex reactive equation trees instantly:
let price = papyr.state(100);
let discount = papyr.state(15);
let tax = papyr.state(8);
let discountAmount = papyr.math.mul(price, papyr.math.div(discount, 100));
let discountedPrice = papyr.math.sub(price, discountAmount);
let taxAmount = papyr.math.mul(discountedPrice, papyr.math.div(tax, 100));
let finalTotal = papyr.math.round(papyr.math.sum(discountedPrice, taxAmount), 2);
let CheckoutUI = papyr.div(
papyr.h3("🛒 Checkout Summary"),
papyr.p(() => "Price: $" + price.value),
papyr.p(() => "After Discount: $" + discountedPrice.value.toFixed(2)),
papyr.p(() => "Tax: $" + taxAmount.value.toFixed(2)),
papyr.h2(() => "Total: $" + finalTotal.value.toFixed(2))
);
💾 Multi-Engine Database
let tasks = papyr.crud("tasks", [], "local");
let sessions = papyr.crud("sessions", [], "session");
let backup = papyr.crud("backup", [], "firebase");
let offline = papyr.crud("offline", [], "sqlite");
tasks.insert({ id: 1, title: "Learn Papyr" });
tasks.update(1, { title: "Master Papyr" });
tasks.delete(1);
🎨 Premium UI Components
Cards
let card = papyr.card("Title", "Content", "Footer");
Modals
let modal = papyr.modal(
papyr.p("Are you sure?"),
"Confirm Action"
);
modal.show();
modal.hide();
Tabs
let tabs = papyr.tabs([
{ label: "Tab 1", content: papyr.p("Content 1") },
{ label: "Tab 2", content: papyr.p("Content 2") }
]);
Forms
let form = papyr.form(
papyr.input("text", "Name", { name: "name" }),
papyr.input("email", "Email", { name: "email" }),
papyr.button("Submit", { onclick: () => {} })
);
🤝 Contributing
We welcome contributions! Here's how you can help:
Areas Needing Help
- 📚 Documentation improvements
- 🐛 Bug reports and fixes
- ✨ New UI component designs
- 🚀 Performance optimizations
- 🔐 Security enhancements
- 🌍 Internationalization (i18n)
- ♿ Accessibility (a11y) improvements
Development Setup
git clone https://github.com/EldrexDelosReyesBula/Papyr.js.git
cd Papyr.js
node build.js
Code Style
- Use functional programming where possible
- Keep functions small and focused
- Add JSDoc comments for public APIs
- Follow existing naming conventions
Reporting Issues
- Use GitHub Issues for bugs
- Provide a minimal reproducible example
- Include browser and OS information
- Share error logs and stack traces
📄 File Structure
Papyr.js/
├── src/
│ ├── core/ # Core modules (reactivity, router, security, db, orm, etc.)
│ ├── plugins/ # Official plugins (ui elements, math, physics, charts, etc.)
│ └── styles/ # CSS design system complete tokens
├── build.js # Library compiler/bundler script
├── package.json # NPM metadata
├── README.md # This markdown documentation
├── CONTRIBUTING.md # Contribution guide
└── LICENSE # MIT License
🛡️ Spellcheck Debugger Warnings
Papyrus protects beginners from typos:
let myBtn = papyr.buton("Click me");
papyr.debug(true);
🔌 Namespace Harmony
Working with legacy code?
const myPapyr = papyr.noConflict();
myPapyr.mount("#app", myPapyr.div("Safe!"));
📊 Comparison with Other Frameworks
| Bundle Size | 12KB | 42KB | 34KB | 16KB |
| Learning Curve | Very Easy | Medium | Medium | Easy |
| No Build Tools | ✅ | ❌ | ❌ | ❌ |
| Direct DOM | ✅ | ❌ | ❌ | ❌ |
| Reactivity | ✅ | ✅ | ✅ | ✅ |
| Built-in Components | ✅ | ❌ | ❌ | ❌ |
| Zero Dependencies | ✅ | ❌ | ❌ | ✅ |
| Encryption Built-in | ✅ | ❌ | ❌ | ❌ |
🎓 Learning Resources
📄 License
Papyrus is released under the MIT License. See LICENSE for details.
MIT License
Copyright (c) 2026 Eldrex Delos Reyes Bula
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction...
🙏 Acknowledgments
- Inspired by Vue.js's reactivity model
- Physics engine concepts from Three.js and Babylon.js
- Security practices from OWASP guidelines
- Community feedback and contributions
⚠️ Legal Disclaimer & Liability Shield (AS-IS / Beta Status)
IMPORTANT NOTICE FOR DEVELOPERS AND ENTERPRISES:
- Beta Classification & Active Development: Papyrus.js (papyr.js) is currently in a highly active development phase (Beta status). While it is continuously optimized and tested, it may not perform as robustly or function as perfectly as modern massive web frameworks (such as React, Vue, or Next.js) that have extensive multi-year optimizations.
- "AS-IS" Distribution: The library, including all modular and complete CDN bundles, is provided completely "AS-IS" without any warranty of any kind, express or implied.
- Absence of Liability: IN NO EVENT shall the author(s), publisher, or contributors be held liable for any claim, damages, security breaches, data loss, or other liabilities, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use of the library.
- Developer Implementation Responsibility: The developer assuming integration of Papyrus.js is solely responsible for verifying the security, XSS sanitization levels, WATT storage tracking consent flows, and legal compliance of their own final applications. No liability is assumed for developer implementation errors, security misconfigurations, or operational failures of their final built apps.
- Continuous Improvements: By utilizing this library, you acknowledge its experimental/lightweight nature and agree to hold the authors completely harmless under the terms of the MIT License.
📄 License
Papyrus is released under the MIT License. See LICENSE for details.
MIT License
Copyright (c) 2026 Eldrex Delos Reyes Bula
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Papyrus v3.0.0 — Built with zero dependencies. Crafted with passion for simplicity.
Start building beautiful apps today: https://papyrus-js.vercel.app/