Notes
Gemma 4 31b it · middle

Reviews & generation details
Reviews
No human review yet. Unreviewed does not mean unsuccessful.
Generation context
Imported historical artifact. Its exact original instructions and lineage are not known.
Generation prompt · exact text unavailable
See the current prompt for reference. It may differ from the instructions used to generate this artifact.
Inspect original source 21,798 bytes · SHA-256 bf5b44601a3f
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ZenNotes | Modern Knowledge Base</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono&display=swap');
:root {
--sidebar-bg: #f9fafb;
--active-note-bg: #eff6ff;
--accent-color: #3b82f6;
}
body {
font-family: 'Inter', sans-serif;
overflow: hidden;
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #e5e7eb;
border-radius: 10px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #d1d5db;
}
.editor-content:focus {
outline: none;
}
.note-item.active {
background-color: var(--active-note-bg);
border-left: 4px solid var(--accent-color);
}
.transition-all-custom {
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
</style>
</head>
<body class="bg-white text-slate-800">
<div class="flex h-screen w-full overflow-hidden">
<!-- Sidebar Left (Navigation) -->
<aside class="w-64 bg-slate-50 border-r border-slate-200 flex flex-col transition-all-custom" id="main-sidebar">
<div class="p-4 flex items-center justify-between">
<div class="flex items-center gap-2 font-bold text-slate-700 text-lg">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center text-white">
<i class="fas fa-feather-alt text-sm"></i>
</div>
<span>ZenNotes</span>
</div>
<button id="collapse-sidebar" class="text-slate-400 hover:text-slate-600">
<i class="fas fa-bars"></i>
</button>
</div>
<div class="px-4 mb-6">
<button id="new-note-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg shadow-sm flex items-center justify-center gap-2 transition-all-custom font-medium">
<i class="fas fa-plus"></i> New Note
</button>
</div>
<nav class="flex-1 overflow-y-auto custom-scrollbar px-2 space-y-6">
<!-- Section: Favorites -->
<div>
<div class="px-3 text-xs font-semibold text-slate-400 uppercase tracking-wider mb-2 flex justify-between items-center">
<span>Favorites</span>
<i class="fas fa-star text-[10px]"></i>
</div>
<ul class="space-y-1" id="favorites-list">
<!-- Dynamic -->
</ul>
</div>
<!-- Section: Notebooks -->
<div>
<div class="px-3 text-xs font-semibold text-slate-400 uppercase tracking-wider mb-2 flex justify-between items-center">
<span>Notebooks</span>
<button class="hover:text-slate-600"><i class="fas fa-plus text-[10px]"></i></button>
</div>
<ul class="space-y-1" id="notebooks-list">
<!-- Dynamic -->
</ul>
</div>
<!-- Section: Tags -->
<div>
<div class="px-3 text-xs font-semibold text-slate-400 uppercase tracking-wider mb-2 flex justify-between items-center">
<span>Tags</span>
</div>
<ul class="space-y-1 px-2" id="tags-list">
<!-- Dynamic -->
</ul>
</div>
</nav>
<div class="p-4 border-t border-slate-200">
<div class="flex items-center gap-3 p-2 hover:bg-slate-100 rounded-lg cursor-pointer transition-all-custom">
<div class="w-8 h-8 bg-slate-300 rounded-full overflow-hidden">
<img src="https://api.dicebear.com/7.x/avataaars/svg?seed=Felix" alt="User">
</div>
<span class="text-sm font-medium text-slate-600">Alex Rivers</span>
<i class="fas fa-cog ml-auto text-slate-400 text-xs"></i>
</div>
</div>
</aside>
<!-- Sidebar Middle (Note List) -->
<aside class="w-80 border-r border-slate-200 flex flex-col bg-white" id="note-list-sidebar">
<div class="p-4 border-b border-slate-100">
<div class="relative">
<i class="fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-sm"></i>
<input type="text" id="search-notes" placeholder="Search notes..." class="w-full pl-9 pr-4 py-2 bg-slate-100 border-transparent focus:bg-white focus:ring-2 focus:ring-blue-500 focus:border-transparent rounded-md text-sm transition-all-custom outline-none">
</div>
</div>
<div class="flex-1 overflow-y-auto custom-scrollbar" id="notes-container">
<!-- Note items rendered here -->
</div>
</aside>
<!-- Main Content (Editor) -->
<main class="flex-1 flex flex-col bg-white relative">
<!-- Toolbar -->
<header class="h-14 border-b border-slate-100 flex items-center justify-between px-6">
<div class="flex items-center gap-4">
<div class="flex items-center gap-1 text-slate-400 text-xs">
<i class="fas fa-folder-open"></i>
<span id="current-notebook-breadcrumb">General</span>
<i class="fas fa-chevron-right text-[8px]"></i>
<span id="current-note-breadcrumb" class="text-slate-600 font-medium">Welcome Note</span>
</div>
</div>
<div class="flex items-center gap-3">
<button id="star-note" class="w-9 h-9 rounded-full hover:bg-slate-100 text-slate-400 hover:text-yellow-500 transition-all-custom flex items-center justify-center">
<i class="far fa-star"></i>
</button>
<button id="delete-note" class="w-9 h-9 rounded-full hover:bg-red-50 text-slate-400 hover:text-red-500 transition-all-custom flex items-center justify-center">
<i class="far fa-trash-alt"></i>
</button>
<div class="h-6 w-px bg-slate-200 mx-1"></div>
<button class="bg-slate-800 text-white px-4 py-1.5 rounded-md text-sm font-medium hover:bg-slate-900 transition-all-custom">
Share
</button>
</div>
</header>
<!-- Editor -->
<div class="flex-1 overflow-y-auto custom-scrollbar p-8 md:p-16 lg:px-32">
<div class="max-w-3xl mx-auto">
<input type="text" id="note-title" placeholder="Note Title" class="w-full text-4xl font-bold mb-6 outline-none border-none placeholder-slate-300" value="Welcome Note">
<!-- Formatting Toolbar -->
<div class="flex items-center gap-2 mb-6 p-1 bg-slate-50 w-fit rounded-lg border border-slate-200 sticky top-0 z-10">
<button onclick="execCmd('bold')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Bold"><i class="fas fa-bold"></i></button>
<button onclick="execCmd('italic')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Italic"><i class="fas fa-italic"></i></button>
<div class="w-px h-4 bg-slate-300 mx-1"></div>
<button onclick="execCmd('insertUnorderedList')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Bullet List"><i class="fas fa-list-ul"></i></button>
<button onclick="execCmd('insertOrderedList')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Numbered List"><i class="fas fa-list-ol"></i></button>
<div class="w-px h-4 bg-slate-300 mx-1"></div>
<button onclick="execCmd('formatBlock', 'h1')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom font-bold text-xs">H1</button>
<button onclick="execCmd('formatBlock', 'h2')" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom font-bold text-xs">H2</button>
<div class="w-px h-4 bg-slate-300 mx-1"></div>
<button onclick="insertChecklist()" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Checklist"><i class="far fa-check-square"></i></button>
<button onclick="execCmd('createLink', prompt('Enter URL:'))" class="w-8 h-8 hover:bg-white hover:shadow-sm rounded flex items-center justify-center text-slate-600 transition-all-custom" title="Link"><i class="fas fa-link"></i></button>
</div>
<div id="editor" contenteditable="true" class="editor-content text-lg leading-relaxed text-slate-700 min-h-[500px] focus:outline-none">
<p>Welcome to <b>ZenNotes</b>!</p>
<p>This is a prototype for a modern knowledge management system. You can:</p>
<ul>
<li>Create notebooks to organize your thoughts</li>
<li>Use tags to link disparate ideas</li>
<li>Format your text with the toolbar above</li>
</ul>
<p>Try creating a new note or switching between existing ones in the sidebar.</p>
</div>
</div>
</div>
</main>
</div>
<script>
// --- State Management ---
const state = {
notes: [
{ id: '1', title: 'Welcome Note', content: '<p>Welcome to <b>ZenNotes</b>!</p><p>This is a prototype for a modern knowledge management system.</p>', notebookId: 'nb1', tags: ['tutorial', 'intro'], favorite: true, updated: new Date() },
{ id: '2', title: 'Project Ideas 🚀', content: '<p>1. AI-powered garden monitor</p><p>2. Local-first note app (like this one!)</p>', notebookId: 'nb1', tags: ['work', 'ideas'], favorite: false, updated: new Date(Date.now() - 86400000) },
{ id: '3', title: 'Grocery List', content: '<ul><li>Milk</li><li>Eggs</li><li>Avocado</li></ul>', notebookId: 'nb2', tags: ['personal'], favorite: false, updated: new Date(Date.now() - 172800000) },
{ id: '4', title: 'Reading List 2024', content: '<p>Books to read this year...</p>', notebookId: 'nb3', tags: ['personal', 'learning'], favorite: true, updated: new Date(Date.now() - 259200000) },
],
notebooks: [
{ id: 'nb1', name: 'General', icon: 'fa-folder' },
{ id: 'nb2', name: 'Personal', icon: 'fa-user' },
{ id: 'nb3', name: 'Learning', icon: 'fa-graduation-cap' },
],
tags: ['tutorial', 'intro', 'work', 'ideas', 'personal', 'learning'],
activeNoteId: '1',
activeNotebookId: null, // null means "All Notes"
};
// --- DOM Elements ---
const notesContainer = document.getElementById('notes-container');
const notebooksList = document.getElementById('notebooks-list');
const tagsList = document.getElementById('tags-list');
const favoritesList = document.getElementById('favorites-list');
const editor = document.getElementById('editor');
const titleInput = document.getElementById('note-title');
const currentNotebookBreadcrumb = document.getElementById('current-notebook-breadcrumb');
const currentNoteBreadcrumb = document.getElementById('current-note-breadcrumb');
const starBtn = document.getElementById('star-note');
const deleteBtn = document.getElementById('delete-note');
// --- Initialization ---
function init() {
renderNotebooks();
renderTags();
renderNotes();
loadNote(state.activeNoteId);
setupEventListeners();
}
// --- Rendering Logic ---
function renderNotebooks() {
notebooksList.innerHTML = `
<li onclick="filterByNotebook(null)" class="px-3 py-2 text-sm rounded-md cursor-pointer transition-all-custom ${state.activeNotebookId === null ? 'bg-blue-50 text-blue-600 font-medium' : 'text-slate-600 hover:bg-slate-100'}">
<i class="fas fa-layer-group mr-2 opacity-70"></i> All Notes
</li>
`;
state.notebooks.forEach(nb => {
notebooksList.innerHTML += `
<li onclick="filterByNotebook('${nb.id}')" class="px-3 py-2 text-sm rounded-md cursor-pointer transition-all-custom ${state.activeNotebookId === nb.id ? 'bg-blue-50 text-blue-600 font-medium' : 'text-slate-600 hover:bg-slate-100'}">
<i class="fas ${nb.icon} mr-2 opacity-70"></i> ${nb.name}
</li>
`;
});
}
function renderTags() {
tagsList.innerHTML = state.tags.map(tag => `
<li onclick="filterByTag('${tag}')" class="px-3 py-1 text-xs rounded-full cursor-pointer transition-all-custom bg-slate-100 text-slate-500 hover:bg-slate-200 w-fit mb-1">
#${tag}
</li>
`).join('');
}
function renderNotes(filteredNotes = null) {
const notesToRender = filteredNotes || state.notes;
notesContainer.innerHTML = '';
if (notesToRender.length === 0) {
notesContainer.innerHTML = `<div class="p-8 text-center text-slate-400 text-sm">No notes found</div>`;
return;
}
notesToRender.sort((a, b) => b.updated - a.updated).forEach(note => {
const isActive = note.id === state.activeNoteId;
const dateStr = note.updated.toLocaleDateString([], { month: 'short', day: 'numeric' });
const div = document.createElement('div');
div.className = `note-item p-4 cursor-pointer transition-all-custom border-b border-slate-50 ${isActive ? 'active' : 'hover:bg-slate-50'}`;
div.onclick = () => loadNote(note.id);
div.innerHTML = `
<div class="flex justify-between items-start mb-1">
<h4 class="font-semibold text-sm truncate pr-2 ${isActive ? 'text-blue-700' : 'text-slate-700'}">${note.title || 'Untitled'}</h4>
<span class="text-[10px] text-slate-400 whitespace-nowrap">${dateStr}</span>
</div>
<p class="text-xs text-slate-500 line-clamp-2 leading-relaxed">${stripHtml(note.content)}</p>
`;
notesContainer.appendChild(div);
});
// Favorites List
const favs = state.notes.filter(n => n.favorite);
favoritesList.innerHTML = favs.map(note => `
<li onclick="loadNote('${note.id}')" class="px-3 py-2 text-sm rounded-md cursor-pointer transition-all-custom ${note.id === state.activeNoteId ? 'bg-blue-50 text-blue-600 font-medium' : 'text-slate-600 hover:bg-slate-100'}">
<i class="fas fa-star text-yellow-400 mr-2 text-[10px]"></i> ${note.title}
</li>
`).join('');
}
function loadNote(id) {
const note = state.notes.find(n => n.id === id);
if (!note) return;
state.activeNoteId = id;
// Update UI
titleInput.value = note.title;
editor.innerHTML = note.content;
// Breadcrumb
const nb = state.notebooks.find(n => n.id === note.notebookId);
currentNotebookBreadcrumb.innerText = nb ? nb.name : 'General';
currentNoteBreadcrumb.innerText = note.title;
// Star button
starBtn.innerHTML = note.favorite ? '<i class="fas fa-star text-yellow-400"></i>' : '<i class="far fa-star"></i>';
renderNotes();
renderNotebooks();
}
// --- Actions ---
function filterByNotebook(id) {
state.activeNotebookId = id;
const filtered = id ? state.notes.filter(n => n.notebookId === id) : state.notes;
renderNotes(filtered);
renderNotebooks();
}
function filterByTag(tag) {
const filtered = state.notes.filter(n => n.tags.includes(tag));
renderNotes(filtered);
}
function createNewNote() {
const id = Date.now().toString();
const newNote = {
id: id,
title: 'New Note',
content: '<p>Start typing...</p>',
notebookId: state.activeNotebookId || 'nb1',
tags: [],
favorite: false,
updated: new Date()
};
state.notes.unshift(newNote);
loadNote(id);
}
function deleteCurrentNote() {
if (state.notes.length <= 1) {
alert("You must have at least one note.");
return;
}
state.notes = state.notes.filter(n => n.id !== state.activeNoteId);
loadNote(state.notes[0].id);
}
function toggleFavorite() {
const note = state.notes.find(n => n.id === state.activeNoteId);
if (note) {
note.favorite = !note.favorite;
loadNote(note.id);
}
}
// --- Editor Helpers ---
function execCmd(command, value = null) {
document.execCommand(command, false, value);
}
function insertChecklist() {
const checkboxHtml = '<div><input type="checkbox" class="mr-2 accent-blue-600"> <span contenteditable="true">New Task</span></div>';
document.execCommand('insertHTML', false, checkboxHtml);
}
function stripHtml(html) {
const tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
// --- Events ---
function setupEventListeners() {
document.getElementById('new-note-btn').addEventListener('click', createNewNote);
titleInput.addEventListener('input', (e) => {
const note = state.notes.find(n => n.id === state.activeNoteId);
if (note) {
note.title = e.target.value;
note.updated = new Date();
currentNoteBreadcrumb.innerText = e.target.value;
renderNotes();
}
});
editor.addEventListener('input', () => {
const note = state.notes.find(n => n.id === state.activeNoteId);
if (note) {
note.content = editor.innerHTML;
note.updated = new Date();
renderNotes();
}
});
starBtn.addEventListener('click', toggleFavorite);
deleteBtn.addEventListener('click', deleteCurrentNote);
document.getElementById('search-notes').addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
const filtered = state.notes.filter(n =>
n.title.toLowerCase().includes(query) ||
n.content.toLowerCase().includes(query)
);
renderNotes(filtered);
});
document.getElementById('collapse-sidebar').addEventListener('click', () => {
const sidebar = document.getElementById('main-sidebar');
sidebar.classList.toggle('w-64');
sidebar.classList.toggle('w-0');
sidebar.classList.toggle('opacity-0');
sidebar.classList.toggle('invisible');
});
}
// Run
init();
</script>
</body>
</html>
<!-- agent-meta {"model":"google/gemma-4-31b-it","provider":"openrouter","persona":"middle","sessionId":"8c0b519d-5f35-4eb3-b937-3c937b6e4c1f","tokensIn":9146,"tokensOut":8544,"tokensTotal":17690,"turns":3,"toolCalls":2,"failedToolCalls":1,"timestamp":"2026-07-14T15:32:11.904Z"} -->