@kaiserofthenight/human-js
v1.0.1
Published
A framework built for humans, not machines. Zero dependencies, zero build tools, 100% readable.
Maintainers
Readme
🦉 HumanJS Framework
A framework built for humans, not machines.
Simple. Readable. Easy to extend. Zero magic. No build tools required.
🌟 Philosophy
HumanJS prioritizes human understanding over machine optimization.
Core Principles
- Zero Magic - Every behavior is traceable in ~200 lines of code
- Human-First API - Read like English sentences
- Minimal Abstractions - Use native DOM APIs when possible
- Easy to Extend - Modify the source, don't fight it
- No Heavy Dependencies - Pure JavaScript (ES6+), browser APIs only
🚀 Quick Start
1. Clone or Download
git clone https://github.com/kaiserofthenight/humanjs.git
cd humanjs2. Open in Browser
# No build step required!
# Just open index.html in your browser
open index.html3. Your First App
import { app, html } from './src/index.js';
app.create({
state: { count: 0 },
render: (state) => {
const element = html`
<div style="padding: 40px; text-align: center;">
<h1>Count: ${state.count}</h1>
<button id="increment">+1</button>
</div>
`;
const events = {
'#increment': {
click: () => state.count += 1
}
};
return { element, events };
}
});That's it! No compilation, no bundling, no configuration.
📚 Core Concepts
1. Reactive State
import { createState } from './src/index.js';
const state = createState({ count: 0 }, (prop, value) => {
console.log(`${prop} changed to ${value}`);
});
state.count = 5; // Triggers callbackAdvanced state features:
// Watch specific properties
state.$watch('count', (newVal, oldVal) => {
console.log(`Count: ${oldVal} → ${newVal}`);
});
// Computed properties
state.$computed('double', function() {
return this.count * 2;
});
// Reset state
state.$reset({ count: 0 });
// Get raw state
const raw = state.$raw();2. HTML Rendering
import { html } from './src/index.js';
// Simple
const greeting = html`<h1>Hello, World!</h1>`;
// With dynamic values
const count = 5;
const counter = html`<div>Count: ${count}</div>`;
// With arrays
const items = ['Apple', 'Banana', 'Orange'];
const list = html`
<ul>
${items.map(item => html`<li>${item}</li>`)}
</ul>
`;Conditional rendering:
import { when } from './src/index.js';
when(
user.isLoggedIn,
() => html`<div>Welcome, ${user.name}!</div>`,
() => html`<div>Please log in</div>`
);List rendering:
import { each } from './src/index.js';
each(users, (user) => html`
<div class="user-card">
<h3>${user.name}</h3>
<p>${user.email}</p>
</div>
`);3. Components
import { app, html } from './src/index.js';
app.create({
// Where to mount
root: document.getElementById('app'),
// Initial state
state: {
count: 0,
user: { name: 'John' }
},
// Render function
render: (state) => {
const element = html`<div>${state.count}</div>`;
const events = {
'#btn': { click: () => state.count++ }
};
return { element, events };
},
// Lifecycle hooks
onMount: (state) => {
console.log('Component mounted!');
},
onUpdate: (state) => {
console.log('State updated!');
},
onDestroy: (state) => {
console.log('Component destroyed!');
}
});4. Event Handling
// Basic events
const events = {
'#button': {
click: () => console.log('Clicked!'),
mouseover: () => console.log('Hovered!')
},
'#input': {
input: (e) => state.value = e.target.value,
focus: () => console.log('Focused!')
}
};
// Form submission
'#form': {
submit: (e) => {
e.preventDefault();
const data = getFormData(e.target);
console.log(data);
}
}Event helpers:
import { on, debounce, throttle } from './src/index.js';
// Debounce search input
const handleSearch = debounce((e) => {
state.query = e.target.value;
}, 300);
// Throttle scroll events
const handleScroll = throttle(() => {
console.log('Scrolling...');
}, 100);5. Routing
import { createRouter, Link } from './src/index.js';
const router = createRouter({
'/': () => html`<h1>Home Page</h1>`,
'/about': () => html`<h1>About Page</h1>`,
'/user/:id': (params) => html`<h1>User ${params.id}</h1>`,
'*': () => html`<h1>404 - Not Found</h1>`
}, {
beforeEach: (to, from, params) => {
console.log(`Navigating from ${from} to ${to}`);
},
afterEach: (to, from, params) => {
console.log(`Navigated to ${to}`);
}
});
// Navigate programmatically
router.navigate('/about');
// Create links
const link = Link('/about', 'About Us', 'nav-link');🔌 Plugins
Form Validation
import { createValidator, rules, displayErrors } from './src/plugins/validator.js';
const validator = createValidator({
email: [rules.required, rules.email],
password: [rules.required, rules.minLength(8)],
age: [rules.required, rules.number, rules.min(18)],
confirmPassword: [rules.required, rules.match('password', 'Password')]
});
const result = validator.validate(formData);
if (!result.isValid) {
displayErrors(formElement, result.errors);
} else {
// Submit form
}Available rules:
required- Field must have a valueemail- Valid email formatminLength(n)- Minimum lengthmaxLength(n)- Maximum lengthmin(n)- Minimum numeric valuemax(n)- Maximum numeric valuepattern(regex, msg)- Custom regexurl- Valid URLnumber- Numeric valueinteger- Integer valuematch(field, name)- Match another fieldcustom(fn, msg)- Custom validation
HTTP Client
import { createHttp, http } from './src/plugins/http.js';
// Use default instance
const { data } = await http.get('/api/users');
await http.post('/api/users', { name: 'John' });
await http.put('/api/users/1', { name: 'Jane' });
await http.delete('/api/users/1');
// Custom instance
const api = createHttp({
baseURL: 'https://api.example.com',
headers: { 'Authorization': 'Bearer token' },
timeout: 10000,
onRequest: (config) => {
console.log('Request:', config);
},
onResponse: (response) => {
console.log('Response:', response);
},
onError: (error) => {
console.error('Error:', error);
}
});
const users = await api.get('/users');Storage
import { local, session, createNamespace } from './src/plugins/storage.js';
// LocalStorage (persists)
local.set('user', { name: 'John', age: 30 });
const user = local.get('user');
local.remove('user');
local.clear();
// SessionStorage (cleared on close)
session.set('token', 'abc123');
const token = session.get('token');
// Namespaced storage
const appStorage = createNamespace('myapp');
appStorage.local.set('settings', { theme: 'dark' });🛠️ Utilities
import { helpers } from './src/index.js';
// Generate unique ID
const id = helpers.uid('todo'); // 'todo_1234567890_abc'
// Deep clone
const copy = helpers.clone(originalObject);
// Deep merge
const merged = helpers.merge(obj1, obj2, obj3);
// Format date
const formatted = helpers.formatDate(new Date(), 'YYYY-MM-DD HH:mm');
// Sleep/delay
await helpers.sleep(1000); // Wait 1 second
// String utilities
helpers.capitalize('hello'); // 'Hello'
helpers.truncate('Long text...', 10); // 'Long text...'
// Array utilities
helpers.shuffle([1, 2, 3, 4, 5]);
helpers.unique([1, 2, 2, 3, 3]); // [1, 2, 3]
helpers.groupBy(users, 'role');
// Object utilities
helpers.get(obj, 'user.address.city', 'Unknown');
helpers.set(obj, 'user.name', 'John');
helpers.pick(obj, ['name', 'email']);
helpers.omit(obj, ['password', 'token']);
// Async utilities
await helpers.waitFor(() => element.isReady, 5000);
await helpers.retry(() => fetchData(), 3, 1000);📦 Project Structure
humanjs-framework/
├── index.html # Demo page
├── README.md # This file
│
├── src/ # Framework source
│ ├── core/ # Core modules
│ │ ├── state.js # Reactive state
│ │ ├── render.js # HTML rendering
│ │ ├── component.js # Components
│ │ ├── router.js # SPA routing
│ │ └── events.js # Event handling
│ │
│ ├── plugins/ # Optional plugins
│ │ ├── validator.js # Form validation
│ │ ├── http.js # HTTP client
│ │ └── storage.js # Storage wrapper
│ │
│ ├── utils/ # Utilities
│ │ └── helpers.js # Helper functions
│ │
│ └── index.js # Main entry point
│
└── examples/ # Example apps
├── todo-app/
│ └── app.js
└── api-example/
└── app.js🎓 Examples
Todo App
A complete todo application with:
- Add, edit, delete todos
- Mark as complete
- Filter (all, active, completed)
- LocalStorage persistence
- Form validation
API Integration
Demonstrates API usage with:
- Fetch users from API
- Loading states
- Error handling
- Search and filter
- Debounced input
🆚 Comparison with Other Frameworks
vs React
| Feature | HumanJS | React | |---------|---------|-------| | Learning curve | 1 day | 1-2 weeks | | Setup | Open HTML file | Complex build setup | | Bundle size | ~5KB | ~40KB (min) | | Abstraction | Minimal | Heavy (JSX, virtual DOM) | | Debugging | Trace in source | Complex stack traces |
vs Vue
| Feature | HumanJS | Vue | |---------|---------|-----| | Template syntax | Native HTML | Custom directives | | Reactivity | Proxy (native) | Proxy + compiler | | Components | Functions | Classes/objects | | Build step | None | Required for SFC |
vs Svelte
| Feature | HumanJS | Svelte | |---------|---------|--------| | Compilation | None | Required | | Runtime size | ~5KB | ~2KB | | Learning curve | 1 day | 3-4 days | | Debugging | Browser native | Compiled output |
When to use HumanJS
✅ Use when:
- Building simple to medium apps
- Learning frontend concepts
- Prototyping quickly
- Want full control
- No build step desired
❌ Don't use when:
- Building complex enterprise apps
- Need large ecosystem
- Team requires specific framework experience
- Need SSR or mobile apps
🔮 Future Improvements
Optional Enhancements
- Virtual DOM - For better performance
- TypeScript - Type definitions
- SSR Support - Server-side rendering
- Dev Tools - Browser extension
- Plugin System - Third-party plugins
- CLI Tool - Project scaffolding
How to Extend
The framework is designed to be modified:
- Fork the repository
- Modify
src/files directly - Add new plugins in
src/plugins/ - Share your improvements!
License
MIT License - do whatever you want with it!
Contributing
Contributions welcome! Please:
- Keep it simple
- Maintain readability
- Add tests for new features
- Update documentation
Support
- 📧 Email: [email protected]
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
- ⭐ Star us on GitHub!
Remember: Frameworks are tools, not religions. Use what makes you productive! 🚀
