A lightweight, declarative frontend framework that brings server-driven interactivity to HTML with minimal JavaScript. Slim lets you build dynamic web applications using simple HTML attributes.
appear eventsInclude Slim in your HTML:
<script src="https://github.com/Markonis/slim/raw/1.23.0/slim.min.js"></script>
Add interactive behavior with attributes:
<button s-get="/api/data" s-target="#result">Load Data</button>
s-get="/path" - GET requests-post="/path" - POST requests-put="/path" - PUT requests-delete="/path" - DELETE requestForm data becomes query params for GET, FormData body for others. File uploads supported.
s-on="event" - Listen for an events-on="event1 | event2" - Multiple listenerss-on="click on .selector" - Event delegations-target="#selector" - Update matched elements (default: self)S-Target: selector headers-emit="event-name" - Broadcast custom events-emit="event after 1.5s" - Delayed events-debounce="300" - Debounce the action by 300mss-debounce="0.5s" - Debounce using seconds notationWhen an element has s-debounce, rapid events are collapsed — the action fires only after the element goes quiet for the specified duration. Useful for search inputs and live filters.
s-eval="javascript code" - Execute JavaScript (with this = element)s-template="#selector" - Use the innerHTML of the templates-push="/path" - Push URL to browser history on events-confirm="message" - Confirmation dialogs-query="key=value" - Add query parameterss-ws="/websocket" - WebSocket URLs-drag-json="{...}" - JSON data on dragstarts-drag-effect="copy" - Drag effect (copy, move, link)s-drop-effect="copy" - Drop effect (enables dragover)s-drop-class="active" - Class added during dragover<button s-get="/api/count">Get Count</button>
<form s-post="/api/users">
<input name="name" required>
<button type="submit">Create</button>
</form>
<button s-emit="refresh">Refresh</button>
<body s-query="v=1">
<button s-get="/api/data">
</button>
</body>
<body s-ws="/ws">
</body>
<button class="item">Item 1</button>
<button class="item">Item 2</button>
<button s-confirm="Delete?" s-delete="/api/item"></button>
<button s-eval="console.log('Button clicked!', this)">Log</button>
<button s-eval="this.style.color = 'red'" s-get="/api/data">Update and Log</button>
<input s-on="input" s-debounce="300" s-get="/api/search" s-target="#results">
<template id="card-template">
<h3>New Card</h3>
Card content here
</template>
<button s-template="#card-template" s-target="#container">Add Card</button>
<button s-push="/dashboard">Go to Dashboard</button>
<button s-get="/api/data" s-push="/data-view">Load Data</button>
<form s-post="/api/submit" s-push="/success">
<input name="item" required>
<button type="submit">Submit</button>
</form>
Elements trigger requests automatically when s-on is not specified:
<form> → submit<button> → click<input type="text">, <select> → change (also input)appearEvery request sent by Slim includes:
S-Location - The URL of the current page (for server context/analytics)S-Target: selector - Override update targetS-Emit: event-name - Broadcast event after updateS-Push: /path - Push URL to browser historyS-Refresh: true - Reload pageS-Redirect: /path - Redirect to URLtext/html - Sets target's innerHTMLtext/plain - Sets target's textContentSlim dispatches on request elements:
slim:ok - Request succeededslim:error - Request failedslim:done - Request completedGlobal events:
location:change - URL pushed / poped from browser historyhash:change - Location hash changeds-query attributes (hierarchical)s-drag-json)Parameters cascade from ancestors:
<body s-query="org=acme">
</body>
<button>, <form>)slim:errors-confirm for destructive actionsRequires:
- ES6+ JavaScript
- Fetch API
- Custom Events
- Intersection Observer
- WebSockets (for s-ws)
MIT