Skip to content

Latest commit

 

History

History
179 lines (138 loc) · 7.33 KB

File metadata and controls

179 lines (138 loc) · 7.33 KB

AGENTS.md

The AGENTS.md is the equivalent to CLAUDE.md

Use modern clean designs inspired by claude.ai

HTML File Standards

New index.html pages can use a copy of the template: /localsite/start/template/index.html

The template .html includes localsite.js and base.css Use css in localsite/css/base.css for -- :root, .dark, .btn, card, panel and radius styles rather than creating page-specific css styles.

UTF-8 Character Encoding: Always include <meta charset="UTF-8"> in the <head> section of new HTML pages to ensure proper character rendering and prevent display issues with special characters.

Exceptions: Do not add charset declarations to redirect pages, or to html template fragments that are included in other pages, as they inherit encoding from their parent documents.

Design

Use a modern, clean response design that has rounded corners on boarderless panels. Each new panel should use the "Panel Menu Toggle System" from localsite/js/localsite.js to place a cirlce icon in its upper right with options for Expand, Close, etc. Include .dark mode css. Set responsive layouts based on parent div widths rather than browser width. When possible, reuse common css from localsite/css/base.css

Icons

material-icons are available to pages that include localsite/js/localsite.js

Loading JavaScript and CSS Files Dynamically

Use these functions from localsite/js/localsite.js to load external files at runtime:

loadScript(url, callback)

Loads a JavaScript file once; prevents double-loading by keying on the URL. Fires callback when the script is ready.

loadScript('/cv/common/index.js', function () {
  // index.js is loaded; safe to call its exported APIs
  window.CVRenderer.render('detailed.json', onDone);
});

includeCSS3(url)

Appends a <link rel="stylesheet"> to <head> once. Prevents double-loading by keying on the URL. No callback — stylesheets apply immediately after insertion.

Swappable stylesheets (e.g. theme switching)

When you need to swap CSS at runtime rather than load it once, manage the <link> element directly by updating its href:

let themeLink = document.getElementById('myThemeStylesheet');
if (!themeLink) {
  themeLink = document.createElement('link');
  themeLink.id = 'myThemeStylesheet';
  themeLink.rel = 'stylesheet';
  themeLink.type = 'text/css';
  document.head.appendChild(themeLink);
}
themeLink.href = `/themes/${encodeURIComponent(theme)}/style.css`;

Do not use includeCSS3 for swappable stylesheets — it is intended for stylesheets that are loaded once and never changed.


Alert Messages

Avoid including \n line breaks in alerts since they prevent text from being copied. For debugging multi-step behavior, prefer combining all trace steps into one final alert string instead of multiple sequential alerts.

DOM Element Waiting

  • NEVER use setTimeout() for waiting for DOM elements
  • ALWAYS use waitForElm(selector) from localsite/js/localsite.js instead
  • Check if localsite/js/localsite.js is included in the page before using waitForElm
  • If not included, ask user if localsite/js/localsite.js should be added to the page
  • Example: waitForElm('#element-id').then(() => { /* code */ });
  • waitForElm does not use timeouts and waits indefinitely until element appears

Hash Management and URL State

Use these functions from localsite/js/localsite.js for hash-based state management:

Hash Reading and Manipulation

  • getHash(): Returns hash parameters as an object

    let hash = getHash(); // Returns {param1: 'value1', param2: 'value2'}
  • goHash(object): Updates hash with new parameters and triggers hashChangeEvent

    goHash({'team': 'Marketing', 'view': 'list'}); // Triggers hash change event
  • updateHash(object): Updates hash without triggering hashChangeEvent

    updateHash({'team': 'Marketing'}); // Silent hash update, no event fired

Hash Change Listening

  • hashChangeEvent: Custom event that fires when hash changes via goHash() and when URL hash is changed directly by the user.
  • Use on multiple page: Allows multiple widgets in a page to independently respond to changing URL hash values.
    document.addEventListener('hashChangeEvent', function (elem) {
        const hash = getHash();
        // Handle hash changes
    });

When to Use Each Function

  • Use goHash(): When you want other components to react to hash changes
  • Use updateHash(): When you want to update the hash without triggering reactions
  • Use hashChangeEvent: To listen for hash changes triggered by goHash()
  • Always check function existence: if (typeof getHash === 'function')

Detecting Hash Changes with priorHash

The window.priorHash object stores the previous hash state and is automatically maintained by localsite.js:

  • Automatically updated: Updated by localsite.js whenever the hash changes (via goHash() or direct URL edit)
  • NOT updated by updateHash(): Silent updates don't change priorHash, allowing intentional bypassing of change detection
  • Use for change detection: Compare current hash with priorHash to detect actual changes and prevent unnecessary updates

Example usage pattern (from localsite/js/navigation.js):

function handleHashChange() {
    const hash = getHash();
    const priorHashValue = window.priorHash?.paramName;

    // Only process if the parameter actually changed
    if (hash.paramName !== priorHashValue) {
        // Parameter changed, update the view
        updateView(hash.paramName);
    }
}

document.addEventListener('hashChangeEvent', handleHashChange);

Why use priorHash?

  • Prevents double-processing when hash change handlers are called multiple times
  • Avoids re-rendering when the same item is selected repeatedly
  • Ensures map updates only happen when coordinates actually change
  • Critical for preventing "every-other-click" bugs where caching happens before comparison

Important: Always use goHash() (not updateHash()) when you want priorHash to be updated and change detection to work properly.

Dual-Purpose Menu System (Food and Product Views)

The profile/item/menu.html page demonstrates hash-based view switching:

  • Food View (default): No layout parameter in hash

    • Shows food categories and USDA nutrition search
    • Country dropdown filters food search results (US = "American", IN = "India")
  • Product View: layout=product in hash

    • Shows product categories from products-data repository
    • Country parameter (US or IN) determines which product catalog to display
    • Without product ID: displays category sidebar for browsing
    • With product ID: loads specific product environmental impact label
  • Hash Parameters:

    • layout: "product" or absent (for food view)
    • country: "US" or "IN" (default: "US")
    • id: Product UUID (only in product view)

Example hash change handler:

document.addEventListener('hashChangeEvent', loadMenu, false);
function loadMenu() {
    const hash = getHash();
    if (hash.layout == "product") {
        // Load product categories or specific product
        if (hash.id) {
            loadProductByCountryAndId(hash.country, hash.id);
        } else {
            loadProductCategorySidebar();
        }
    } else {
        // Load food categories
        loadFoodCategorySidebar();
    }
}