</> HTML5 nav & auth code
// Wire up nav + auth using native <dialog> elements
function bindNavButtons() {
  document.getElementById('btn-sign-in').addEventListener('click', signIn);
  document.getElementById('btn-sign-out').addEventListener('click', signOut);

  document.getElementById('btn-admin-login').addEventListener('click', () => {
    // Native <dialog>: call showModal() to open
    document.getElementById('dialog-admin-login').showModal();
  });

  document.getElementById('btn-admin-logout').addEventListener('click', () => {
    localStorage.removeItem('adminApiKey');
    document.body.classList.remove('admin-active');
    document.getElementById('admin-table-container').innerHTML = '';
  });
}

// React to Clerk auth changes and keep the top bar in sync
onChange(({ user }) => {
  const body = document.body;
  if (user) {
    body.classList.add('signed-in');
    body.classList.remove('signed-out');
    document.getElementById('user-name').textContent =
      user.firstName || user.emailAddresses?.[0]?.emailAddress || 'User';
    loadPrivateNotes();
  } else {
    body.classList.remove('signed-in');
    body.classList.add('signed-out');
    document.getElementById('user-name').textContent = '';
    document.getElementById('private-notes-grid').innerHTML = '';
  }
});
🧪 E2E test (Playwright)
// e2e-tests/tests/html5.spec.ts
test('page has correct title', async ({ page }) => {
  await page.goto(appPath, { waitUntil: 'domcontentloaded' });
  await expect(page).toHaveTitle(/Elysia Notes - HTML5/);
});

All Notes (Admin View)

View and manage all notes in the system

Delete notes whose content or title matches the regex

Loading admin notes...
</> HTML5 code
// Fetch all notes with admin API key, render with <template>
async function loadAdminNotes() {
  const key = localStorage.getItem('adminApiKey');
  const res = await fetch('/api/notes/all', {
    headers: { 'X-API-Key': key },
  });
  const notes = await res.json();
  renderAdminTable(notes);
}

function renderAdminTable(notes) {
  const container = document.getElementById('admin-table-container');
  container.innerHTML = '';
  if (!notes.length) {
    const empty = document.createElement('div');
    empty.className = 'empty-state';
    empty.textContent = 'No notes found.';
    container.appendChild(empty);
    return;
  }
  // Use <template> for row rendering
  const tpl = document.getElementById('tpl-admin-row');
  const wrapper = document.createElement('div');
  wrapper.className = 'admin-table-wrapper';
  const table = document.createElement('table');
  table.className = 'admin-table';
  table.innerHTML = '<thead><tr><th>ID</th><th>Title</th><th>Content</th><th>Type</th><th>Actions</th></tr></thead>';
  const tbody = document.createElement('tbody');
  for (const note of notes) {
    const row = tpl.content.cloneNode(true);
    // Use textContent for user data — no XSS
    row.querySelector('.col-id').textContent = note.id;
    row.querySelector('.col-title').textContent = note.title || '';
    row.querySelector('.col-content').textContent = note.content || note.data || '';
    row.querySelector('.col-type').textContent = note.isPublic ? 'Public' : 'Private';
    row.querySelector('.btn-admin-delete').dataset.id = note.id;
    tbody.appendChild(row);
  }
  table.appendChild(tbody);
  wrapper.appendChild(table);
  container.appendChild(wrapper);
}
🧪 E2E test (Playwright)
// Admin cleanup in globalTeardown
// globalTeardown deletes notes matching e2eNotePattern() after all tests complete.

Public Notes

Visible to everyone

Loading public notes...
</> HTML5 code
// Fetch public notes and render using <template id="tpl-public-note">
async function loadPublicNotes() {
  const res = await fetch('/api/public-notes');
  publicNotes = await res.json();
  renderPublicNotes();
}

function renderPublicNotes() {
  const grid = document.getElementById('public-notes-grid');
  grid.innerHTML = '';
  if (!publicNotes.length) {
    const empty = document.createElement('div');
    empty.className = 'empty-state';
    empty.textContent = 'No public notes yet. Create one!';
    grid.appendChild(empty);
    updateCounts();
    return;
  }
  const tpl = document.getElementById('tpl-public-note');
  for (const note of publicNotes) {
    const card = tpl.content.cloneNode(true);
    // textContent prevents XSS for user-provided data
    card.querySelector('.note-card-title').textContent = note.title || '';
    card.querySelector('.note-card-content').textContent = note.content || '';
    card.querySelector('.note-card-date').textContent = formatDate(note.createdAt);
    card.querySelector('.btn-edit-note').dataset.id = note.id;
    card.querySelector('.btn-delete-note').dataset.id = note.id;
    grid.appendChild(card);
  }
  updateCounts();
}

// Open native <dialog> to create a public note
document.getElementById('btn-create-public').addEventListener('click', () => {
  document.getElementById('dialog-create-public').showModal();
});
🧪 E2E test (Playwright)
// e2e-tests/tests/html5.spec.ts
test('Create Public Note button opens a dialog', async ({ page }) => {
  await page.locator('#btn-create-public').click();
  await expect(page.locator('#dialog-create-public')).toBeVisible();
});

Your Notes

Only you can see these notes

Loading private notes...
</> HTML5 code
// Fetch private notes with Bearer token, render using <template id="tpl-private-note">
async function loadPrivateNotes() {
  const token = getToken();
  if (!token) return;
  const res = await fetch('/api/private-notes', {
    headers: { Authorization: `Bearer ${token}` },
  });
  privateNotes = await res.json();
  renderPrivateNotes();
}

function renderPrivateNotes() {
  const grid = document.getElementById('private-notes-grid');
  grid.innerHTML = '';
  const tpl = document.getElementById('tpl-private-note');
  for (const note of privateNotes) {
    const card = tpl.content.cloneNode(true);
    card.querySelector('.note-card-title').textContent = note.title || '';
    card.querySelector('.note-card-content').textContent = note.content || note.data || '';
    card.querySelector('.note-card-date').textContent = formatDate(note.createdAt);
    card.querySelector('.btn-delete-note').dataset.id = note.id;
    grid.appendChild(card);
  }
  document.getElementById('private-count').textContent = String(privateNotes.length);
}

// Open native <dialog> to create a private note
document.getElementById('btn-create-private').addEventListener('click', () => {
  document.getElementById('dialog-create-private').showModal();
});
🧪 E2E test (Playwright)
// e2e-tests/tests/notes.spec.ts — private notes (signed in)
test('private note create, delete', async ({ page }) => {
  await page.goto(appPath, { waitUntil: 'domcontentloaded' });
  await expect(page.getByRole('button', { name: /create private note/i }))
    .toBeVisible({ timeout: 25_000 });
});