Module Reference
Modules live underjs/. At the time of this docs move, the app tree has 332 top-level JavaScript modules. This page is a guided implementation map, not a promise that every small hook/delegate/helper file has its own long section. Grouped by layer — lower layers have no dependencies on higher ones.
Layer 1 — Foundation
schema.js
The single source of truth for all biomarker definitions. No runtime logic — pure data.
Key exports:
MARKER_SCHEMA— nested object:{ categoryKey: { label, icon, markers: { markerKey: { name, unit, refMin, refMax, refMin_f, refMax_f, desc } } } }. Categories includebiochemistry,hormones,electrolytes,lipids,hematology,differential,thyroid,proteins,vitamins,diabetes,inflammation,fattyAcids,calculatedRatios, and othersUNIT_CONVERSIONS— keyed by"category.markerKey":{ type: 'multiply', factor, unit }for EU→US conversionsOPTIMAL_RANGES— keyed by"category.markerKey":{ optimalMin, optimalMax, optimalMin_f?, optimalMax_f? }PHASE_RANGES— keyed by"category.markerKey":{ menstrual: { min, max }, follicular: {...}, ovulatory: {...}, luteal: {...} }— covershormones.estradiol,hormones.progesterone,hormones.lh, andhormones.fshSPECIALTY_MARKER_DEFS— re-exported fromadapters.jsasADAPTER_MARKERS. Used bymigrateProfileData()andbuildMarkerReference()CHIP_COLORS— status → CSS color stringMODEL_PRICING— AI model pricing metadata, keyed by provider/model
adapters.js
Parser adapter registry for specialty lab detection and normalization. Single source of truth for all specialty marker definitions (OAT, fatty acids, Metabolomix+, BioStarks).
Key exports:
ADAPTER_MARKERS— flat object keyed by"category.markerKey":{ name, unit, refMin, refMax, categoryLabel, icon, group, singlePoint? }(217 entries). Re-exported fromschema.jsasSPECIALTY_MARKER_DEFSgetAllAdapterMarkers()— returns merged marker map from all registered adaptersdetectProduct(fileName, pdfText)— runs all adapterdetect()functions, returns{ adapter, product: { prefix, label } }ornullnormalizeWithAdapter(adapter, markers, fileName, pdfText, product)— dispatches toadapter.normalize()for post-AI marker key/category rewritinggetAdapterByTestType(testType)— looks up adapter by AI-returned test type string
{ id, testTypes[], markers, detect?, normalize? }:
fattyAcids— 29 markers, detects Spadia/ZinZino/OmegaQuant by filename/text, normalizes to product-prefixed categories under “Fatty Acids” sidebar groupmetabolomix— no unique markers (reuses OAT + FA), detects Genova Metabolomix+ reports, routes FA add-on markers tometabolomixFAprefixoat— 165 markers, no detect/normalize (AI handles OAT categorization directly)biostarks— 23 markers, detects BioStarks dried blood spot reports by filename/text, normalizes specialty markers (amino acids, serum FA, intracellular minerals, hormones, vitamins) while passing standard blood markers through to schema categories (hybrid import)
constants.js
Static arrays and string constants used across modules.
Key exports:
CHAT_PERSONALITIES— array of{ id, name, icon, promptText }for the 3 built-in personalitiesCHAT_SYSTEM_PROMPT— the base system prompt string injected into all AI chat requestsCOUNTRY_LATITUDES—{ countryCode: latitudeBand }(~70 countries, 5 bands: arctic/north/temperate/subtropical/tropical)FAKE_DATA— synthetic name/address/DOB data for PII obfuscation- Per-card option arrays:
SLEEP_DURATIONS,SLEEP_QUALITIES,SLEEP_SCHEDULES,SLEEP_ISSUES,SLEEP_ENVIRONMENTS,SLEEP_PRACTICES,LIGHT_AM,LIGHT_DAYTIME,LIGHT_UV,LIGHT_EVENING,LIGHT_SCREEN,LIGHT_TECH_ENV,LIGHT_COLD,LIGHT_GROUNDING,LIGHT_MEAL_TIMING,STRESS_LEVELS,STRESS_SOURCES,STRESS_MANAGEMENT,ENV_SETTING,ENV_CLIMATE,ENV_WATER,ENV_WATER_CONCERNS,ENV_EMF,ENV_EMF_MITIGATION,ENV_HOME_LIGHT,ENV_AIR,ENV_TOXINS,ENV_BUILDING,LOVE_STATUS,LOVE_RELATIONSHIP,LOVE_SATISFACTION,LOVE_LIBIDO,LOVE_FREQUENCY,LOVE_ORGASM,LOVE_CONCERNS,PERIOD_SYMPTOMS,DIET_TYPES,DIET_RESTRICTIONS,DIET_PATTERNS,EXERCISE_FREQUENCIES,EXERCISE_TYPES,EXERCISE_INTENSITIES,EXERCISE_DAILY_MOVEMENT
state.js
Single shared mutable state object. Import state to read or write. No logic.
Key exports:
state— the mutable singleton:
window._labState = state is set for debugging in the browser console.
Window exports: none (state is accessed via import)
utils.js
Shared pure utility functions.
Key exports:
escapeHTML(str)— escapes<>&"'for safe innerHTML insertionhashString(str)— djb2 hash, returns integergetStatus(value, refMin, refMax)—'normal'|'high'|'low'|'missing'. Returns'normal'when refs arenullformatValue(value, unit)— formats a numeric value with appropriate decimal placesshowNotification(message, type)— toast notification ('info'|'success'|'error'|'warning')showConfirmDialog(message)— returnsPromise<boolean>, styled confirm dialoglinearRegression(points)—{ slope, intercept, r2 }from[{ x, y }]arrayhasCardContent(obj)— generic empty-card gate: returnstrueif any field has content (strings non-empty, arrays non-empty,notetrimmed). Used bybuildLabContext()for 7 context card gatesbindModalSyncRefresh(opts)/bindDetailModalSyncRefresh(kind, refresh)/bindDetachedModalSyncRefresh(opts)— sharedlabcharts-sync-appliedmodal refresh bindings with dirty-form guards and scroll restoration
showNotification, showConfirmDialog, setDebugMode, setPIIReviewEnabled, hasCardContent
Layer 2 — Core Services
modal-lifecycle.js
Shared modal backdrop, focus-trap, and body-scroll lock helpers. Owns the cross-module scroll-lock registry used by Light & Sun modals; sun.js re-exports the legacy names for compatibility.
Key exports:
wireBackdropClose(overlay, closeFn?)/_wireBackdropClose(overlay, closeFn?)— backdrop click close wiring with inside-click guardtrapModalFocus(overlay)— locks background scroll, restores focus/overflow on removal, and handles Escape close
sun.js still exposes compatibility globals.
theme.js
Theme management and Chart.js color helpers.
Key exports:
getTheme()/setTheme(theme)/toggleTheme()—'dark'|'light';setThemesetsdata-themeon<html>getChartColors()— reads live CSS custom properties and returns a chart color config objectformatDateLabel(dateStr)— formats ISO date for chart x-axisgetTimeFormat()/setTimeFormat(fmt)—'24h'|'12h', stored inlabcharts-time-formatformatTime(timeStr)— formats a 24h time string for display using the active formatparseTimeInput(input)— accepts both'14:30'and'2:30 PM', always returns 24h format
toggleTheme
hardware.js
GPU detection and model fitness advisor for Local AI settings. Pure functions, no DOM manipulation.
Key exports:
detectHardware()— async, returns{ gpu: { name, vram, unified, renderer, source }, ram: { gb, source }, cpuThreads }. GPU detected via WebGLWEBGL_debug_renderer_infomatched against 75-entryGPU_DB(Apple Silicon M1–M4, NVIDIA RTX 30/40/50, AMD RX 6000/7000, Intel Arc, Vega)assessModel(modelObj, hardware)— returns{ tier, badge, vramNeeded, label }where tier is'fits'/'tight'/'toobig'/'unknown'assessFitness(modelName)— rates a model for getbased lab analysis:{ tier, note }where tier is'recommended'/'capable'/'underpowered'/'inadequate'. Benchmarked against Sonnet 4.6getBestModel(modelDetails, hardware)— picks the highest-fitness installed model that fits in VRAMgetUpgradeSuggestion(modelDetails, hardware)— returns a pull recommendation if no installed model is “recommended” tiersaveHardwareOverride(vram)/getHardwareOverride()— manual VRAM override in localStorage
settings.js)
api.js
AI provider routing and model management. All AI calls flow through callClaudeAPI.
Key exports:
callClaudeAPI(opts)— main router: delegates to the active provider based ongetAIProvider()callOpenRouterAPI(opts)— OpenRouter viacallOpenAICompatibleAPIcallRoutstrAPI(opts)— Routstr viacallOpenAICompatibleAPIcallPPQAPI(opts)— PPQ viacallOpenAICompatibleAPIcallVeniceAPI(opts)— Venice AI viacallOpenAICompatibleAPIcallOpenAICompatibleLocalAPI(opts)— Local AI via sharedcallOpenAICompatibleAPIhelpercallOpenAICompatibleAPI(endpoint, key, model, providerName, opts, extraHeaders)— shared OpenAI-format helpergetAIProvider()/setAIProvider(provider)—'openrouter'|'routstr'|'ppq'|'venice'|'ollama'(internal key for Local)hasAIProvider()— returnstrueif any provider is configured; gates all 7 AI featuresgetOpenRouterModel(),getRoutstrModel(),getPPQModel(),getVeniceModel(),getOllamaMainModel()fetchOpenRouterModels(),fetchRoutstrModels(),fetchPPQModels(),fetchVeniceModels()— dynamic model listsgetModelPricing(modelId)— checks dynamic OpenRouter pricing cache, falls back toMODEL_PRICINGOPENROUTER_CURATED— whitelist of latest-gen medically capable models (prefix-matched)OPENROUTER_EXCLUDE— blocklist filtering codex/audio/image/oss variants
getRoutstrNodeUrl (used by settings UI for node URL access)
api-transport.js
Shared AI API transport helpers used by api.js.
Key exports:
fetchWithRetry(url, options, config)— wraps fetch with request timeout, transient network retry, and 429 backoffcreateProxyFetch(shouldUseProxy)— builds the Custom API proxy fetch wrapperreadWithStallTimeout(reader, label)— guards streaming readers from hanging between chunksSTREAM_STALL_TIMEOUT_MS,FETCH_REQUEST_TIMEOUT_MS,AI_IMPORT_REQUEST_TIMEOUT_MS— public timeout constants re-exported byapi.js
cashu-wallet.js
In-app Cashu eCash wallet for decentralized AI payments. Proofs stored in IndexedDB, BIP-39 seed encrypted in localStorage.
Key exports:
getMintUrl()/setMintUrl(url)— configured Cashu mintgenerateWalletSeed()— creates 12-word BIP-39 mnemonicrestoreWalletFromSeed(mnemonic)— restores proofs from mint viabatchRestoregetWalletBalance()— sum of unspent proofs for current mintcreateFundingInvoice(amountSats)/checkFundingStatus(quoteId)— Lightning deposit flowreceiveToken(tokenString)— deposit a Cashu tokendepositToNode(nodeUrl, amountSats, existingKey)— swap proofs for a node session keysendAsToken(amountSats)— withdraw as shareable Cashu tokencreateWithdrawQuote(bolt11)/executeWithdraw(quoteId)— Lightning withdrawalwithdrawToAddress(address, amountSats)— LNURL-pay withdrawalrecoverPendingDeposit()/recoverPendingWithdraw()— failed operation recoveryexportWallet()/importWallet(tokenString)— backup/restoregetFeePct()— current fee percentage (0 during beta)
cashu (e.g., cashuGetBalance, cashuDepositToNode)
nostr-discovery.js
Discovers Routstr AI nodes via Nostr relays (Kind 38421 events).
Key exports:
discoverNodes(forceRefresh)— queries relays in parallel, deduplicates, health-checks, returns sorted node arraygetSelectedNodeUrl()/setSelectedNodeUrl(url)— persisted node selectionclearNodeCache()— force re-discovery on next call
nostrDiscoverNodes, nostrGetSelectedNode, nostrSetSelectedNode, nostrClearNodeCache
Layer 3 — Data & Profile
profile.js
Profile lifecycle and settings persistence.
Key exports:
profileStorageKey(profileId, suffix)— buildslabcharts-{profileId}-{suffix}createDefaultProfileData()— returns the empty importedData shape used for new/metadata-only profile syncloadProfiles()/saveProfiles()— profile index CRUDswitchProfile(profileId)— loads importedData from localStorage for the given profiledeleteProfile(profileId)— removes all keys for the profilemigrateProfileData()— upgrades legacy field formats on load (oldsleepCircadian→sleepRest+lightCircadian, oldfieldExperts/fieldLens→interpretiveLens, initializes missing fields withnull)getProfileLocation()/setProfileLocation(country, zip)— country+ZIP storagegetLatitudeFromLocation()— looks up latitude band fromCOUNTRY_LATITUDESrenderProfileDropdown()— renders the profile selector UI
openProfileEditor, switchProfile, deleteProfile, addProfile, saveProfile
data.js
The central data pipeline. Every view gets its data from getActiveData().
Key exports:
getActiveData()— deep-clonesMARKER_SCHEMA, merges custom markers, applies sex-specific ranges, populatesvalues[]arrays fromimportedData.entries, computes ratios + PhenoAge + cycle phases, applies unit conversion. Returnsdataobject with{ dates[], dateLabels[], categories, phaseLabels? }saveImportedData()— persistsstate.importedDatato localStorage (or encrypted store), triggers backupbuildMarkerReference()— compact JSON of all known markers for AI system prompts (PDF import)filterDatesByRange(data)— appliesstate.dateRangeFilterto dates + values arrays in-placeregisterRefreshCallback(fn)— registers the refresh function fromapp-event-listeners.jsgetFocusCardFingerprint()— djb2 hash of all entries + all 9 context cards + sex + DOB- Compatibility re-exports from
marker-analysis.jskeep existingwindow.*helper access stable.
saveImportedData, clearAllData (via export.js), filterDatesByRange
marker-analysis.js
Read-only marker range, status, and trend helpers. This module owns pure marker analysis so chart, dashboard, AI context, and export code do not need to import the storage/sync-heavy data.js when they only need derived marker calculations.
Key exports:
getEffectiveRange(marker)— returns{ min, max }respectingstate.rangeModegetEffectiveRangeForDate(marker, dateIndex)— phase-aware range lookup; falls back togetEffectiveRange()getPhaseRefEnvelope(marker)— widest span across all cycle phases for chart ref bandsgetLatestValueIndex(values)— index of the latest non-null marker valuecountFlagged(markers)/getAllFlaggedMarkers(data)— out-of-range marker helpersstatusIcon(status)— status-to-symbol mapping used by category cardsdetectTrendAlerts(data)— sudden-change (25% of ref range, 2+ values) and linear-regression (slope >0.02, R²>0.5 for 4+ points) alertsgetKeyTrendMarkers(filteredData)— dashboard key-trend selection
data.js keeps compatibility exports.
pii.js
Two-path PII obfuscation for PDF text before AI submission, with streaming review modal.
Key exports:
sanitizeWithOllamaStreaming(pdfText, onChunk, signal)— preferred path: SSE streaming via OpenAI-compatible API, callsonChunk(delta)per token, supportsAbortSignalsanitizeWithOllama(pdfText)— non-streaming path: same endpoint, used when review is disabledobfuscatePDFText(pdfText)— regex fallback: label-based + pattern-based replacement, returns{ obfuscated, original, replacements }reviewPIIBeforeSend(originalText, { obfuscatedText, streamFn })— review modal: streaming mode (passstreamFn) or static mode (passobfuscatedText). Returns edited text or'cancel'checkOllamaPII()— checks PII server availability via/v1/modelsgetOllamaConfig()/saveOllamaConfig(config)— local AI config:{ url, model, apiKey }showPIIDiffViewer(original, obfuscated, replacements)— debug diff viewer (requireslabcharts-debugflag)
setOllamaPIIModel
image-utils.js
Shared image utilities for chat attachments and PDF image fallback.
Key exports:
resizeImage(file, maxDim?, quality?)— resizes an image to fit withinmaxDimpixels (default 1024), returns{ base64, mediaType, width, height, origWidth, origHeight, quality_warnings }isValidImageType(type)— validates MIME type againstimage/(jpeg|png|gif|webp)formatImageBlock(base64, mediaType, provider)— returns a provider-specific image content block (type:'image_url'for OpenAI-compatible providers)buildVisionContent(imageBlocks, text, provider)— assembles a content array with image blocks + text block
analyzeImageQuality(ctx, width, height)— canvas-based pixel sampling (~100k samples): brightness (dark/overexposed) + Laplacian variance (blur detection). Returnsstring[]warnings
resizeImage, isValidImageType, formatImageBlock, buildVisionContent
Layer 4 — Domain Modules
charts.js
Chart.js configuration and all custom plugins.
Key exports:
createLineChart(canvasId, marker, data, phaseLabels?)— creates a Chart.js line chart with all plugins applieddestroyAllCharts()— destroys all instances instate.chartInstancesto prevent memory leaks- Five Chart.js plugins (registered globally):
refBandPlugin— shaded reference range bandoptimalBandPlugin— green dashed optimal range bandnoteAnnotationPlugin— yellow dot annotations at note dates with hover tooltipssupplementBarPlugin— colored timeline bars for supplementsphaseBandPlugin— cycle phase vertical shading (menstrual=red, follicular=blue, ovulatory=purple, luteal=yellow, 8% opacity)
notes.js
Standalone note management (independent of lab entries).
Key exports:
openNoteEditor(date?)— opens the note editor modal, pre-filled ifdateprovidedsaveNote()— saves the current editor content toimportedData.notesdeleteNote(date)— removes a note by date
openNoteEditor, saveNote, deleteNote
supplements.js
Supplement and medication timeline, editor, ingredient tracking, and AI impact analysis.
Key exports:
openSupplementsEditor(index?)— opens the supplement editor modalsaveSupplement(idx)— persists current form state toimportedData.supplementsdeleteSupplement(idx)— removes by indexrenderSupplementsSection()— dashboard timeline barsrenderSupplementImpact(supp, editIdx)— per-supp impact card (shimmer → cached AI summary)computeSupplementImpact(supp, markerKey, ...)— before/after mean comparison for one markercomputeAllImpacts(supp, data)— impact vectors across all markers, sorted by |pctChange|parseAmount(str)— extract{value, unit}from “890mg” / “5,4 mg” / “500 IU” (handles comma decimals)effectiveTimesPerDay(ing, supp)— row override wins, else supp-level defaultingredientDailyTotal(ing, supp)— computedamount × effectiveTimesPerDay
timesPerDay (default multiplier); each ingredient row has {name, amount, timesPerDay?} where timesPerDay is an optional per-row override. Daily total = amount × (row.timesPerDay ?? supp.timesPerDay).
Impact cache: per-supp cache in labcharts-{profileId}-suppImpact keyed by supp name with a fingerprint that includes dosage, outer timesPerDay, per-ingredient fields, periods, and lab dates — any edit auto-invalidates only that supp’s cache entry. Concurrent renders are coalesced via a 50ms debounced queue (scheduleAnalyze → flushAnalyses).
cycle.js
Menstrual cycle tracking, helpers, and dashboard rendering.
Key exports:
getCyclePhase(dateStr, mc)—{ cycleDay, phase, phaseName }for a date against a cycle objectgetNextBestDrawDate(mc)— next early follicular window (days 3–5)getBloodDrawPhases(mc, dates)— maps lab dates to phasescalculateCycleStats(periods)— auto-computes{ cycleLength, periodLength, regularity }from period logdetectPerimenopausePattern(mc, dob)— flags perimenopause pattern (age 35+, 4+ periods, 2+ of 4 indicators)detectCycleIronAlerts(mc, data)— cross-references heavy flow with ferritin/hemoglobin/ironopenMenstrualCycleEditor()— opens the cycle editor modalsaveMenstrualCycle()— saves toimportedData.menstrualCycle, triggers cycle tourrenderMenstrualCycleSection(data)— renders the full cycle dashboard sectionstartCycleTour(auto)— triggers the 8-step cycle spotlight tour
openMenstrualCycleEditor, saveMenstrualCycle, addPeriod, deletePeriod, startCycleTour
context-cards.js
Lifestyle context card rendering plus AI health dots, Interpretive Lens / Knowledge Base dashboard rows, dashboard CTA pills, context change history, and legacy compatibility exports for summary/editor helpers.
Key exports:
renderProfileContextCards(data)— renders the 3-column context card grid on the dashboardrenderInterpretiveLensSection()— renders the lens row (when set) + KB status row (when configured) + AI personalize CTA pill + Data protection CTA pillrenderKnowledgeBaseSection()— pure-render helper for the KB status row (returns''when no library configured)renderDataProtectionCta(stateOverride?)— pure render of the data-protection pill; accepts an explicit state override for testabilityopenPersonalizeAIPicker()— 2-card picker (Lens / Knowledge Base) shown when both are unsetopenDataProtectionPicker()— 3-card picker (Encryption / Sync / Auto-backup) with configured cards grayed outtriggerDNAFilePicker()— programmatic file input trigger that routes throughwindow.handleDNAFile; used by the genetics empty-state stubloadContextHealthDots()— async; fetches AI health ratings for stale cards (per-card fingerprint caching)getCardFingerprint(key)— djb2 hash of lab data + card data + sex + DOB for cache invalidation- Per-card editor functions:
openDiagnosesEditor,openDietEditor,openExerciseEditor,openSleepEditor,openLightEditor,openStressEditor,openLoveLifeEditor,openEnvironmentEditor,openHealthGoalsEditor; Medical History helpers are compatibility re-exports fromcontext-card-medical-history-editor.js, and lifestyle/simple editors are compatibility re-exports fromcontext-card-lifestyle-editors.js - Per-card save functions:
saveDiagnoses,saveDiet,saveExercise,saveSleep,saveLight,saveStress,saveLoveLife,saveEnvironment,saveHealthGoals;saveDiagnosesis a compatibility re-export fromcontext-card-medical-history-editor.js, and lifestyle/simple saves are compatibility re-exports fromcontext-card-lifestyle-editors.js selectCtxOption(el, group, multi)— compatibility re-export fromcontext-card-editor-ui.jsgetSelectedOption(group)— reads selected value from a.ctx-btn-group- Summary helpers such as
getDietSummary()andgetEnvironmentSummary()— compatibility re-exports fromcontext-card-summaries.js debounceContextNotes()— auto-saves the free-form context notes textarearecordChange(field)— snapshots a context field and appends a timestamped entry toimportedData.changeHistory(dedup: same-day overwrite, identical skip, 200 cap)
selectCtxOption, addCondition, deleteCondition, addGoal, deleteGoal, syncDiagnosesNote, openInterpretiveLensEditor, saveInterpretiveLens, renderKnowledgeBaseSection, openPersonalizeAIPicker, openDataProtectionPicker, triggerDNAFilePicker
context-card-summaries.js
Context card metadata, filled-state checks, dashboard summary strings, and the EMF assessment launcher/summary. Kept side-effect-light so card rendering, chat/onboarding callers, and tests can share one source of truth without pulling in every editor modal.
Key exports: CONTEXT_CARD_KEYS, getContextCardDefs(), isContextFilled(key), getConditionsSummary(), getDietSummary(), getExerciseSummary(), getSleepSummary(), getLightCircadianSummary(), getStressSummary(), getLoveLifeSummary(), getEnvironmentSummary(), getGoalsSummary(), getEMFAssessments(), renderEMFAssessmentLauncher().
Window exports: none directly; legacy globals are assigned by context-cards.js.
context-card-editor-ui.js
Shared context editor modal shell and field-control render/read helpers used by the 9 card editors.
Key exports: renderContextEditorModal(), renderSelectField(), selectCtxOption(), getSelectedOption(), renderTagsField(), toggleCtxTag(), getSelectedTags(), renderNoteField(), contextEditorActions().
Window exports: none directly; legacy globals are assigned by context-cards.js.
context-card-medical-history-editor.js
Medical History editor module for personal conditions and family history. Owns the condition autocomplete, relative allowlist, add/delete flows, modal rendering, note sync, and save/clear handlers for importedData.diagnoses.
Key exports: configureMedicalHistoryEditor(), openDiagnosesEditor(), renderDiagnosesModal(), filterConditionSuggestions(), selectConditionSuggestion(), closeSuggestionsOnClickOutside(), syncDiagnosesNote(), addCondition(), editCondition(), cancelConditionEdit(), deleteCondition(), addFamilyHistoryEntry(), editFamilyHistoryEntry(), cancelFamilyHistoryEdit(), deleteFamilyHistoryEntry(), filterFamilyConditionSuggestions(), selectFamilyConditionSuggestion(), saveDiagnoses(), closeDiagnoses(), clearDiagnoses().
Window exports: none directly; legacy globals are assigned by context-cards.js.
context-card-lifestyle-editors.js
Lifestyle/simple context editors for Diet & Digestion, Sleep & Rest, Light & Circadian, Exercise, Stress, Love Life, Environment, Health Goals, Interpretive Lens, and the diet contaminant modal. Uses configureLifestyleContextEditors() so context-cards.js remains the owner of recordChange() and saveAndRefresh() while the editor module owns modal rendering and save/clear handlers.
Key exports: configureLifestyleContextEditors(), renderDietContaminantsBadge(), openDietEditor(), saveDiet(), clearDiet(), openSleepRestEditor(), saveSleepRest(), clearSleepRest(), openLightCircadianEditor(), saveLightCircadian(), clearLightCircadian(), openExerciseEditor(), saveExercise(), clearExercise(), openStressEditor(), saveStress(), clearStress(), openLoveLifeEditor(), saveLoveLife(), clearLoveLife(), openEnvironmentEditor(), saveEnvironment(), clearEnvironment(), openHealthGoalsEditor(), renderHealthGoalsModal(), addHealthGoal(), deleteHealthGoal(), closeHealthGoals(), clearHealthGoals(), openInterpretiveLensEditor(), saveInterpretiveLens(), clearInterpretiveLens(), showDietContaminantsModal().
Window exports: none directly; legacy globals are assigned by context-cards.js.
Layer 5 — Feature Modules
dna.js
DNA raw data import: client-side parser, storage, dashboard section, AI context assembly.
Key exports:
detectDNAFile(text)— detects format from file header:'ancestry'|'23andme'|'livingdna'|'csv'|nullisDNAFile(file)— checks filename patterns for known DNA providersisDNAFileByContent(file)— async, reads first 500 bytes to detect DNA format by contentparseDNAFile(file)— async, runs Web Worker parser, matches againstdata/snp-health.json(41 SNPs), resolves APOE haplotype, returns enriched matches with effect/note per genotypesaveGeneticsData(profileData, result)— stores matched SNPs + APOE inimportedData.geneticsdeleteGeneticsData(profileData)— removes genetics databuildGeneticsContext(genetics, activeMarkerKeys)— serializes genetics for AI context, filtered to SNPs relevant to active markersrenderGeneticsSection()— full genetics interpretation section for classic/mobile dashboard contexts; returns an in-context “Add your DNA data” empty-state stub (wired totriggerDNAFilePicker) when no SNPs/mtDNA existhandleDNAFile(file)— full import flow: parse → preview modal → confirm → save
isDNAFile, isDNAFileByContent, handleDNAFile, confirmDNAImport, closeDNAImportPreview, deleteGeneticsData, _buildGeneticsContext, _getRelevantSNPs
pdf-import.js
PDF/image/text-to-lab-data import pipeline and confirm/save merge logic.
Key exports:
extractPDFText(file)— pdf.js text extraction with x/y coordinates, returns page-aware formatted textparseLabPDFWithAI(pdfText)— sends text +buildMarkerReference()to AI; maps lab results to marker keyshandleImageFile(file)— imports lab reports from JPG/PNG/WebP images via AI image pipelinehandleBatchPDFs(files)— sequential multi-file import with per-file confirm/skipshowImportPreview(parsed)— re-export frompdf-import-review.jsconfirmImport(parsed)— merges parsed data intoimportedData.entriessetupDropZone()— legacy eager drop-zone binding retained for compatibility; page shells useimport-drop-zone.jsso the PDF import module stays lazy-loaded
confirmImport, skipImport, importNextPDF, syncImportStatusFab, handleImportStatusClick, isImportRunning
pdf-import-preflight.js
Pre-AI import checks for duplicate PDF hashes, previous-model mismatch prompts, and unsupported specialty-test warnings.
Key exports:
runPreflightChecks(pdfText, fileName)— returnsfalsewhen the user cancels before token-spending import work startsnormalizeImportModelId(id)— shared model ID canonicalization for cross-provider import mismatch checks
pdf-import.js calls this during PDF/batch import.
pdf-import-progress.js
Import progress bar, header import-button status, and batch progress rendering.
Key exports:
showImportProgress(step, fileName)/hideImportProgress(reason)— render and clear the import progress UIshowBatchImportProgress(step, fileName, current, total)— render per-file batch progressupdateImportProgressPct(pct)— streaming AI progress update hooksyncImportStatusFab()/handleImportStatusClick()/isImportRunning()— status bridge used bypdf-import.jswindow exports; the legacy function name now syncs the header import button
pdf-import.js
pdf-import-marker-normalization.js
Shared AI marker normalization for PDF text import and image import.
Key exports:
normalizeParsedImportMarkers(parsed, options)— sanitizes AI marker keys, runs product/test-type adapters, applies specialty guard rules, reconciles marker mappings, and returns{ testType, markers }
pdf-import.js calls this after AI JSON parsing.
pdf-import-persistence.js
Durable imported-data persistence helpers for PDF import flows.
Key exports:
snapshotImportedData()/restoreImportedDataSnapshot(snapshot)— rollback guard used when durable import saves failrefreshImportedDataViews()— rebuilds sidebar/header and restores the current route after imported data changesremoveImportedEntry(date)/renameImportedEntryDate(oldDate)— entry delete and date-edit mutations with tombstones, immediate sync save, rollback, and success refresh
pdf-import.js
pdf-import-review.js
Import review modal rendering and interaction state.
Key exports:
showImportPreview(parsed)— modal with matched, new custom, unmatched, and excluded marker rowsapplyManualImportDate(date)— updates pending review date and confirm button statemapUnmatchedMarkerInput(input)/toggleImportRow(button)— review-row mapping and exclusion controlsgetPendingImport()/getExcludedImportIndices()— narrow state access used byconfirmImport()showImportPreviewAsync(result, current, total)— batch import preview promise bridge
pdf-import.js
import-drop-zone.js
Lazy drop-zone event binding shared by Dashboard, Labs, and mobile dashboard shells. It imports loadPdfImport() from import-loader.js, classifies dropped files only after interaction, and routes JSON, lab PDFs/images, text imports, and DNA files to the same handlers used by the file input path.
Key exports:
setupDropZone()— idempotently binds click, drag, and drop handlers to#drop-zone
import-file-input.js
Lazy file-picker import binding for the hidden #pdf-input. It shares loadPdfImport() with the drop-zone path, classifies files on change, clears stale selections on failure, and routes JSON, lab PDFs/images, text imports, and DNA files through the import/DNA handlers exposed on window.
Key exports:
bindImportFileInput()— idempotently binds#pdf-inputchange handling and document-level drag/drop preventionhandleImportInputChange(e)— routes one file-picker change event through the lazy import classifier
export.js
Data export, import, and reset.
Key exports:
exportToJSON()— exports v2 JSON for the current profile:{ version: 2, exportedAt, entries, notes, diagnoses, diet, exercise, sleepRest, lightCircadian, stress, loveLife, environment, interpretiveLens, healthGoals, contextNotes, menstrualCycle, customMarkers, supplements }buildClientExportObject(profileId, includeChat?)— module-only helper that returns the reusable v2 single-profile export object used by JSON export and encrypted profile sharing. It includes profile metadata, labs, context, supplements, genetics, biometrics, marker notes, wearables summaries/preferences, and Light/Sun data, while excluding OAuth/wearable connection credentials and raw per-device wearable rowsexportClientJSON(profileId)— exports a single client’s data (used from Client List ⋮ menu)exportAllDataJSON()— exports a full database bundle with all profiles, chat threads, custom personalities, and settingsbuildAllDataBundle()— builds the bundle object used by bothexportAllDataJSON()and folder backupimportFromJSON(file)— merges entries by date, deduplicates notes, overwrites context fields, merges healthGoals by text. Auto-detects database bundles and handles multi-profile mergeexportToPDF()— generates a printable PDF report with all data, charts, and context cardsclearAllData()— confirms and wipes all imported data for the current profile
exportToJSON, exportDataJSON, exportClientJSON, exportAllDataJSON, importFromJSON, exportToPDF, clearAllData
profile-share.js
Encrypted single-profile share links. The module creates a profile export through the module-only buildClientExportObject() helper, encrypts it in the browser with a password, posts only the ciphertext envelope to /api/share, and imports shared profiles from #share/{id} deep links after local password decryption. Shared envelopes require at least 100,000 PBKDF2-SHA256 iterations; the normal generated value is 600,000.
Key exports:
createProfileShare({ profileId, password, expiresDays })— builds, encrypts, uploads, and records a managed share link for one profileencryptProfileShareEnvelope(exportObj, secret, options?)/decryptProfileShareEnvelope(envelope, secret)— AES-256-GCM envelope helpers using PBKDF2-SHA256generateProfileSharePassword()— generates a user-copyable random passwordbuildProfileShareUrl(id)/parseProfileShareIdFromLocation(loc?)— link construction and deep-link parsingopenProfileShareModal(profileId?)/openSharedProfileImportModal(id)— create/load modal entry pointshandleProfileShareDeepLink()/initProfileShareLinks()— startup hash handling for shared links
getbased-profile-shares-v1. Records store share metadata and the management token needed to stop sharing; they do not store the profile password or plaintext profile data.
Window exports: openProfileShareModal, closeProfileShareModal, openSharedProfileImportModal, createProfileShare, deleteProfileShareEnvelope, encryptProfileShareEnvelope, decryptProfileShareEnvelope, parseProfileShareIdFromLocation, buildProfileShareUrl
chat.js
Chat public barrel and startup entry point. Importing this module installs chat-window-bindings.js for legacy inline handlers, then re-exports the public chat helpers from the feature modules. Per-marker/correlation prompt builders live in chat-marker-prompts.js; direct send/streaming and image send integration live in chat-send.js; chat transcript rendering lives in chat-render.js; empty/onboarding message states live in chat-empty-state.js; chat-first onboarding handlers and provider quiz helpers live in chat-onboarding.js; multi-persona discussion exports live in chat-discussion.js, with public user-action handlers in chat-discussion-flow.js, callback bridging in chat-discussion-callbacks.js, cleanup/completion helpers in chat-discussion-lifecycle.js, round turn execution helpers in chat-discussion-turns.js, persona/thread state helpers in chat-discussion-state.js, round execution in chat-discussion-round-runner.js, round prompt helpers in chat-discussion-round-prompts.js, round API request helpers in chat-discussion-round-request.js, thread-bound round persistence in chat-discussion-round-state.js, live round message DOM helpers in chat-discussion-round-view.js, persona picker controls in chat-discussion-picker.js, and Discuss button/continue controls in chat-discussion-ui.js; panel chrome lives in chat-panel.js; FAB nudge state lives in chat-nudge.js; personality selection and custom persona editing live in chat-personalities.js; current-thread history persistence lives in chat-history.js; message action bars live in chat-actions.js; chat image attachment state lives in chat-images.js; thread index storage and rail rendering live in chat-threads.js; thread rail message search and match highlighting live in chat-thread-search.js.
Key exports:
sendChatMessage()— re-exported fromchat-send.jsfor existing callersrenderChatMessages()— re-exported fromchat-render.jsfor existing callersaskAIAboutMarker(markerKey)— re-exported fromchat-marker-prompts.js; opens chat with a marker-specific promptaskAIAboutCorrelations()— re-exported fromchat-marker-prompts.js; opens chat with a selected-marker correlation prompt- Thread management:
createNewThread(),loadThread(id),deleteThread(id),renameThread(id)
sendChatMessage, setChatPersonality, openChatPanel, closeChatPanel, createNewThread, loadThread, deleteThread, renameThread, generateCustomPersonality, saveCustomPersonality, askAIAboutMarker, addImageAttachment, toggleHDMode
chat-window-bindings.js
Chat callback wiring and legacy window.* compatibility exports. Owns _resumeAI, configures chat-discussion.js, chat-onboarding.js, and chat-panel.js callbacks, and exposes the chat handlers needed by inline HTML and cross-module window.fn() call sites.
Key exports: none; loaded for side effects by chat.js.
Window exports: sendChatMessage, renderChatMessages, setChatPersonality, openChatPanel, closeChatPanel, discussion handlers, onboarding handlers, summary handlers, action-bar handlers, and per-marker Ask AI handlers.
chat-marker-prompts.js
Per-marker and selected-correlation chat prompt builders. Owns askAIAboutMarker() and askAIAboutCorrelations(), including phase-aware marker values, effective reference ranges, latest status, and trend text before opening the chat panel with a prefilled prompt.
Key exports: askAIAboutMarker, askAIAboutCorrelations
Window exports: assigned by chat-window-bindings.js for existing inline Ask AI buttons.
chat-send.js
Direct chat send and streaming state. Owns sendChatMessage(), Enter-key handling, stop-button abort state, send-button icon mode, typewriter trickle, image attachment payload injection, API message assembly, usage footnotes, live EMF/product recommendation injection, and partial-message persistence on abort. It is imported by chat.js, which re-exports its public entry points and passes its typewriter/abort helpers to chat-discussion.js.
Key exports: sendChatMessage, handleChatKeydown, isChatStreaming, createTypewriter, getChatAbortController, setChatAbortController, setSendButtonMode, updateSendButtonState
Window exports: updateSendButtonState is assigned by this module for chat-images.js; other user-facing handlers are assigned by chat-window-bindings.js.
chat-render.js
Chat transcript rendering. Owns renderChatMessages() for persisted messages, lens-source disclosure rendering, assistant footnotes, image badges, EMF hints, and persisted recommendation sections. It delegates empty chat and onboarding states to chat-empty-state.js and keeps rendering details out of the chat window wiring module.
Key exports: renderChatMessages, _getNoDataPrompts, _renderLensSources
Window exports: renderChatMessages is assigned by chat-window-bindings.js for existing inline handlers and cross-module callbacks.
chat-empty-state.js
Empty chat and chat-first onboarding message composition. Owns the profile setup bubble, paused-AI prompt, explicit provider quiz entry state, no-lab optional setup cards, no-data prompt selection, and the default empty prompt buttons used before a real thread has messages.
Key exports: renderEmptyChatState, _getNoDataPrompts
Window exports: none; called by chat-render.js.
chat-panel.js
Chat panel chrome and entry-state helpers. Owns open/close/fullscreen behavior, persisted fullscreen preference, web-search toggle persistence/visibility, and composer disabled state. It imports thread/history/personality helpers directly, delegates FAB nudge dismissal to chat-nudge.js, and receives the active-discussion restore callback through configureChatPanel() to avoid importing chat-discussion.js.
Key exports: configureChatPanel, toggleChatPanel, toggleChatFullscreen, openChatPanel, closeChatPanel, updateChatInputState, getChatWebSearchEnabled, setChatWebSearchEnabled, refreshWebSearchToggle; also re-exports setChatNudge and updateChatNudge from chat-nudge.js for compatibility.
Window exports: assigned by chat-window-bindings.js for existing inline handlers and cross-module callbacks.
chat-nudge.js
Chat FAB nudge badge state. Owns nudge stage persistence, per-profile dismissal, badge/pulse DOM updates, and the profile/API/data/context card readiness check used by startup, settings, onboarding, DNA import, and panel-open flows.
Key exports: setChatNudge, dismissCurrentChatNudge, updateChatNudge
Window exports: assigned by chat-window-bindings.js for existing inline handlers and cross-module callbacks.
chat-onboarding.js
Chat-first onboarding helpers. Owns the provider quiz render helper, onboarding progress crumbs, profile/location/cycle/supplement handlers, lab-import CTA behavior, context-card nudge callback, and prompt CTA helper. It receives renderChatMessages, sendChatMessage, closeChatPanel, and nudge callbacks from chat-window-bindings.js through configureChatOnboarding() so it can update the shared chat UI without importing chat UI modules directly.
Key exports: configureChatOnboarding, useChatPrompt, requestOnboardingLabImportProvider, startOnboardingLabImport, _renderOnboardCrumbs, _renderProviderQuiz, _countFilledCards, setChatProfileSex, saveChatProfile, saveChatLocation, onboardHeightUnitChanged, saveChatPeriod, addChatSupplement, removeChatSupplement, setProviderQuizBranch, backToProviderQuiz, skipProviderSetup, skipOnboardingExtras, showCycleNoMensesOptions, showCyclePeriodEntry, saveCycleStatus, _updatePeriodBtn, onContextCardSaved
Window exports: assigned by chat-window-bindings.js for existing inline handlers and context-cards.js callbacks.
chat-discussion.js
Multi-persona discussion public barrel. Re-exports discussion flow handlers from chat-discussion-flow.js, callback configuration from chat-discussion-callbacks.js, UI compatibility helpers from chat-discussion-ui.js, and persona/thread state helpers from chat-discussion-state.js.
Key exports: configureChatDiscussion, getThreadPersonaCount, updateDiscussButton, getCurrentDiscussionState, sendDiscussionUserTurn, restoreDiscussionContinuePrompt, showDiscussContinuePrompt, removeDiscussContinuePrompt, cleanupDiscussionState, startDiscussion, startDiscussionFromPicker, continueDiscussion, endDiscussion
Window exports: assigned by chat-window-bindings.js for existing inline handlers and chat-threads.js callbacks.
chat-discussion-flow.js
Multi-persona discussion public user-action handlers. Owns manual-message entry, Continue, Discuss, and picker-start actions. It delegates cleanup/completion to chat-discussion-lifecycle.js, turn execution to chat-discussion-turns.js, and picker/prompt DOM through chat-discussion-ui.js.
Key exports: sendDiscussionUserTurn, restoreDiscussionContinuePrompt, showDiscussContinuePrompt, cleanupDiscussionState, startDiscussion, startDiscussionFromPicker, continueDiscussion, endDiscussion
Window exports: none directly; chat-discussion.js re-exports the public handlers and chat-window-bindings.js assigns the compatibility handlers.
chat-discussion-lifecycle.js
Discussion cleanup and completion helpers. Owns active-discussion restore, continuation prompt persistence, transient UI cleanup, explicit end lifecycle, original-persona restore, Discuss button/header refresh, and post-round Continue prompt handoff.
Key exports: restoreDiscussionContinuePrompt, showDiscussContinuePrompt, cleanupDiscussionState, endDiscussion, finishDiscussionRound
Window exports: none directly; chat-discussion-flow.js re-exports the public lifecycle handlers.
chat-discussion-turns.js
Discussion turn execution helpers. Owns continuation round dispatch, first debate turn dispatch, single joined-persona turn dispatch, joined-persona marker insertion, thread-bound discussion state persistence, and round completion handoff.
Key exports: runDiscussionContinuation, runSingleDiscussionTurn, runDiscussion
Window exports: none.
chat-discussion-callbacks.js
Discussion callback bridge. Owns configureChatDiscussion() and the callback wrappers that let discussion rounds reuse chat-send streaming state, send-button mode, transcript rendering, and typewriter behavior without importing chat-send.js.
Key exports: configureChatDiscussion, getChatAbortController, setChatAbortController, renderChatMessages, setSendButtonMode, createDiscussionTypewriter
Window exports: none directly; chat-discussion.js re-exports configureChatDiscussion for chat-window-bindings.js.
chat-discussion-round-runner.js
Discussion round execution loop. Owns per-persona iteration, streaming API calls, abort-controller/send-button state, auto-message insertion, typewriter updates, final assistant message persistence, usage footnotes, and modal-aware round error rendering.
Key exports: runDiscussionRound
Window exports: none.
chat-discussion-round-prompts.js
Discussion round prompt helpers. Owns the default follow-up prompt, initial-analysis prompt, joined-persona prompt, auto-message shape, joined-persona marker shape, and the first-turn versus rebuttal prompt selection logic.
Key exports: DEFAULT_DISCUSS_PROMPT, INITIAL_DISCUSS_PROMPT, DISCUSSION_JOIN_PROMPT, hasExistingDiscussionResponses, getDiscussionPromptText, buildDiscussionAutoMessage, buildDiscussionJoinMessage
Window exports: none.
chat-discussion-round-request.js
Discussion round API request helpers. Owns lab-context and lens enrichment, active personality prompt assembly, provider/model/web-search snapshots, tagged history messages, assistant message metadata, and usage tracking for multi-persona rounds.
Key exports: buildDiscussionRoundRequest, buildDiscussionAssistantMessage, trackDiscussionUsage
Window exports: none.
chat-discussion-round-state.js
Thread-bound discussion round persistence helpers. Owns origin-thread activity checks, discussion metadata writes, active-thread repaint handoff, and off-thread history persistence during streaming rounds.
Key exports: isRoundThreadActive, persistDiscussionThreadState, renderRoundMessages, saveRoundChatHistory
Window exports: none.
chat-discussion-round-view.js
Live discussion round DOM helpers. Owns typing indicators, persona labels, streamed assistant message nodes, final markdown replacement, usage footnotes, and active-thread-only error rendering for multi-persona rounds.
Key exports: createDiscussionTypingIndicator, createDiscussionPersonaLabel, appendRoundPersonaLabel, createDiscussionAiMessage, renderFinalDiscussionMessage, appendDiscussionUsageFootnote, renderDiscussionRoundError
Window exports: none.
chat-discussion-ui.js
Multi-persona discussion button and continuation prompt controls. Owns the Discuss button visibility/add-persona state and transient state handoff used by continueDiscussion() and endDiscussion(). Re-exports picker helpers from chat-discussion-picker.js so existing discussion flow imports stay stable.
Key exports: updateDiscussButton, showDiscussContinuePrompt, removeDiscussContinuePrompt, removeDiscussPersonaPicker, readDiscussPersonaPickerSelection, showDiscussPersonaPicker
Window exports: none directly; chat-discussion.js wraps/re-exports public controls and chat-window-bindings.js assigns the compatibility handlers.
chat-discussion-picker.js
Multi-persona discussion picker controls. Owns persona picker markup, active-persona locking, checkbox limiting, and picker selection reads.
Key exports: removeDiscussPersonaPicker, readDiscussPersonaPickerSelection, showDiscussPersonaPicker
Window exports: none.
chat-discussion-state.js
Multi-persona discussion state helpers. Owns per-thread active discussion detection, history fallback persona collection, current-thread lookup, unique assistant-persona counts, and current-thread discussion lifecycle metadata.
Key exports: getThreadPersonaCount, collectDiscussionPersonas, getCurrentThread, clearCurrentDiscussionThreadState, reopenCurrentDiscussionThread, getCurrentDiscussionState
Window exports: none directly; chat-discussion.js re-exports the public count/state helpers and chat-window-bindings.js assigns them.
chat-personalities.js
Chat personality storage, personality picker rendering, custom persona editor, AI-powered persona generation, and chat header title/model status. The module imports thread index helpers directly and calls back to window.renderChatMessages?.() for the two places that need to repaint chat content without creating a chat.js import cycle.
Key exports: getActivePersonality, getCustomPersonalities, saveCustomPersonalities, getCustomPersonality, getCustomPersonalityText, pickPersonaIcon, setChatPersonality, loadChatPersonality, updateChatHeaderTitle, updateChatHeaderModel, updateSummaryButton, updatePersonalityBar, togglePersonalityBar, generateCustomPersonality, saveCustomPersonality, startNewCustomPersonality, editCustomPersonality, deleteCustomPersonality, autoResizePersonaTextarea, markPersonalityDirty, snapshotPersonalityClean
Window exports: assigned by chat-window-bindings.js for existing inline handlers and cross-module callbacks.
chat-history.js
Thread-aware chat message persistence and clearing. The module owns the legacy storage key helper, encrypted/plain thread message load/save, thread metadata updates, saved-summary cleanup, and the clear-history confirmation flow. It uses window.renderChatMessages?.() and window.updateDiscussButton?.() callbacks for repaint/discussion hooks that would otherwise create a chat.js import cycle.
Key exports: getChatStorageKey, loadChatHistory, saveChatHistory, clearChatHistory
Window exports: assigned by chat-window-bindings.js for existing inline handlers and chat-threads.js callbacks.
chat-thread-search.js
Thread rail message-content search and match highlighting. It owns the debounced per-thread content search, encrypted/plain message reads, result rendering, cache invalidation, jump-to-result behavior, and in-message mark/highlight cleanup while receiving thread key, rail render, and switch callbacks from chat-threads.js.
Key exports: configureChatThreadSearch, filterThreadList, invalidateThreadContentCache, jumpToSearchResult
Window exports: re-exported and assigned by chat-threads.js for existing inline handlers.
chat-actions.js
Chat message action bar rendering and message-level handlers. The module owns Regenerate, Copy, and context-details toggle behavior while calling back to window.renderChatMessages?.(), window.sendChatMessage?.(), and window.isChatStreaming?.() to avoid importing the streaming/rendering module.
Key exports: buildActionBar, regenerateLastMessage, copyMessage, toggleContextDetails
Window exports: assigned by the module directly and re-exported by chat.js for existing inline handlers.
chat-icons.js
Shared chat SVG icon strings and icon-button DOM helper extracted from chat.js. Keeps action buttons and streaming send/stop button state changes using the same symbols without keeping SVG construction code in the chat orchestration module.
Key exports: CHAT_ICON_COPY, CHAT_ICON_REFRESH, CHAT_ICON_EDIT, CHAT_ICON_X, setIconButtonContent
Window exports: none
chat-attestation.js
Venice E2EE attestation display helpers shared by the chat header and assistant-message cost footnotes. Keeps lock glyph, attestation tooltip, and verified/failed mark formatting out of the chat orchestration module.
Key exports: attestationTooltip, e2eeLockHTML, e2eeLockFootnote
Window exports: none
chat-continuation.js
Response limit detection and automatic continuation wrapper for chat and discussion calls. Centralizes token-headroom constants, incomplete-response heuristics, continuation prompt construction, and usage merging.
Key exports: CHAT_RESPONSE_MAX_TOKENS, callChatAPIWithContinuation, isAIResponseTruncated, responseLimitNote
Window exports: none
chat-prompt-context.js
Pure prompt/message helpers shared by direct chat sends and multi-persona discussion rounds. Centralizes persona prompt additions, cross-persona API-message tagging, web-search/E2EE system hints, system-prompt assembly, and persisted lens-source serialization.
Key exports: buildPersonalityPrompt, buildMultiPersonaInstruction, buildTaggedChatMessages, buildWebSearchHint, buildChatSystemPrompt, serializeLensSources, attachLensSources
Window exports: none
chat-summaries.js
Conversation summary generation, saved-summary profile storage, and summary modal actions extracted from chat.js.
Key exports: summarizeThread, renderSavedSummaries, viewSavedSummary, deleteSavedSummary, closeSummaryModal, copySummary, downloadSummary, printSummary
Window exports: assigned by chat-window-bindings.js for existing inline handlers.
settings.js
Settings modal shell with profile, display, AI, privacy, data, wearables, and Agent Access tabs. Delegates AI provider panels to provider-panels.js, wearables rows to wearables-settings-panel.js, sync controls to settings-sync-panel.js, and Agent Access rendering/actions to settings-agent-access-panel.js.
Key exports:
openSettingsModal()/closeSettingsModal()initSettingsModelFetch()— fetches model lists for all providers on modal opensaveProfileSettings()— saves sex, DOB, location from the Profile sectionsetUnitSystem(system)—'EU'|'US'
openSettingsModal, closeSettingsModal, saveProfileSettings, setUnitSystem, setAIProvider, startTour
settings-sync-panel.js
Settings subpanel module for cross-device sync. Owns the Settings → Data sync section, sync setup/restore modal, mnemonic and relay controls, and delegates Settings → Agent Access rendering/actions to settings-agent-access-panel.js.
Key exports:
renderSyncSection()— renders the Settings → Data sync panelrenderMessengerSection()— compatibility export that renders the Settings → Agent Access panel throughsettings-agent-access-panel.jshydrateSettingsSyncPanel()— loads mnemonic and relay status after the settings modal is paintedshowSyncSetupModal()— opens the cross-device sync setup wizard directly; used by the dashboard data-protection picker
showSyncSetupModal, toggleSync, toggleMnemonicVisibility, copyMnemonic, saveSyncRelay, openRestoreMnemonicDialog, closeRestoreMnemonicDialog, confirmRestoreMnemonic, closeSyncSetup, syncSetupNew, syncSetupRestore, syncSetupBack, syncSetupDoRestore, syncSetupDone, toggleMessenger, toggleMessengerToken, copyMessengerToken, regenerateMessengerToken
settings-agent-access-panel.js
Settings → Agent Access renderer and action handler. It owns the enable/disable state, synced Agent Access metadata, read-only relay token display, local context-key display, wearable daily-series window, and the one-paste setup-command builder for supported MCP clients.
Key exports:
renderMessengerSection()— renders the Agent Access settings panel, including the target-client chip groupbuildAgentAccessSetupCommand(client)— builds the privategbsetup_v1_...bootstrap command forhermes,openclaw,claude-code,claude-desktop,cursor,cline, orcodexhandleMessengerAction(action, el)— delegated action handler for enabling, regenerating, copying secrets, copying setup commands, and series-window changestoggleMessengerToken()/copyMessengerToken()/regenerateMessengerToken()— compatibility actions for legacy window bindings
feedback.js
In-app feedback modal.
Key exports:
openFeedbackModal()/closeFeedbackModal()submitFeedback()— validates and submits feedback (bug report or feature request)
openFeedbackModal, closeFeedbackModal, submitFeedback
nav.js
Sidebar navigation, profile switcher, and mobile sidebar shell.
Key exports:
buildSidebar(data)- renders Home, Lenses, Tools, and lab category navigation with marker countsfilterSidebar()- filters lab categories and keeps top-level app routes visible during searchtoggleNavGroup(groupId)- expands/collapses sidebar category groupsrenderProfileDropdown()/renderProfileButton()- profile switcher UIopenRecommendationsFromSidebar()- compatibility helper that routes to the dedicatedrecommendationspage
buildSidebar, filterSidebar, toggleNavGroup, renderProfileDropdown, renderProfileButton, toggleMobileSidebar, closeMobileSidebar, openRecommendationsFromSidebar
Layer 6 — Orchestration
views-router.js
Route validation, per-profile last-view persistence, mobile tab sync handoff, and element-anchor scroll preservation. views.js creates the concrete navigator by passing render handlers into createNavigate().
Key exports:
createNavigate({ routeHandlers, syncMobileBottomNav })— builds the app-levelnavigate()function without importing page renderersgetInitialView()— restores the active profile’s last valid route, falling back todashboardisKnownRoute(route, data?)— validates fixed routes and data-backed lab category routes
lens-pages.js
Dedicated page renderers for Labs, Genome, Body, Insight, and Recommendations. The module receives dashboard, recommendation, and lens shell helper functions from views.js through createLensPageHandlers() so page rendering can move out of the main views module without creating new import cycles.
Key exports:
createLensPageHandlers(deps)— returnsshowLabs,showGenomeLens,showBodyLens,showInsightLens, andshowRecommendations
dashboard-page-view.js
Dashboard route shell and page-level dashboard orchestration. dashboard-view-composition.js creates it with createDashboardPageView() after wiring dashboard widget renderers, controls, and registry helpers, so the dashboard route can live outside the main compatibility module without importing the widget control layer directly.
Key exports:
createDashboardPageView(deps)— returnsshowDashboard(data?); owns the populated dashboard shell, empty welcome/demo state, import drop-zone setup calls, mobile dashboard handoff, focus-card hydration, context-dot hydration, and first-visit tour triggers
dashboard-view-composition.js
Dashboard route, widget, mobile handoff, marker-modal, and lens-shell composition wiring. views.js creates this layer once and keeps compatibility facades, while this module wires dashboard-page-view.js, dashboard-widgets.js, dashboard-widget-controls.js, dashboard-widget-renderers.js, and mobile dashboard dependencies together.
Key exports:
createDashboardViewComposition(deps)— returnsshowDashboard, dashboard widget control handlers, recommendation helpers, and dashboard render helpers needed by lens pages and recommendation actions
lens-page-shell.js
Shared lens page chrome and ordering helpers used by views.js and lens-pages.js. The module owns lens headers, reorderable page widget wrappers, per-profile lens widget order persistence, page-section move controls, dashboard add/remove toggles, and the delegated action attributes/listener used by shared lens chrome.
Key exports:
configureLensPageShell(deps)— injects dashboard widget visibility helpers without importing dashboard modules directlyrenderLensHeader(title, subtitle, actions?)— renders the shared lens page headerrenderLensPageWidgets(route, widgets)/renderLensWidget(...)— render reorderable page widgets and their chromemoveLensPageWidget(route, id, direction)— persists per-profile page section order and refreshes the active routelensPageActionAttrs(action, attrs?)— builds escapeddata-lens-page-*attributes consumed by the shared delegated click listener
dashboard-widgets.js
Dashboard widget registry and persistence helpers. dashboard-view-composition.js supplies renderer functions from dashboard-widget-renderers.js to createDashboardWidgetRegistry() so widget metadata, defaults, availability gates, per-profile widget preferences, custom marker widget IDs, and visible-entry generation can live outside the main views module.
Key exports:
createDashboardWidgetRegistry(renderers, opts?)— returns dashboard widget definitions plus preference/order helpersDASHBOARD_WIDGET_SOURCE_ORDER— Lens/source ordering for the widget pickerDASHBOARD_WIDGET_DEFAULT_IDS— new-profile dashboard default orderDASHBOARD_MANUAL_BIOMETRIC_METRICSanddashboardBiometricSelectionKey()— biometrics widget selection helpers
dashboard-widget-controls.js
Dashboard widget picker, widget chrome, layout actions, and drag/reorder controls. dashboard-view-composition.js creates the control layer with registry, marker, and biometrics dependencies; views.js re-exports the public handlers for existing window.* integrations.
Key exports:
createDashboardWidgetControls(deps)— returns render helpers and dashboard widget action handlers
dashboard-widget-renderers.js
Dashboard widget body renderers and shared recommendation helpers. dashboard-view-composition.js creates the renderer layer with Light helper and mobile-summary dependencies, then passes the returned renderers to dashboard-widgets.js, dashboard-widget-controls.js, and lens-pages.js.
Key exports:
createDashboardWidgetRenderers(deps)— returns dashboard body renderers, dashboard context builders, biometrics helpers, custom marker renderer support, and recommendation helper functions
category-view-renderers.js
Category chart card, table, heatmap, and fatty-acid profile renderers. category-page-view.js calls these helpers for category route content, while views.js imports and re-exports them so existing module and window.* integrations stay stable.
Key exports:
renderChartCard(id, marker, dateLabels)— renders one category/dashboard marker card and registers it for the detail modalrenderTableView(cat, dateLabels, categoryKey, dates)/renderHeatmapView(cat, dateLabels, dates, categoryKey)— render category table shells with empty-value add affordancesrenderFattyAcidsView(cat, categoryKey)/renderFattyAcidsCharts(cat)— render the single-date fatty-acid profile cards and bar chart
category-page-view.js
Category route shell and view-mode orchestration. The module owns showCategory(), switchView(), category card sorting, range-toggle order preservation, chart hydration, and chart-card recommendation loading. It depends on category-view-renderers.js for HTML fragments and keeps views.js as a thin router/compatibility facade.
Key exports:
showCategory(categoryKey, data?)— renders the category header, view tabs, date/layer controls, chart grid, empty marker affordances, and saved table/heatmap modeswitchView(view, categoryKey, btn)— switches between chart, table, and heatmap modes, updates tab ARIA state, destroys stale charts, and rehydrates charts when needed
category-customization.js
Category and marker display override helpers. The module owns category rename, marker rename/revert, the emoji picker, and category icon override persistence while views.js keeps compatibility exports and injects navigation via configureCategoryCustomization().
Key exports:
configureCategoryCustomization(deps)— injects the app-levelnavigate()function without importingviews.jsrenameCategory(categoryKey)/renameMarker(id)/revertMarkerName(id)— persist display-name overrides intoimportedData.categoryLabelsandimportedData.markerLabelsshowEmojiPicker(anchorEl, callback, opts?)— shared category/custom-marker emoji picker used by category views and the marker creation modalchangeCategoryIcon(categoryKey)— persistsimportedData.categoryIconsoverrides and mirrors custom marker category icon metadata
views.js
Tool page routing and compatibility exports. Dashboard composition lives in dashboard-view-composition.js; dashboard route shell lives in dashboard-page-view.js; dashboard widget body renderers live in dashboard-widget-renderers.js; recommendation action handlers live in recommendation-actions.js; category route orchestration lives in category-page-view.js; category card/table/heatmap renderers live in category-view-renderers.js; category display overrides live in category-customization.js; the Light page shell lives in light-page-view.js; Light channel pills and drill-down panels live in light-channel-view.js; shared lens page chrome lives in lens-page-shell.js; public navigation and lens page functions remain exported here for compatibility, backed by views-router.js and delegated to route modules where applicable.
Key exports:
navigate(section, params)— router facade created fromviews-router.js; calls the appropriate render functionshowDashboard(data?)- compatibility facade backed bydashboard-view-composition.jsanddashboard-page-view.js; renders the customizable widget dashboard whose default widget order starts with Biological Coherence, Current Focus, Current Priority, Quick Markers, Key Trends, Recommended Next Steps, Profile Context, Biometrics Overview, Biological Age, Metabolic Flexibility, and Cycle when availableshowLabs(data?),showGenomeLens(),showBodyLens(),showInsightLens(data?),showRecommendations(data?)- compatibility facades delegated tolens-pages.jsshowCategory(categoryKey, data?)- compatibility facade imported fromcategory-page-view.jsshowLight(data?),renderLightTodayStrip(),renderLightChannelsLive()- compatibility facades imported fromlight-page-view.jsshowCompare(data?)/showCorrelations(data?)- focused tool pages- Dashboard widget controls: compatibility facades backed by
dashboard-widget-controls.js, includingopenDashboardWidgetPicker(),toggleDashboardOrganizeMode(),resetDashboardWidgets(),clearDashboardWidgets(),addDashboardWidgetFromLens(), andremoveDashboardWidgetFromLens() showDetailModal(markerKey, data?)— opens the marker detail modal
navigate, showDashboard, showLabs, showGenomeLens, showBodyLens, showInsightLens, showRecommendations, showLight, showCategory, showDetailModal, dashboard widget controls, and recommendation page helpers (openRecommendationDetail, discussRecommendation, saveRecommendation, dismissRecommendation)
recommendation-actions.js
Recommendation modal and action handlers shared by dashboard cards and the Recommendations page. It keeps option-detail rendering, chat prompts, saved/bookmarked state, and dismissed state out of the main route facade.
Key exports:
createRecommendationActions(deps)— returnsopenRecommendationDetail(),discussRecommendation(),saveRecommendation(), anddismissRecommendation()
light-page-view.js
Light & Sun page shell, Light Today strip, dashboard Light channel pills, Light session log actions, page widget assembly, and async population of page-only Light workbench sections. It imports shared lens chrome from lens-page-shell.js, condition rendering from light-conditions-now.js, session history from light-sessions-view.js, and channel rows/suggestions from light-channel-view.js.
Key exports:
showLight(data?)— renders the reorderable Light & Sun page widgetsrenderLightTodayStrip()— legacy compact Light strip used by embedded/welcome surfacesrenderLightChannelsLive()— refreshes the live channel-pills slot after session updatesrenderDashboardLightChannelPills()/renderLightSessionLogActions()— dashboard widget helper bodies shared throughdashboard-widget-renderers.js_expandLightToolsSection()— compatibility handler for expanding the collapsed Light tools placeholder
light-channel-view.js
Light channel pill rows, seven-day sparklines, dashboard-to-Light channel navigation, per-channel drill-down panels, citations, source mix, and channel suggestions. light-page-view.js imports the render helpers; views.js keeps the legacy window._toggleChannelDetail / window._openChannelOnLightPage wiring for inline handlers and dashboard widgets.
Key exports:
mergeTotals(a, b)— combines sun and device channel totalsrenderChannelPills(totals7d, totals30d)— renders the interactive Light page channel row and detail slot_toggleChannelDetail(channelKey)/_openChannelOnLightPage(channelKey)— compatibility handlers for expanding channel detail panelsrenderSuggestion(totals7d)— fallback channel-guidance copy when AI synthesis is unavailable
main.js
Thin module entry point. Imports startup feature side effects, then starts the startup orchestrator.
Responsibilities:
- Imports
app-feature-modules.jsfor startup-loaded feature side effects and window exports - Calls
startApp()fromstartup-orchestrator.js
app-feature-modules.js
Startup-loaded feature side-effect imports extracted from main.js. This module preserves the previous feature import order while keeping main.js focused on startup orchestration. Foundation/privacy imports are grouped behind app-foundation-modules.js; the Health & Data feature cluster is grouped behind app-health-data-modules.js; the Light & Sun feature cluster is grouped behind app-light-sun-modules.js; the import/export feature cluster is grouped behind app-data-io-modules.js; the AI/chat/settings feature cluster is grouped behind app-ai-interaction-modules.js; the UI shell feature cluster is grouped behind app-ui-shell-modules.js.
Key exports: none
Window exports: none directly; imported feature modules attach their existing compatibility handlers.
app-foundation-modules.js
Startup-loaded foundation/privacy side-effect imports extracted from app-feature-modules.js. This module preserves the previous schema/constants/utils/pii import order while keeping the top-level feature list as named startup clusters.
Key exports: none
Window exports: none directly; imported foundation modules attach their existing compatibility handlers.
app-health-data-modules.js
Startup-loaded Health & Data feature side-effect imports extracted from app-feature-modules.js. This module preserves the previous charts/notes/supplements/recommendations/cycle/context/DNA/wearables import order while keeping the top-level feature list easier to scan.
Key exports: none
Window exports: none directly; imported Health & Data modules attach their existing compatibility handlers.
app-light-sun-modules.js
Startup-loaded Light & Sun feature side-effect imports extracted from app-feature-modules.js. This module preserves the previous Light & Sun import order while keeping the top-level feature list easier to scan.
Key exports: none
Window exports: none directly; imported Light & Sun modules attach their existing compatibility handlers.
app-data-io-modules.js
Startup-loaded import/export feature side-effect imports extracted from app-feature-modules.js. This module owns the compatibility startup load for data export/import handlers while keeping the top-level feature list as named startup clusters.
Key exports: none
Window exports: none directly; imported data I/O modules attach their existing compatibility handlers.
app-ai-interaction-modules.js
Startup-loaded AI/chat/settings feature side-effect imports extracted from app-feature-modules.js. This module preserves the previous chat/image/settings/lens/provider helper import order while keeping the top-level feature list easier to scan.
Key exports: none
Window exports: none directly; imported AI interaction modules attach their existing compatibility handlers.
app-ui-shell-modules.js
Startup-loaded UI shell feature side-effect imports extracted from app-feature-modules.js. This module preserves the previous feedback/tour/touch-tooltip/client-list/views import order while keeping the top-level feature list easier to scan.
Key exports: none
Window exports: none directly; imported UI shell modules attach their existing compatibility handlers.
startup-orchestrator.js
Startup global wiring and phase ordering. Runs once, installs app-wide startup hooks, and registers the DOMContentLoaded startup sequence.
Responsibilities:
- Sets the
_getActiveProfileIdstartup global - Installs lazy EMF window handlers through
emf-facade.js - Installs app-wide event and refresh wiring through
app-event-listeners.js - Delegates encryption, backup, and meteo bootstrap to
startup-foundation.js - Initializes startup profile data
- Delegates startup service boot and post-profile maintenance to
startup-maintenance.js - Delegates wearable/OpenRouter callback routing to
startup-oauth-callbacks.js - Delegates first-render UI bootstrap to
startup-ui.js
startApp()— idempotently installs startup globals/listeners and registers the startup sequence
_getActiveProfileId
emf-facade.js
Lazy window facade for the EMF assessment module extracted from main.js. It installs async window.* handlers for EMF editor and assessment actions, then imports emf.js on first use and replaces the facade handlers with the real module exports.
Key exports:
EMF_LAZY_WINDOW_FUNCTIONS— list of EMF window handlers covered by the lazy facadeinstallEMFLazyFacade()— installs lazy handlers during app startup
EMF_LAZY_WINDOW_FUNCTIONS
startup-foundation.js
Blocking startup foundation extracted from main.js: encryption unlock, decrypted meteo config cache hydration, cross-tab broadcast setup, and folder backup handle restoration.
Key exports:
initializeStartupFoundation()— runs the blocking security/storage bootstrap before wearable services or profile data load
startup-profile.js
Profile startup bootstrap extracted from main.js: legacy v1 profile migration, encrypted profile-cache warmup, active-profile imported-data load, and unit/sex/range/DOB display state.
Key exports:
initializeProfileData()— creates the default profile for legacy users, migrates old imported data through encrypted storage, warms the profile cache, setsstate.currentProfile, and loads active imported data before OAuth callbacks can persist profile-scoped dataapplyProfileDisplayState()— applies saved units/range mode plus sex/DOB metadata tostateand the startup toggle controls
startup-oauth-callbacks.js
Startup OAuth callback routing extracted from main.js. Wearable callbacks run first after profile load; if they do not consume the URL code, OpenRouter OAuth handles the same ?code=/state pair.
Key exports:
handleStartupOAuthCallbacks()— delegates wearable OAuth callback handling, exchanges OpenRouter codes with state verification, stores the OpenRouter key, switches the active AI provider, and opens chat after init
startup-maintenance.js
Non-blocking startup maintenance extracted from main.js: wearable runtime config/scheduler boot, sun session self-heal, light-device preset hydration, and legacy biometrics migration.
Key exports:
initializeStartupServices()— starts wearable runtime config loading and scheduler setup before profile data loadsrunPostProfileStartupMaintenance()— schedules post-profile maintenance jobs without blocking OAuth callbacks or first render
startup-ui.js
First-render UI bootstrap extracted from main.js: profile display state, theme, footer version, sidebar, sync indicator, initial navigation, deferred sync/catalog warmup, changelog, startup nudges, deferred settings/chat opens, header chrome, chat attachment handlers, and file-picker import binding.
Key exports:
renderStartupUI()— runs the initial UI render and schedules non-blocking startup UI work after profile/OAuth startup completes
app-event-listeners.js
App-wide browser event wiring that used to live in main.js: modal wheel guards, backdrop click handling, global role-button keyboard activation, Escape/Tab modal behavior, app shortcuts, and the registerRefreshCallback() bridge back into navigate(state.currentView || 'dashboard').
Key exports:
installGlobalEventListeners()— idempotently installs document-level modal, keyboard, shortcut, and click handlersregisterAppRefreshCallback()— registers the data refresh callback that rebuilds sidebar state and re-renders the active route
tour.js
Generic spotlight tour engine plus the app tour and cycle tour configurations.
Key exports:
runTour(steps, storageKey, auto)— generic engine: creates#tour-overlay,#tour-spotlight,#tour-tooltip; filters steps with missing targets; navigates with Back/Next/Skip/DonestartTour(auto)— launches the 7-step app tour (auto=truechecks completion flag first)startCycleTour(auto)— launches the 8-step cycle-specific tourendTour()— removes tour DOM elements, stores completion flagCYCLE_TOUR_STEPS— array of 8 step configs for the cycle tour
startTour, startCycleTour, endTour
changelog.js
What’s New modal triggered on version bump so users see what changed after each PWA update.
Key exports:
APP_VERSION— number matching the SW cache version (e.g., 53)openChangelog(showAll)— renders and shows the modal;showAll=trueshows all entries,falseshows latest 3closeChangelog()— hides modal, marks current version as seen in localStoragemaybeShowChangelog()— auto-trigger: shows modal iflabcharts-changelog-seen!==APP_VERSION
openChangelog, closeChangelog, maybeShowChangelog
client-list.js
Client List modal for managing multiple profiles.
Key exports:
openClientListModal()/closeClientListModal()— modal lifecyclerenderClientList(query?, sortBy?)— renders searchable, sortable profile list with inline create/edit form- Per-profile actions: archive, flag, pin, delete, per-client export
openClientListModal, closeClientListModal, createClientInline, saveClientInline, toggleArchiveClient, toggleFlagClient, togglePinClient, deleteClient, exportClientJSON
recommendations.js
Supplement, lifestyle, light-device, and EMF affiliate recommendations driven by a lazy-loaded catalog. Region-aware: products + URLs + coupons are filtered by user country via a single hierarchy chain (CZ → EU → INTL etc.). The global Recommendations page is rendered by lens-pages.js, while dashboard-widgets.js registers the dashboard surface and dashboard-widget-renderers.js owns its dashboard renderer; this module owns catalog loading, slot rendering, disclosure state, product filtering, and DNA/wearable slot helpers.
Key exports:
loadCatalog()— lazy-loadsdata/recommendations.jsonon first callgetUserRegion()— derives region code (CZ/SK/DE/AT/EU/US/INTL) from profile countryregionLookupChain(region)— returns the lookup chain (most-specific → INTL); used by both product visibility filter and per-region map resolutiongetProductsForSlot(catalog, slotKey, region)— region-filtered products_resolveCouponForRegion,_resolveHomepageForRegion,_resolveProductUrlForRegion— pick from per-region maps using the chain_addUTMParams(url, content, campaign)— partner-dashboard attributionrenderRecommendationSection(slotKey, opts)— renders the “What can help” section in the detail modalrenderEMFMeterRecs(catalog, opts)/renderEMFMitigationRecs(catalog, tags, opts)— EMF panel surfaces
views.js, chat.js, context-cards.js)
crypto.js
Data encryption at rest and cross-tab sync.
Key exports:
encryptedSetItem(key, value)/encryptedGetItem(key)— AES-256-GCM via PBKDF2 passphrasegetEncryptionEnabled()/setEncryptionEnabled(bool)— encryption togglevalidatePassphrase(p)— checks 4 strength rules (8+ chars, lowercase, uppercase, special), returns{ valid, message }broadcastDataChanged(profileId)— BroadcastChannel message for multi-tab syncSENSITIVE_PATTERNS— array of localStorage key pattern strings that get encrypted
setEncryptionEnabled, changePassphrase, exportBackup, importBackup
backup.js
IndexedDB auto-backup, folder backup via File System Access API, and backup restore. Extracted from crypto.js.
Key exports:
scheduleAutoBackup()— debounced 60s trigger; saves up to 5 snapshots to IndexedDB + writes to folder backup if configuredbuildBackupSnapshot()— captures all importedData + per-profile preferencesloadBackupSnapshots()— async; populates the Backup & Restore section with IndexedDB snapshotsrestoreAutoBackup(id)— writes snapshot to localStorage, reloadssaveFolderBackup(snapshot)— writesgetbased-backup-latest.json+ daily dated snapshot to user-selected folder via File System Access API
restoreAutoBackup, pickBackupFolder, showBackupReminder
lab-context.js
Central AI context serializer. Extracted from chat.js.
Key exports:
buildLabContext()— serializes all lab entries + all 9 context cards + interpretiveLens + contextNotes + cycle data + notes into a structured AI context string
buildLabContext
markdown.js
Block-aware markdown parser for chat rendering. Extracted from chat.js.
Key exports:
renderMarkdown(text)— block-aware parser: headings, lists, code blocks, HR, paragraphs + inline formatting
renderMarkdown
provider-panels.js
AI provider settings behavior for the settings modal. Owns provider selection, key validation flows, provider model dropdown refresh, balances, and local-model advisor wiring. Imports provider-panel-renderers.js for provider-specific Settings → AI panel markup.
Key exports:
renderAIProviderPanel(provider)— returns the active provider configuration panel HTMLswitchAIProvider(provider)— persists provider choice and refreshes the settings panel- Provider key/model helpers for Venice, OpenRouter, Routstr, PPQ, Custom API, and local OpenAI-compatible servers
onclick attributes, including imported Routstr wallet handlers from provider-wallet-panels.js
provider-panel-renderers.js
Provider-specific Settings → AI panel markup for OpenRouter, Routstr, Venice, PPQ, Custom, and Local AI. Keeps static panel HTML and cached-model select markup separate from provider validation, balance polling, and local-model advisor behavior.
Window exports: none directly. renderAIProviderPanel() is re-exported and attached to window by provider-panels.js.
provider-wallet-panels.js
Routstr/Cashu wallet UI and node funding actions used inside the Routstr provider panel. Extracted from provider-panels.js so wallet deposit, withdrawal, seed backup/restore, mint switching, and node deposit/refund behavior are isolated from general provider key/model rendering.
Key exports:
configureRoutstrWalletPanels(callbacks)— injects provider-panel callbacks without introducing a circular module importroutstrWalletActionButtons(active)/buildRoutstrNodeActions(nodeUrl, hasKey, active)— render the wallet and node action controls used by the Routstr paneldoRoutstrWalletFund()/doRoutstrNodeDeposit()/doRoutstrNodeWithdraw()/ withdraw and restore helpers — Cashu wallet and Routstr node action handlers
provider-panels.js for legacy inline handlers.
provider-qr.js
Shared QR-code loader for provider payment surfaces.
Key exports:
ensureQRCode()— lazy-loads/vendor/qrcode-generator.jsand returns the globalqrcodefactory
lens.js
Knowledge Base / Interpretive Lens — RAG endpoint config + multi-query rewrite + dedicated modal. Two backends under one UI: 'in-browser' (transformers.js + OPFS via lens-local.js) and 'external-server' (user-configured URL + Bearer key).
Key exports:
hasLens()— true when a lens is configured AND has indexed contentqueryLens(hint, opts?)— single-query retrieval; routes to in-browser worker or remote server based on backendqueryLensMulti(hint, opts?)— multi-query orchestrator: rewrites the query into N=3 paraphrases via the active LLM, fans out toqueryLensfor each, fuses results with reciprocal-rank scoring (k=60). Falls back to single-query when no AI provider, when rewrite fails, when query is <3 words, or when the toggle is offgetLensConfig()/saveLensConfig(partial)/getLensKey()/saveLensKey(key)getLensSummary()— synchronous status object{configured, backend, displayName, docCount, chunkCount, multiQueryOn, aiAvailable}used by the dashboard KB rowopenKnowledgeBaseModal()/closeKnowledgeBaseModal()— dedicated modal that wrapsrenderCustomLensSection(). Replaces the previous Settings → AI inline sectionbuildLensSnippet(chunks, sourceName)— formats retrieved chunks for AI prompt injectiontestLensConnection()/clearLensCache()renderCustomLensSection()— full settings markup (URL/key inputs, backend toggle, library picker, ingest UI, multi-query toggle); rendered inside the KB modal_resetRewriteCache()/_fuseChunksRRFForTest()/_dedupeQueriesForTest()— test surface
hasLens, queryLens, queryLensMulti, buildLensSnippet, testLensConnection, clearLensCache, openKnowledgeBaseModal, closeKnowledgeBaseModal, plus all the in-modal save/toggle/library handlers
wearable-adapters.js
Canonical wearable-metric registry + per-vendor adapter registry. Source of truth for OAuth client IDs, redirect URIs, scopes, and metric → endpoint mappings.
Key exports:
ADAPTERS— array of{id, displayName, authType, oauth?, apiHost?, metrics, accountInfo?}for the 8 supported sources (Oura / Withings / Ultrahuman / WHOOP / Fitbit / Polar / Apple Health / manual)CANONICAL_METRICS—{id: {label, sub, unit, worseWhen}}for every metric the strip can renderDEFAULT_METRIC_ORDER— preferred order when multiple sources contributeadapterById(id)/visibleAdapters(connectedIds)/adapterSupportsMetric(adapterId, metricId)/metricsForSources(sourceIds)/canonicalMetric(id)applyOAuthOverrides(map)— merges a{adapterId: clientId}map into the runtime override store; called fromloadWearableRuntimeConfig()getOAuthClientId(adapterOrId)— returns the runtime override if set, falling back to the adapter’s hardcodedoauth.clientId. Every consumer reads through this helper so self-host overrides apply uniformly_resetOAuthOverrides()— test surface
wearables-connect.js
Connect/disconnect/backfill orchestration. OAuth dispatch table, scheduled stale-source sync, runtime config bootstrap.
Key exports:
OAUTH_DISPATCH—{adapterId: {begin, isCallback, complete, withFreshToken, fetchAccountInfo, fetchRange, displayName, postConnect?, commitAfterWrite?}}— generic OAuth orchestration tablebeginConnectOAuth(adapterId)— kicks off the auth flow; readsclientIdviagetOAuthClientId(adapter)handleOAuthCallbackOnLoad()— runs viastartup-oauth-callbacks.jsinit; readspending.clientIdfrom sessionStorage (set at begin time, NOT from runtime config)getConnection(adapterId)/listConnectedSources()/disconnectAdapter(adapterId)syncNow(adapterId, opts?)/forceBackfill(adapterId, days)initWearableScheduler()— visibility-change + 6h interval poll; awaitsruntimeConfigReady()before first sync to prevent race against override fetchloadWearableRuntimeConfig()— POSTs{wearable_runtime_config: true}to/api/proxy, applies the returned*_CLIENT_IDoverrides viaapplyOAuthOverrides. Memoized as a promise raced against a 1.5s soft timeout
Wearables vendor adapters
Each connected source ships as a pair:wearables-<vendor>.js (read API) + wearables-<vendor>-auth.js (OAuth dance). Apple Health and Manual skip the auth half — Apple is file-import only, Manual is fully local. Tokens never leave the device; sync-payload.js strips wearableConnections from the synced payload (and again on pull as defense-in-depth).
OAuth2 (server-side secret): wearables-oura.js + …-oura-auth.js, …-withings.js + …-withings-auth.js, …-ultrahuman.js + …-ultrahuman-auth.js, …-polar.js + …-polar-auth.js. Secrets live in .env.local + /api/proxy.
OAuth2 PKCE (no secret): wearables-whoop.js + …-whoop-auth.js, wearables-fitbit.js + …-fitbit-auth.js. Code verifier + S256 challenge per the IETF spec.
No OAuth: wearables-apple-health.js (file-import — parseAppleHealthXml reads the export.xml from a Health zip), wearables-manual.js (logManualMetric / logManualBP + MANUAL_TAGS whitelist for what users can log by hand).
L1 storage + summary derivation: wearables-store.js (per-profile IndexedDB at labcharts-wearables-{profileId}; two-phase upsertDailyBatch), wearables-summary.js (L2 derivation; vendor sources read a 90-day window, while sparse manual rows read all history so older hand-entered BP/pulse/weight entries stay visible; write gate — 5% d7 shift / trend flip / 14d force-refresh / source flip / metric removal triggers).
UI surface: wearables.js (dashboard strip, source picker, reorder mode, empty-card manual-log forms, and legacy window facade), wearables-detail-modal.js (metric detail modal, Chart.js series, manual-entry list/add/delete, focus trap, EMF sleep nudge), wearables-formatters.js (shared value/date formatting), wearables-manual-form-ui.js (shared manual chip/note form snippets), wearables-settings-panel.js (Settings → Wearables rows, connect/sync/backfill/disconnect actions, Apple Health file-import UI, manual-source counts/delete action, strip visibility toggle), brand-assets.js (per-vendor logo registry — iconLight/Dark for in-app rows, signInLight/Dark for landing-site Connect buttons, mono SVG fallback while a vendor logo is gated).
Knowledge Base in-browser stack
lens.js is the dispatcher; the 4 sibling lens-local-* modules are the in-browser implementation. The dispatcher routes between in-browser and external-server backends per the user’s selection.
lens-local.js— main-thread shell: spawns a module worker, posts ingest/query/list/activate/delete messages, exposes a Promise-based API tolens.js.lens-local-worker.js— module worker. Loads transformers.js (currently from jsdelivr — seeupdate-vendor.shnotes), runs WebGPU embedding when available with WASM fallback, owns OPFS persistence (FileSystemSyncAccessHandle), library CRUD, MMR re-rank (λ namedMMR_LAMBDA), per-library model selection from a 4-model catalog.lens-local-utils.js— pure helpers:chunkText,mmrSelect, hashing, vector-pack helpers. Importable from both threads.lens-local-parsers.js— main-thread document parsers (PDF viapdfjs-loader.js, DOCX via mammoth, ZIP via JSZip, plus plain text/markdown/CSV).
Other recently-extracted modules
Not separately documented because their exports are best read from source — kept thin on purpose.chat-images.js— image attachment lifecycle (getPendingAttachments,clearAttachments, etc.). Owns the_pendingAttachmentsqueue. Extracted fromchat.jsin v1.21.9.chat-threads.js— conversation thread CRUD, list rendering, autoname,onChatSaveddebounce trigger. Extracted in v1.21.9.markdown.js— XSS-safe markdown rendering (applyInlineMarkdownfor spans,renderMarkdownfor full blocks). 34 dedicated XSS test assertions.lab-context.js— lab-data → AI-prompt context assembly; memoized via fingerprint that includes wearable summary, change history, and all 9 context cards.provider-panels.js— Settings → AI provider behavior, validation, balances, dropdown refresh, globals.provider-panel-renderers.js— Settings → AI per-provider panel markup (Venice / OpenRouter / Routstr / PPQ / Local AI / Custom).pdfjs-loader.js— cached dynamic import of vendored pdf.js ESM. PinsisEvalSupported: falsedefense-in-depth on everygetDocumentcall.sun-body-silhouette.js— anatomical sun-session body-region picker, stock-figure region-map hit testing, and async selection overlay. Re-exported bysun.jsfor compatibility.sun-active-session.js— quick-log/start modal, live active-session ticker, Simpson live-dose integration, and active-session compatibility handlers. Dependency-injected fromsun.jsso persistence and hydration stay in the owner module.sun-session-ui.js— saved sun-session row/detail rendering, detailed past-session modal, channel chips, delete, and edit-duration UI. Dependency-injected fromsun.jsso storage, hydration, and dose math stay in the owning module.light-device-setup-modal.js— add-device preset picker, custom-device form, and URL/photo AI spec extraction. Dependency-injected fromlight-devices.jsso device persistence and channel defaults stay in the owning module.light-device-session-modal.js— log/start light therapy device session modal; dependency-injected fromlight-devices.jsso session persistence and active timer state stay in the owning module.light-env-audits.js— saved Light Environment snapshots, audit comparison renderer, and audit-specific window handlers. Dependency-injected fromlight-env.jsso rooms/screens remain owned by the environment module.light-env-evening.js— canonical room after-sunset exposure helpers; normalizes legacy boolean room rows to numericeveningHoursAfterSunsetwhile leaving screeneveningUseAfterSunsetnumeric.light-tool-camera.js/light-tool-camera-modals.js— shared camera lock, row-banding, aiming guides, lux calibration, and the camera-backed Light tool modal flows. Dependency-injected fromlight-tools.jsso measurement persistence stays in the owning module.supplement-warnings.js/food-contaminants.js— keyword scanners that build “harm flag” lists for the AI context.emf.js— Baubiologie SBM-2015 EMF assessment as a sub-module of the Environment context card.sync.js— Public sync entry/barrel; exports sync lifecycle, actions, diagnostics, relay, identity, and cutover APIs while delegating dependency wiring tosync-configure.js.sync-configure.js— Sync subsystem dependency wiring; configures relay health, push/pull/subscription/tombstone/diagnostic/UI/action/recovery/reconcile modules and browser window bindings.sync-push.js— outbound profile push path, in-flight push watchdog, Phase 2 drift auto-revert, and Evolu profileData insert/update.sync-push-deltas.js— push-side per-row delta planning/application; walks DELTA_ARRAYS/MAPS/SCALARS before blob writes, advances snapshots after onComplete, and records delta telemetry.sync-pull.js— inbound pull orchestration and row loop; delegates one-time cleanup, active-profile UI refresh, and rebroadcast scheduling to helper modules.sync-pull-merge.js— pull row recovery/dedupe, importedData blob/per-row merge, wearable-token preservation, metadata-only genetics blob protection, and profile metadata merge helpers.sync-pull-maintenance.js— pull-path one-time migrations such as stale-sync-hashlocalStorage cleanup.sync-pull-active-refresh.js— active-profile in-memory update, migration, chat reload, sidebar rebuild, current-view refresh, toast, and sync-applied event after a pull.sync-pull-rebroadcast.js— pull-side rebroadcast gating, budget checks, push-pending guard, and delayed active-profile push scheduling.data-merge.js— importedData blob merge helpers, shared record freshness comparison, tombstone state merge, and sync-aware array mutation helpers (appendImportedArrayItem,replaceImportedArrayItem,deleteImportedArrayItem,deleteImportedArrayItems,clearImportedArray) used by feature modules so identity edits/deletes record the right tombstones before the next sync push.sync-cutover.js— readiness-gated Phase 2 lean-sync cutover enable/disable bridge over payload flags and delta readiness.sync-delta.js— per-row CRDT delta facade; config fan-out, apply helpers, and compatibility re-exports for planners, snapshots, merge, telemetry, and readiness.sync-delta-planners.js— push-side planner facade; configures shared planner dependency context and compatibility re-exports for array/map/scalar planners.sync-delta-planner-context.js— shared Evolu/itemRow query dependency access for push-side delta planners.sync-delta-array-planner.js— push-side array planner; diffs array items against snapshots and emits itemRow insert/update/tombstone ops with tombstone-storm protection.sync-delta-map-planner.js— push-side keyed-map planner; diffs keyed objects against snapshots, preserves original raw keys in payloads, and guards genetics SNP empty-map races.sync-delta-scalar-planner.js— push-side scalar planner; handles singleton fields, most-recent canonical row selection, and null-transition tombstones.sync-delta-snapshot.js— delta snapshot keying, reads, plannedAt-gated writes, and snapshot clear helpers.sync-delta-merge.js— pull-side itemRow grouping and merge-shape dispatch into importedData after blob merge.sync-delta-merge-shapes.js— pull-side row overlay facade; compatibility re-exports for array/map/scalar merge helpers.sync-delta-row-codec.js— shared itemRow payload decoder for pull-side delta merge helpers, including gzip envelope handling.sync-delta-array-merge.js— pull-side array row overlay helper; owns item tombstones, nested-path writes, dedupe, composite caps, and pull delta telemetry.sync-delta-map-merge.js— pull-side keyed-map row overlay helper; owns raw-key preservation, synth-id tombstones, proto guards, nested-path writes, and pull delta telemetry.sync-delta-scalar-merge.js— pull-side scalar row overlay helper; owns singleton LWW selection, null tombstones, dotted-path writes, genetics SNP preservation, and pull delta telemetry.sync-delta-registry.js— delta registry facade; compatibility re-exports for surfaces, per-surface config, and identity helpers.sync-delta-surfaces.js— DELTA_ARRAYS/MAPS/SCALARS importedData surface lists for per-row sync.sync-delta-surface-config.js— per-surface itemId/keyId overrides for array/map delta planners and pull overlays.sync-delta-id.js— shared per-row identity helpers, stable hash, allowlist guard, and proto-pollution key rejection.sync-delta-observability.js— delta observability facade; compatibility re-exports for telemetry, pull snapshots, readiness, and injected Evolu query access.sync-delta-observability-context.js— shared Evolu/itemRow query dependency access for delta observability helpers.sync-delta-pull-snapshot.js— in-memory pull-side row-count snapshots for Sync Diagnose delta replication checks.sync-delta-telemetry.js— per-push delta telemetry storage, aggregation, reset, and latest pull-snapshot reporting.sync-delta-readiness.js— Phase 2 cutover readiness checks across array/map/scalar delta surfaces.sync-apply.js— inbound sync apply helpers for AI provider settings and display prefs, with compatibility re-exports for chat apply helpers.sync-chat-apply.js— inbound chat thread/message application, chat delete tombstones, and local freshness locks that protect just-edited local chat from stale remote rows.sync-tombstones.js— remote profile delete propagation helpers, inbound tombstone application, batched-delete quarantine, and apply/reject pending tombstone actions for Settings.sync-messenger.js— Agent Access token/context-key helpers, owner-bound encrypted context writes, revoke helpers, and debounced lab-context push to the Agent Access context gateway.sync-environment.js— relay URL selection, relay connectivity probing, and browser capability checks for Evolu sync.sync-identity.js— BIP-39/QR lazy loaders plus mnemonic read/restore helpers for Evolu owner identity.sync-diagnostics.js— Evolu diagnostics facade; stable exports for configuration, row snapshots, and copy-text formatting.sync-diagnostics-context.js— Injected Evolu/query/subscription state accessors for sync diagnostics.sync-diagnostics-snapshot.js— Evolu row diagnostics snapshot assembly, including live/tombstone rows, active imported counts, delta telemetry, and lean-sync readiness.sync-diagnostics-text.js— Plain-text Sync Diagnose copy formatting for support/debug handoff.sync-diagnose-ui.js— Sync Diagnose modal lifecycle, copy snapshot handling, and compatibility re-exports for Diagnose action handlers.sync-diagnose-render.js— Pure Sync Diagnose panel/table markup for identity, relay health, relay storage, delta telemetry, lean-sync readiness, and local Evolu rows.sync-diagnose-actions.js— Sync Diagnose action facade; keeps the public imports stable while delegating to focused action modules.sync-diagnose-actions-context.js— Shared injected dependencies for Diagnose actions, including sync enable/restore, push, cutover toggles, and modal refresh.sync-diagnose-relay-actions.js— Sync Diagnose relay storage refresh and self-serve compaction handlers.sync-diagnose-identity-actions.js— Sync Diagnose identity rotation modal, BIP-39 mnemonic generation, QR display, copy fallback, and local apply flow.sync-diagnose-cutover-actions.js— Sync Diagnose telemetry reset plus lean-sync enable/backfill/disable handlers.sync-actions.js— user-triggered sync actions, all-profile initial push, and compatibility re-exports for save hooks and storage cleanup.sync-save-hooks.js— save/chat/profile-metadata debounce hooks, AI-setting push scheduling, per-profile timer cleanup, and profile importedData reads for initial push.sync-storage-cleanup.js— emergency sync storage compaction; clears model-list caches, trims oversizedchangeHistory, saves the active profile, and reports freed bytes.sync-ui.js— header sync badge, popover rendering, status subscription, and activity-log copy helpers.sync-payload-collectors.js— Local AI/chat/display settings collection for sync payloads, including synced setting allowlists and chat thread tombstone keys.sync-payload.js— Evolu wire-payload helpers; outbound envelope assembly, Phase 2 cutover payload shape, gzip envelope handling, inbound payload parsing, and local-only data stripping for wearable credentials and SNP map rows.sync-relay-health.js— Evolu relay helper boundary; client-side quota estimate, signed/self/owner-storageand/self/compact-ownercalls, and push-landed health verdict for the silent-reject detector.sync-state.js— in-memory sync status pub-sub, header badge display-state derivation, recent sync activity ring buffer, and per-profile rebroadcast budget guard.