Files
pbakaus_impeccable/public/app.js
T
Paul BakausandClaude Opus 4.5 5d65154dee Fix: Restore public directory from accidental regression
Commit 3d9f4ae accidentally reverted public/app.js and public/css/main.css
(plus other files) to old versions. This broke the site because:
- app.js imported from deleted files (commands.js, skills.js)
- main.css lost 1200+ lines of Renaissance redesign (split comparison, etc.)

Restored from commit 343e342 which had the working frontend.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 13:38:19 -08:00

138 lines
4.0 KiB
JavaScript

import {
initGlassTerminal,
renderTerminalLayout,
} from "./js/components/glass-terminal.js";
import { initLensEffect } from "./js/components/lens.js";
import { initFrameworkViz } from "./js/components/framework-viz.js";
import { initHeroEffect } from "./js/effects/liquid-canvas.js";
import { initScrollReveal } from "./js/utils/reveal.js";
import { initScrollIndicator, initSmoothScroll, initHashTracking } from "./js/utils/scroll.js";
// ============================================
// STATE
// ============================================
let allCommands = [];
// ============================================
// CONTENT LOADING
// ============================================
async function loadContent() {
try {
const [commandsRes, patternsRes] = await Promise.all([
fetch("/api/commands"),
fetch("/api/patterns"),
]);
allCommands = await commandsRes.json();
const patternsData = await patternsRes.json();
// Render commands (Glass Terminal)
renderTerminalLayout(allCommands);
// Render patterns with tabbed navigation
renderPatternsWithTabs(patternsData.patterns, patternsData.antipatterns);
} catch (error) {
console.error("Failed to load content:", error);
}
}
function renderPatternsWithTabs(patterns, antipatterns) {
const container = document.getElementById("patterns-categories");
if (!container || !patterns || !antipatterns) return;
// Create a map of antipatterns by category name
const antipatternMap = {};
antipatterns.forEach(cat => {
antipatternMap[cat.name] = cat.items;
});
// Build tabs
const tabsHTML = patterns
.map((category, i) => `<button class="pattern-tab${i === 0 ? ' active' : ''}" data-tab="${category.name}">${category.name}</button>`)
.join("");
// Build panels
const panelsHTML = patterns
.map((category, i) => {
const antiItems = antipatternMap[category.name] || [];
return `
<div class="pattern-panel${i === 0 ? ' active' : ''}" data-panel="${category.name}">
<div class="pattern-columns">
<div class="pattern-column pattern-column--anti">
<span class="pattern-column-label">Don't</span>
<ul class="pattern-list">
${antiItems.map((item) => `<li class="pattern-item pattern-item--anti">${item}</li>`).join("")}
</ul>
</div>
<div class="pattern-column pattern-column--do">
<span class="pattern-column-label">Do</span>
<ul class="pattern-list">
${category.items.map((item) => `<li class="pattern-item pattern-item--do">${item}</li>`).join("")}
</ul>
</div>
</div>
</div>
`;
})
.join("");
container.innerHTML = `
<div class="pattern-tabs">${tabsHTML}</div>
<div class="pattern-panels">${panelsHTML}</div>
`;
// Tab click handling
container.querySelectorAll('.pattern-tab').forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.dataset.tab;
// Update active tab
container.querySelectorAll('.pattern-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update active panel
container.querySelectorAll('.pattern-panel').forEach(p => p.classList.remove('active'));
container.querySelector(`[data-panel="${tabName}"]`).classList.add('active');
});
});
}
// ============================================
// EVENT HANDLERS
// ============================================
// Handle bundle download clicks via event delegation
document.addEventListener("click", (e) => {
const bundleBtn = e.target.closest("[data-bundle]");
if (bundleBtn) {
const { bundle: provider } = bundleBtn.dataset;
window.location.href = `/api/download/bundle/${provider}`;
}
});
// ============================================
// STARTUP
// ============================================
function init() {
initSmoothScroll();
initScrollIndicator();
initHashTracking();
initHeroEffect();
initLensEffect();
initScrollReveal();
initGlassTerminal();
initFrameworkViz();
loadContent();
document.body.classList.add("loaded");
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}