Copy. Paste. Done.
Every snippet below is real, working HTML you can paste directly into your Django template. Each one has a live preview on the left and the exact code on the right — just copy it. Set up base.html once in the Base Setup section and every component on every page just works.
Base Setup
Add these lines to base.html once. Every component becomes available on every page automatically — no per-page imports needed.
<script> tags at the very bottom of <body>, after your content blocks. Use so child templates can add their own scripts without breaking load order.
<!DOCTYPE html> <html lang="en"> <head> <!-- Your theme --> <link rel="stylesheet" href="/static/resources/css/style.css" /> <!-- Phosphor Icons (used by list-tile, buttons) --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/phosphor-icons/2.0.2/phosphor.min.css" /> <!-- Quill.js --> <link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" /> </head> <body> <div data-barba="wrapper"> <div data-barba="container" data-barba-namespace="default"> <smart-toast position="top-right" max="5"><smart-toast position="top-right" max="5"></smart-toast> <smart-modal></smart-modal> <smart-loader type="overlay"><smart-loader type="overlay"></smart-loader> <!-- Your Content Goes here --> <!-- Your Content Ends here --> </div> </div> <smart-motion type="panel" duration="400"></smart-motion> <smart-effects auto></smart-effects> <!-- SmartComponents --> <script type="module" src="/static/resources/js/components/smart_core.js"></script> <script type="module" src="/static/resources/js/components/smart_motion.js"></script> <script type="module" src="/static/resources/js/components/smart_effect.js"></script> <script type="module" src="/static/resources/js/components/input.js"></script> <script type="module" src="/static/resources/js/components/smart_search_input.js"></script> <script type="module" src="/static/resources/js/components/smart_button.js"></script> <script type="module" src="/static/resources/js/components/button.js"></script> <script type="module" src="/static/resources/js/components/smart_list_tile.js"></script> <script type="module" src="/static/resources/js/components/rich_text_input.js"></script> <script type="module" src="/static/resources/js/components/smart_table.js"></script> <script type="module" src="/static/resources/js/components/smart_image.js"></script> <script type="module" src="/static/resources/js/components/smart_form.js"></script> <script type="module" src="/static/resources/js/components/smart_permission.js"></script> <script type="module" src="/static/resources/js/components/smart_chart.js"></script> <!-- Quill.js (For SmartQuill) --> <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script> <!-- Chart.js and ApexCharts (For SmartChart) --> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> </body> </html>
SmartInput
One tag covers all input types. Validation, labels, and error states are built-in — no JS needed.
<smart-input type="text" name="full_name" label="Full Name" placeholder="John Doe" required ></smart-input> <smart-input type="email" name="email" label="Email" placeholder="you@example.com" required ></smart-input> <smart-input type="password" name="password" label="Password" placeholder="Min 8 characters" required ></smart-input> <!-- Also works: type="number" "tel" "url" --> <smart-input type="number" name="age" label="Age" placeholder="25" ></smart-input>
<!-- Static options --> <smart-input type="select" name="status" label="Status" value="pending" data-onchange="handleStatusChange" data-options='[ {"id":"pending", "name":"Pending"}, {"id":"active", "name":"Active"}, {"id":"inactive", "name":"Inactive"} ]' required ></smart-input> <!-- Multi-select --> <smart-input type="select" name="tags" label="Tags" multiple data-options='[ {"id":"django","name":"Django"}, {"id":"python","name":"Python"} ]' ></smart-input> <!-- Load options from API endpoint --> <smart-input type="select" name="user" label="Assign User" data-url="/api/users/" required ></smart-input> <script> function handleStatusChange(event) { console.log('Status:', event.target.value); } </script>
<!-- Datepicker with min / max --> <smart-input type="datepicker" name="birthdate" label="Birth Date" value="15-08-2000" min-date="01-01-1970" max-date="31-12-2010" ></smart-input> <!-- File — allowed-types: documents images videos spreadsheets archives audio --> <smart-input type="file" name="documents" label="Upload Documents" allowed-types="documents" max-size="5" max-files="3" ></smart-input> <!-- Images up to 10 MB, up to 5 files --> <smart-input type="file" name="images" label="Upload Images" allowed-types="images" max-size="10" max-files="5" ></smart-input> <!-- Textarea --> <smart-input type="textarea" name="message" label="Message" rows="4" placeholder="Write here..." required ></smart-input>
<!-- Checkbox --> <smart-input type="checkbox" name="agree" label="I agree to the terms" value="true" required ></smart-input> <!-- Switch (is-big = large toggle) --> <smart-input type="switch" name="notifications" label="Enable Notifications" value="true" is-big ></smart-input> <!-- Radio group --> <smart-input type="radio" name="priority" label="Priority" value="medium" data-options='[ {"id":"low", "name":"Low"}, {"id":"medium", "name":"Medium"}, {"id":"high", "name":"High"} ]' required ></smart-input>
SmartSearchInput
Type-to-search with AJAX, debounce, badge display, and keyboard nav. Point search-url at any endpoint returning [{id, name}].
Type 2+ chars to search books
<smart-search-input label="Assign Lessons" placeholder="Search and add lessons..." search-url="/api/lessons/" input-name="lesson_ids" min-chars="2" max-results="8" badge-variant="secondary" show-badges allow-remove data-onselect="onItemSelect" data-onremove="onItemRemove" ></smart-search-input> # Django: endpoint returns flat array def search_lessons(request): q = request.GET.get('q', '') qs = Lesson.objects.filter( name__icontains=q ).values('id', 'name')[:10] return JsonResponse(list(qs), safe=False) <script> function onItemSelect(item, all) { console.log('Added:', item.name); } function onItemRemove(item, all) { console.log('Removed:', item.name); } </script>
<smart-search-input label="Team Members" placeholder="Search to add more..." search-url="/api/users/" input-name="member_ids" badge-variant="primary" show-badges allow-remove allow-edit edit-url-template="/admin/users/{id}/" pre-selected='' ></smart-search-input> <!-- Read IDs back via public API --> <script> const el = document.querySelector( 'smart-search-input' ); console.log(el.getSelectedIds()); // → ["1", "2"] </script>
Type 1+ char — filters local array
<smart-search-input label="Skills" placeholder="Type to filter..." input-name="skill_ids" min-chars="1" badge-variant="success" show-badges allow-remove data-onsearch="localSkillSearch" ></smart-search-input> <script> // Return [{id, name}] — sync or async const SKILLS = [ {id:1,name:"Python"}, {id:2,name:"Django"}, {id:3,name:"JavaScript"}, {id:4,name:"React"}, {id:5,name:"PostgreSQL"}, {id:6,name:"Docker"}, ]; function localSkillSearch(query) { return SKILLS.filter(s => s.name.toLowerCase() .includes(query.toLowerCase()) ); } </script>
SmartQuill
Rich text editor with form integration. The HTML output lands in a hidden input — works with any Django view.
<form id="article-form"> <smart-quill name="body" label="Article Body" placeholder="Write your content..." required ></smart-quill> <custom-button label="Publish Article" form-id="article-form" post="/api/articles/" buttontype="success" showspinner="true" ></custom-button> </form> # Django: request.POST['body'] # → "<p>Hello <strong>world</strong></p>"
CustomButton & SmartButton
AJAX-powered buttons. Every behaviour — spinner, confirm modal, toast — is just an attribute.
<!-- AJAX submit with spinner --> <custom-button label="Save Changes" form-id="my-form" post="/api/save/" buttontype="success" showspinner="true" ></custom-button> <!-- Delete with styled confirm modal --> <custom-button label="Delete Record" post="/api/items//delete/" buttontype="danger" confirm-title="Delete this record?" confirm-message="This cannot be undone." ></custom-button> <!-- Info / export style --> <custom-button label="Export Data" post="/api/export/" buttontype="info" showspinner="true" ></custom-button>
<!-- Icon-only button (uses Phosphor icons) --> <smart-button icon="floppy-disk" form-id="my-form" post="/api/save/" text="Save" showspinner="true" buttontype="primary" ></smart-button> <smart-button icon="pencil" post="/api/edit//" text="Edit" buttontype="secondary" ></smart-button> <smart-button icon="trash" post="/api/delete//" text="Delete" buttontype="danger" ></smart-button>
SmartListTile
Sidebar nav, step wizards, menu lists. Click any tile below — the active state switches live.
<!-- active tile --> <smart-list-tile id="tile-dashboard" leading-icon="ph ph-house" title="Dashboard" subtitle="Overview & analytics" active clickable trailing-icon="ph ph-caret-right" onclick="activateTile('tile-dashboard')" ></smart-list-tile> <!-- regular tile --> <smart-list-tile id="tile-users" leading-icon="ph ph-users" title="Users" subtitle="Manage team" clickable trailing-icon="ph ph-caret-right" onclick="activateTile('tile-users')" ></smart-list-tile> <!-- disabled tile --> <smart-list-tile leading-icon="ph ph-lock" title="Billing" subtitle="Upgrade to access" disabled trailing-icon="ph ph-lock-simple" ></smart-list-tile> <!-- Active-state switcher JS --> <script> function activateTile(id) { document.querySelectorAll('smart-list-tile') .forEach(t => t.removeAttribute('active')); document.getElementById(id) .setAttribute('active', ''); } </script>
SmartImage
Lazy load with skeleton. Every visual feature is a boolean attribute — hover-zoom, lightbox, fallback, rounded, circle.
<!-- Shimmer + hover-zoom + click lightbox --> <smart-image src="" width="300" height="200" animation-type="shimmer" rounded hover-zoom click-preview caption="" ></smart-image> <!-- Fluid 16:9 banner --> <smart-image src="" aspect-ratio="16/9" style="width:100%" fit="cover" rounded ></smart-image>
<!-- Circle avatar with spinner skeleton --> <smart-image src="" width="60" height="60" animation-type="spinner" circle ></smart-image> <!-- Fallback shown if src fails to load --> <smart-image src="" fallback-src="/static/img/placeholder.jpg" width="300" height="200" rounded ></smart-image>
SmartTable
A full sortable, searchable, paginated data table from one tag. Delete rows with one attribute. Zero JS required.
<!-- Minimal: auto-detect columns --> <smart-table api-url="/api/users/" response-map='{"dataPath":"","totalPath":""}' page-size="10" hide-id ></smart-table> <!-- Custom columns + badge type + delete --> <smart-table api-url="/api/users/" response-map='{"dataPath":"results", "totalPath":"count"}' columns='[ {"field":"name", "label":"Name"}, {"field":"email", "label":"Email"}, {"field":"status", "label":"Status", "type":"badge"} ]' delete-api-url="/api/users" page-size="20" ></smart-table> # Django DRF view (paginated response) class UserListView(ListAPIView): def list(self, request): qs = User.objects.all() return Response({ "results": UserSerializer( qs, many=True ).data, "count": qs.count() })
Full Copy-Paste Template
A complete Django template block with every component wired up. Replace the dummy URLs, option arrays, and with your own data.
base.html already imports all component scripts as shown in Base Setup. Only the HTML block and page-level JS are here.
<form id="main-form"> <smart-input type="text" name="name" label="Full Name" required></smart-input> <smart-input type="email" name="email" label="Email" required></smart-input> <smart-input type="password" name="password" label="Password" required></smart-input> <smart-input type="select" name="status" label="Status" data-options='[{"id":"active","name":"Active"},{"id":"inactive","name":"Inactive"}]' required ></smart-input> <smart-input type="datepicker" name="due_date" label="Due Date"></smart-input> <smart-input type="file" name="docs" label="Documents" allowed-types="documents" max-size="5" max-files="3" ></smart-input> <smart-quill name="description" label="Description" required></smart-quill> <smart-input type="switch" name="notify" label="Send notifications" is-big></smart-input> <smart-search-input label="Assigned Users" placeholder="Search users..." search-url="/api/users/" input-name="user_ids" badge-variant="primary" show-badges allow-remove pre-selected='' ></smart-search-input> <custom-button label="Save" form-id="main-form" post="/api/save/" buttontype="success" showspinner="true" ></custom-button> <custom-button label="Delete" post="/api/items//delete/" buttontype="danger" confirm-title="Delete this item?" confirm-message="This cannot be undone." ></custom-button> </form> <!-- Data table --> <smart-table api-url="/api/users/" response-map='{"dataPath":"results","totalPath":"count"}' columns='[ {"field":"name", "label":"Name"}, {"field":"email", "label":"Email"}, {"field":"status", "label":"Status","type":"badge"} ]' delete-api-url="/api/users" page-size="20" ></smart-table> <!-- Image with fallback --> <smart-image src="" fallback-src="/static/img/placeholder.jpg" width="300" height="200" rounded hover-zoom click-preview ></smart-image> <script> // Read selected IDs from smart-search-input document.getElementById('main-form') .addEventListener('submit', () => { const s = document.querySelector('smart-search-input'); console.log('User IDs:', s.getSelectedIds()); }); </script>