Dots3-Note Preview (free)
by Dots StudioReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 39.7 s
- Cost
- $0
- Output tokens
- 4,187
- Spent thinking
- 0 tokens
- Speed
- 107.3 tok/s
- Console errors
- 0
- First token after
- 673 ms
- First visible text after
- 673 ms
- Prompt tokens
- 495
- Code size
- 14.6 KB
- Finish reason
- stop
- Served by
- AtlasCloud
- Model id
dots-studio/dots-3-note-preview:free- Reasoning sent
{"effort":"none"}- Max output
- 32,000 tokens
- Generated
- Nov 9, 2026
What it was asked
The prompt
Build an interactive Kanban board in vanilla HTML, CSS and JavaScript (no framework, no library). Requirements: - Three columns: "To do", "In progress", "Done", each showing its card count. - Pre-populate the board with 6 realistic cards spread across the columns so the first screenshot looks alive. - Each card has a title and a priority (low / medium / high) shown as a colored badge. - Add a card through a small modal form (title required), and delete a card with a button on it. - Drag and drop cards between columns with the mouse, with a clear visual drop indicator. - A search field that filters cards live by title. - A light / dark theme toggle. - State lives in memory only (no storage APIs).
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task. Output rules: - Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block. - Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task. - Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw. - The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar. - Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction. - Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session. - Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing. - The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message. - The code must run with zero errors in the console of the latest Chrome.
Code run-1.html · 624 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kanban Board</title>
<style>
:root {
--bg: #f4f5f7;
--surface: #ffffff;
--text: #172b4d;
--text-secondary: #5e6c84;
--border: #dfe1e6;
--accent: #0079bf;
--shadow: rgba(0, 0, 0, 0.1);
--low: #61bd4f;
--medium: #ffab4a;
--high: #eb5a46;
}
[data-theme="dark"] {
--bg: #1d2125;
--surface: #2c3338;
--text: #e6e6e6;
--text-secondary: #9da6b0;
--border: #4a5559;
--accent: #4fa9e6;
--shadow: rgba(0, 0, 0, 0.3);
--low: #57a64f;
--medium: #e6a532;
--high: #d9484f;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: var(--bg);
color: var(--text);
min-height: 100vh;
display: flex;
flex-direction: column;
}
header {
background-color: var(--surface);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
box-shadow: 0 1px 3px var(--shadow);
flex-wrap: wrap;
gap: 1rem;
}
h1 {
font-size: 1.5rem;
font-weight: 600;
}
.controls {
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.search {
padding: 0.5rem;
border: 1px solid var(--border);
border-radius: 4px;
background-color: var(--surface);
color: var(--text);
width: 250px;
font-size: 0.9rem;
}
.theme-toggle {
background: none;
border: 1px solid var(--border);
border-radius: 4px;
padding: 0.5rem 1rem;
cursor: pointer;
color: var(--text);
background-color: var(--surface);
font-size: 0.9rem;
}
.add-btn {
background-color: var(--accent);
color: white;
border: none;
border-radius: 4px;
padding: 0.5rem 1rem;
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
}
.add-btn:hover {
opacity: 0.9;
}
main {
flex: 1;
display: flex;
gap: 1rem;
padding: 2rem;
overflow-x: auto;
}
.column {
background-color: var(--surface);
border-radius: 6px;
padding: 1rem;
width: 300px;
min-width: 300px;
display: flex;
flex-direction: column;
box-shadow: 0 1px 3px var(--shadow);
}
.column-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--border);
}
.column-title {
font-weight: 600;
font-size: 1rem;
}
.card-count {
background-color: var(--border);
color: var(--text-secondary);
border-radius: 12px;
padding: 0.1rem 0.6rem;
font-size: 0.8rem;
}
[data-theme="dark"] .card-count {
background-color: #4a5559;
}
.cards {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.75rem;
min-height: 100px;
padding: 0.5rem;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.cards.drag-over {
background-color: var(--accent);
opacity: 0.1;
}
.card {
background-color: var(--surface);
border: 1px solid var(--border);
border-radius: 4px;
padding: 0.75rem;
cursor: grab;
box-shadow: 0 1px 2px var(--shadow);
position: relative;
transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.card:hover {
transform: translateY(-1px);
box-shadow: 0 2px 4px var(--shadow);
}
.card.dragging {
opacity: 0.5;
cursor: grabbing;
}
.card-title {
font-size: 0.9rem;
margin-bottom: 0.5rem;
word-break: break-word;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.priority-badge {
font-size: 0.7rem;
padding: 0.2rem 0.5rem;
border-radius: 12px;
color: white;
font-weight: 500;
text-transform: uppercase;
}
.priority-low { background-color: var(--low); }
.priority-medium { background-color: var(--medium); }
.priority-high { background-color: var(--high); }
.delete-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 1rem;
padding: 0.2rem;
border-radius: 2px;
opacity: 0.7;
}
.delete-btn:hover {
opacity: 1;
color: var(--high);
background-color: rgba(235, 90, 70, 0.1);
}
/* Modal */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal {
background-color: var(--surface);
padding: 1.5rem;
border-radius: 6px;
width: 90%;
max-width: 400px;
box-shadow: 0 4px 12px var(--shadow);
}
.modal h2 {
margin-bottom: 1rem;
font-size: 1.2rem;
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-size: 0.9rem;
font-weight: 500;
}
.form-group input,
.form-group select {
width: 100%;
padding: 0.5rem;
border: 1px solid var(--border);
border-radius: 4px;
background-color: var(--surface);
color: var(--text);
font-size: 0.9rem;
}
.modal-buttons {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
margin-top: 1.5rem;
}
.modal-btn {
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.9rem;
}
.cancel-btn {
background-color: var(--border);
color: var(--text);
}
.save-btn {
background-color: var(--accent);
color: white;
}
.empty-state {
text-align: center;
color: var(--text-secondary);
padding: 2rem 0;
font-size: 0.9rem;
}
@media (max-width: 768px) {
main {
padding: 1rem;
gap: 0.5rem;
}
.column {
width: 280px;
min-width: 280px;
}
}
</style>
</head>
<body>
<header>
<h1>Kanban Board</h1>
<div class="controls">
<input type="text" class="search" placeholder="Search cards by title...">
<button class="theme-toggle" id="themeToggle">🌙 Dark</button>
<button class="add-btn" id="addCardBtn">+ Add Card</button>
</div>
</header>
<main>
<div class="column" data-status="todo">
<div class="column-header">
<div class="column-title">To do</div>
<div class="card-count" id="count-todo">0</div>
</div>
<div class="cards" id="todo-cards"></div>
</div>
<div class="column" data-status="inprogress">
<div class="column-header">
<div class="column-title">In progress</div>
<div class="card-count" id="count-inprogress">0</div>
</div>
<div class="cards" id="inprogress-cards"></div>
</div>
<div class="column" data-status="done">
<div class="column-header">
<div class="column-title">Done</div>
<div class="card-count" id="count-done">0</div>
</div>
<div class="cards" id="done-cards"></div>
</div>
</main>
<div class="modal-overlay" id="modalOverlay">
<div class="modal">
<h2>Add New Card</h2>
<div class="form-group">
<label for="cardTitle">Title</label>
<input type="text" id="cardTitle" placeholder="Enter card title" required>
</div>
<div class="form-group">
<label for="cardPriority">Priority</label>
<select id="cardPriority">
<option value="low">Low</option>
<option value="medium" selected>Medium</option>
<option value="high">High</option>
</select>
</div>
<div class="modal-buttons">
<button class="modal-btn cancel-btn" id="cancelBtn">Cancel</button>
<button class="modal-btn save-btn" id="saveCardBtn">Save</button>
</div>
</div>
</div>
<script>
// State
let cards = [
{ id: 1, title: "Design landing page", priority: "high", status: "todo" },
{ id: 2, title: "Write API documentation", priority: "medium", status: "inprogress" },
{ id: 3, title: "Fix login bug", priority: "high", status: "inprogress" },
{ id: 4, title: "Update user profile", priority: "low", status: "done" },
{ id: 5, title: "Implement dark mode", priority: "medium", status: "todo" },
{ id: 6, title: "Refactor authentication", priority: "high", status: "done" }
];
let nextId = 7;
let currentTheme = "light";
let draggedCardId = null;
// DOM Elements
const themeToggle = document.getElementById("themeToggle");
const addCardBtn = document.getElementById("addCardBtn");
const modalOverlay = document.getElementById("modalOverlay");
const cardTitleInput = document.getElementById("cardTitle");
const cardPrioritySelect = document.getElementById("cardPriority");
const saveCardBtn = document.getElementById("saveCardBtn");
const cancelBtn = document.getElementById("cancelBtn");
const searchInput = document.querySelector(".search");
// Initialize
document.addEventListener("DOMContentLoaded", () => {
renderBoard();
setupEventListeners();
});
// Event Listeners
function setupEventListeners() {
themeToggle.addEventListener("click", toggleTheme);
addCardBtn.addEventListener("click", openModal);
cancelBtn.addEventListener("click", closeModal);
saveCardBtn.addEventListener("click", saveCard);
searchInput.addEventListener("input", filterCards);
// Close modal on overlay click
modalOverlay.addEventListener("click", (e) => {
if (e.target === modalOverlay) {
closeModal();
}
});
// Close modal on Escape key
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && modalOverlay.style.display === "flex") {
closeModal();
}
});
}
// Render Board
function renderBoard() {
renderColumn("todo");
renderColumn("inprogress");
renderColumn("done");
updateCounts();
}
function renderColumn(status) {
const container = document.getElementById(`${status}-cards`);
container.innerHTML = "";
const filteredCards = getFilteredCards().filter(card => card.status === status);
if (filteredCards.length === 0) {
const emptyState = document.createElement("div");
emptyState.className = "empty-state";
emptyState.textContent = "No cards";
container.appendChild(emptyState);
return;
}
filteredCards.forEach(card => {
const cardElement = createCardElement(card);
container.appendChild(cardElement);
});
}
function createCardElement(card) {
const cardDiv = document.createElement("div");
cardDiv.className = "card";
cardDiv.draggable = true;
cardDiv.dataset.id = card.id;
cardDiv.innerHTML = `
<div class="card-title">${escapeHtml(card.title)}</div>
<div class="card-footer">
<span class="priority-badge priority-${card.priority}">${card.priority}</span>
<button class="delete-btn" title="Delete card">×</button>
</div>
`;
// Drag events
cardDiv.addEventListener("dragstart", handleDragStart);
cardDiv.addEventListener("dragend", handleDragEnd);
// Delete button
const deleteBtn = cardDiv.querySelector(".delete-btn");
deleteBtn.addEventListener("click", (e) => {
e.stopPropagation();
deleteCard(card.id);
});
return cardDiv;
}
// Drag and Drop
function handleDragStart(e) {
draggedCardId = parseInt(e.target.dataset.id);
e.target.classList.add("dragging");
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/html", e.target.innerHTML);
}
function handleDragEnd(e) {
e.target.classList.remove("dragging");
draggedCardId = null;
}
// Setup drop zones
document.querySelectorAll(".cards").forEach(container => {
container.addEventListener("dragover", handleDragOver);
container.addEventListener("dragleave", handleDragLeave);
container.addEventListener("drop", handleDrop);
});
function handleDragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = "move";
const container = e.currentTarget;
container.classList.add("drag-over");
}
function handleDragLeave(e) {
const container = e.currentTarget;
container.classList.remove("drag-over");
}
function handleDrop(e) {
e.preventDefault();
const container = e.currentTarget;
container.classList.remove("drag-over");
if (draggedCardId === null) return;
const newStatus = container.parentElement.dataset.status;
const card = cards.find(c => c.id === draggedCardId);
if (card && card.status !== newStatus) {
card.status = newStatus;
renderBoard();
}
}
// Modal Functions
function openModal() {
modalOverlay.style.display = "flex";
cardTitleInput.value = "";
cardPrioritySelect.value = "medium";
cardTitleInput.focus();
}
function closeModal() {
modalOverlay.style.display = "none";
}
function saveCard() {
const title = cardTitleInput.value.trim();
const priority = cardPrioritySelect.value;
if (!title) {
alert("Title is required");
cardTitleInput.focus();
return;
}
const newCard = {
id: nextId++,
title: title,
priority: priority,
status: "todo"
};
cards.push(newCard);
renderBoard();
closeModal();
}
function deleteCard(id) {
if (confirm("Are you sure you want to delete this card?")) {
cards = cards.filter(card => card.id !== id);
renderBoard();
}
}
// Search Filter
function filterCards() {
renderBoard();
}
function getFilteredCards() {
const query = searchInput.value.toLowerCase().trim();
if (!query) return cards;
return cards.filter(card =>
card.title.toLowerCase().includes(query)
);
}
// Theme Toggle
function toggleTheme() {
currentTheme = currentTheme === "light" ? "dark" : "light";
document.body.dataset.theme = currentTheme;
themeToggle.textContent = currentTheme === "light" ? "🌙 Dark" : "☀️ Light";
}
// Update Counts
function updateCounts() {
document.getElementById("count-todo").textContent =
getFilteredCards().filter(c => c.status === "todo").length;
document.getElementById("count-inprogress").textContent =
getFilteredCards().filter(c => c.status === "inprogress").length;
document.getElementById("count-done").textContent =
getFilteredCards().filter(c => c.status === "done").length;
}
// Utility
function escapeHtml(text) {
const div = document.createElement("div");
div.textContent = text;
return div.innerHTML;
}
</script>
</body>
</html>