AI Suite #
A complete set of UI patterns for building AI-powered features. Drop-in markup for chat interfaces, image generation, content writing, prompt management, and usage analytics.
Frontend only
Admindek's AI Suite ships frontend markup and styles only — wire up your own backend (OpenAI, Anthropic, self-hosted, mock) by replacing the placeholder fetch calls. The page-level JavaScript is structured so you can plug in any provider with minimal changes.
Page catalog #
| Page | File | Purpose |
|---|---|---|
| AI Chat | application/ai-chat.html | Conversation interface with message bubbles |
| AI Image Generator | application/ai-image.html | Prompt → image with results gallery |
| AI Content Writer | application/ai-writer.html | Long-form generation with templates |
| AI Dashboard | application/ai-dashboard.html | Usage metrics and cost tracking |
| Prompt Library | application/ai-prompts.html | Categorized prompt templates |
AI Chat #
A conversation interface modeled on ChatGPT and Claude — sidebar of past conversations, message thread, input area.
File: src/html/application/ai-chat.html
Features #
- Conversation sidebar — list of past chats grouped by Today / Yesterday / Last 7 days / Older
- Search for past conversations
- New chat button
- Message thread with user vs. assistant bubbles
- Code blocks with copy button (Prism.js syntax highlighting)
- Markdown rendering in assistant responses
- Streaming response support — append-to-bubble pattern ready
- Regenerate / edit controls on user messages
- Stop generation button while streaming
- Mobile: sidebar collapses, hamburger toggle
Markup snippet #
<div class="ai-chat-wrapper">
<aside class="ai-chat-sidebar" id="ai-chat-sidebar">
<button class="btn btn-primary w-100" id="ai-new-chat">
<i class="ti ti-plus"></i> New Chat
</button>
<div class="input-group input-group-sm">
<span class="input-group-text"><i class="ti ti-search"></i></span>
<input type="text" class="form-control" placeholder="Search conversations…" />
</div>
<div class="flex-grow-1 overflow-auto">
<small class="text-muted text-uppercase">Today</small>
<ul class="ai-conversation-list">
<li class="ai-conversation-item active">
<i class="ti ti-message"></i>
<div>
<div class="text-truncate">REST API with Express.js</div>
<small class="text-muted">2 min ago</small>
</div>
</li>
</ul>
</div>
</aside>
<main class="ai-chat-main">
<div class="ai-chat-messages" id="ai-messages">
<div class="ai-message ai-message-user">
<div class="ai-message-avatar">JD</div>
<div class="ai-message-bubble">How do I set up an Express server?</div>
</div>
<div class="ai-message ai-message-assistant">
<div class="ai-message-avatar"><i class="ti ti-sparkles"></i></div>
<div class="ai-message-bubble">
<p>Here's a minimal Express setup:</p>
<pre><code class="language-javascript">const express = require('express')
const app = express()
app.listen(3000)</code></pre>
</div>
</div>
</div>
<div class="ai-chat-input">
<textarea placeholder="Send a message…" rows="1"></textarea>
<button class="btn btn-primary"><i class="ti ti-send"></i></button>
</div>
</main>
</div>Wiring up a backend #
Replace the demo handler in ai-chat.js with your fetch / SSE call:
async function sendMessage(text) {
appendMessage('user', text)
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: text, conversationId: currentId }),
})
// For streaming, use ReadableStream
const reader = response.body.getReader()
const decoder = new TextDecoder()
const bubble = appendMessage('assistant', '')
while (true) {
const { value, done } = await reader.read()
if (done) break
bubble.textContent += decoder.decode(value)
}
}AI Image Generator #
Prompt-based image generation with a results grid and history.
File: src/html/application/ai-image.html
Features #
- Prompt input with character counter and prompt-enhancement suggestions
- Style presets: Photorealistic, Anime, Sketch, Watercolor, 3D Render, Pixel Art
- Aspect ratio selector: 1:1, 16:9, 9:16, 4:3, 3:2
- Quality / step controls
- Negative prompt input (advanced)
- Results gallery with hover actions: Download, Copy URL, Variations, Use as base
- History panel of past generations
- Lightbox preview (GLightbox)
Layout #
<div class="ai-image-wrapper row g-3">
<aside class="col-lg-4 ai-image-controls">
<div class="card">
<div class="card-body">
<label class="form-label">Prompt</label>
<textarea class="form-control" rows="4" placeholder="A serene lake at sunset…"></textarea>
<label class="form-label mt-3">Style</label>
<div class="ai-style-presets">
<button class="ai-style-preset active">Photorealistic</button>
<button class="ai-style-preset">Anime</button>
<button class="ai-style-preset">3D Render</button>
</div>
<label class="form-label mt-3">Aspect ratio</label>
<div class="btn-group w-100">
<input type="radio" name="ratio" id="r-1-1" checked /><label for="r-1-1" class="btn btn-outline-secondary">1:1</label>
<input type="radio" name="ratio" id="r-16-9" /><label for="r-16-9" class="btn btn-outline-secondary">16:9</label>
</div>
<button class="btn btn-primary w-100 mt-3">
<i class="ti ti-sparkles"></i> Generate
</button>
</div>
</div>
</aside>
<main class="col-lg-8 ai-image-results">
<div class="row g-2">
<div class="col-6">
<a href="/generated/1.jpg" class="glightbox ai-image-result">
<img src="/generated/1.jpg" alt="" />
<div class="ai-image-actions">
<button title="Download"><i class="ti ti-download"></i></button>
<button title="Variations"><i class="ti ti-refresh"></i></button>
</div>
</a>
</div>
</div>
</main>
</div>AI Content Writer #
Long-form text generation with template prompts and inline editing.
File: src/html/application/ai-writer.html
Features #
- Template gallery — Blog post, Email, Product description, Social caption, Landing page, Code docs
- Template form with structured inputs (e.g., for Blog: topic, tone, target length, audience)
- Quill rich text editor for the generated output
- Inline regenerate — select text and click "Regenerate" to rewrite just that section
- Tone adjuster — Friendly / Formal / Confident / Casual
- Length adjuster — Shorter / Same / Longer
- Export — Markdown, HTML, PDF, DOCX
<div class="ai-writer row g-3">
<aside class="col-lg-4">
<div class="card">
<div class="card-body">
<h6>Templates</h6>
<ul class="list-unstyled ai-writer-templates">
<li class="ai-template active"><i class="ti ti-article"></i> Blog post</li>
<li class="ai-template"><i class="ti ti-mail"></i> Email</li>
<li class="ai-template"><i class="ti ti-shopping-bag"></i> Product description</li>
<li class="ai-template"><i class="ti ti-brand-twitter"></i> Social caption</li>
</ul>
<hr />
<form class="ai-template-form">
<label class="form-label">Topic</label>
<input type="text" class="form-control" />
<label class="form-label mt-3">Tone</label>
<select class="form-select">
<option>Friendly</option>
<option>Formal</option>
<option>Confident</option>
</select>
<label class="form-label mt-3">Length</label>
<input type="range" class="form-range" min="300" max="2000" step="100" />
<button class="btn btn-primary w-100 mt-3">Generate</button>
</form>
</div>
</div>
</aside>
<main class="col-lg-8">
<div class="card">
<div class="card-header d-flex justify-content-between">
<h6 class="mb-0">Editor</h6>
<div class="btn-group">
<button class="btn btn-sm btn-outline-secondary"><i class="ti ti-refresh"></i> Regenerate</button>
<button class="btn btn-sm btn-outline-secondary"><i class="ti ti-download"></i> Export</button>
</div>
</div>
<div class="card-body">
<div id="ai-writer-editor"></div>
</div>
</div>
</main>
</div>import Quill from 'quill'
new Quill('#ai-writer-editor', {
theme: 'snow',
placeholder: 'Generated content will appear here…',
})AI Dashboard #
Usage analytics for AI features — tokens consumed, cost, latency, model breakdown.
File: src/html/application/ai-dashboard.html
Widgets #
- Total spend (this month) with month-over-month delta
- Tokens consumed — input vs. output split
- Active users — users who used AI features in the period
- P95 latency per model
- Cost by model — donut chart (GPT-4, GPT-3.5, Claude, etc.)
- Tokens over time — area chart
- Top users — table with consumption ranking
- Error rate — line chart of failed completions
- Recent generations — activity feed
Same widget primitives as the main dashboards — KPI cards, ApexCharts, DataTables.
Prompt Library #
Searchable, taggable prompt templates organized by use case.
File: src/html/application/ai-prompts.html
Features #
- Category sidebar: Writing, Coding, Marketing, Research, Customer support, Translation, etc.
- Search bar with full-text search across prompt titles and bodies
- Tag filter — filter by tags (multi-select)
- Sort: Most used, Recently added, Alphabetical, Rating
- Prompt card with title, category, tags, copy button, "Use this prompt" button
- Prompt detail modal — full prompt body, variables (
{{topic}},{{audience}}), example outputs - Variables form — when "Use this prompt" is clicked, fill in
{{variables}}then send to AI Chat or Writer - Personal vs. team library — toggle between your saved prompts and your team's shared library
- Add prompt — form to save your own prompts with title, body, category, tags, variables
Markup #
<div class="ai-prompts-wrapper row g-3">
<aside class="col-lg-3">
<div class="card">
<div class="card-body">
<h6>Categories</h6>
<ul class="list-unstyled ai-prompt-categories">
<li class="active">All <span class="badge bg-light text-dark ms-auto">128</span></li>
<li>Writing <span class="badge">42</span></li>
<li>Coding <span class="badge">31</span></li>
<li>Marketing <span class="badge">19</span></li>
</ul>
</div>
</div>
</aside>
<main class="col-lg-9">
<div class="d-flex gap-2 mb-3">
<input type="search" class="form-control" placeholder="Search prompts…" />
<select class="form-select w-auto">
<option>Most used</option>
<option>Recent</option>
<option>Alphabetical</option>
</select>
</div>
<div class="row g-3">
<div class="col-md-6 col-xl-4">
<article class="ai-prompt-card">
<div class="d-flex justify-content-between align-items-start mb-2">
<span class="badge bg-info">Writing</span>
<button class="btn btn-sm btn-link" title="Copy"><i class="ti ti-copy"></i></button>
</div>
<h6 class="ai-prompt-title">Blog post outline</h6>
<p class="ai-prompt-preview text-muted small">
Create a detailed outline for a blog post about {{topic}}…
</p>
<div class="ai-prompt-tags">
<span class="badge">blog</span>
<span class="badge">seo</span>
</div>
<button class="btn btn-primary btn-sm w-100 mt-3">Use this prompt</button>
</article>
</div>
</div>
</main>
</div>Wiring it all together #
The AI Suite pages are designed to share state. A common pattern:
- User browses Prompt Library → clicks "Use this prompt"
- Variables form opens (modal or sidebar) → user fills in
{{topic}},{{audience}} - User picks a destination: AI Chat or AI Content Writer
- The selected page loads with the prompt prefilled
You can implement this with a shared client-side store (localStorage, Zustand, or a vanilla JS event bus) — the markup is independent.
See also #
- Applications — Email, File Manager, Chat, Calendar, etc.
- Dashboard Widgets — Reusable widget primitives (KPI cards, charts) used in AI Dashboard
- What's new in 3.4 — Release notes for the AI Suite