Module Reference
Modules live underjs/. The app has hundreds of focused top-level JavaScript modules. This page is a guided implementation map, not a promise that every small hook, delegate, or helper file has its own long section. It is grouped by layer; lower layers have no dependencies on higher ones.
Layer 1 — Foundation
schema.js and marker-schema/
schema.js is the stable compatibility facade for the modular biomarker catalog, range registries, unit conversions, pricing, and environment thresholds. Category definitions and immutable marker identities are authored in category modules under marker-schema/, composed by marker-schema/index.js, and generated into marker-schema.js; contributors must not edit the generated file directly.
Key exports:
MARKER_SCHEMA— 196 core entries across 19 categories, including the 22-entrycalculatedRatioscategoryUNIT_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.fshCONTEXT_REFERENCE_RANGES/CONTEXT_OPTIMAL_RANGES— age-, sex-, and date-resolved guidance consumed by the active-data pipelineSPECIALTY_MARKER_DEFS— re-exported fromadapters.jsasADAPTER_MARKERS. Used bymigrateProfileData()andbuildMarkerReference()BUILTIN_MARKER_IDENTITIES,BUILTIN_MARKER_DOT_KEY_ALIASES,getBuiltinMarkerId(),getBuiltinMarkerDotKey(), andresolveBuiltinMarkerDotKey()— immutablegb:marker:*IDs plus current and legacy location compatibility exportsCHIP_COLORS— status → CSS color stringMODEL_PRICING— AI model pricing metadata, keyed by provider/model
marker-schema/index.js and marker-schema.js
marker-schema/index.js is the authoring composition root. It imports the category source modules in stable order and exports the catalog inputs. scripts/build-marker-schema.mjs turns those inputs into the generated runtime module marker-schema.js; contributors must not edit the generated file directly.
Key generated exports: MARKER_SCHEMA, BUILTIN_MARKER_IDENTITIES, BUILTIN_MARKER_DOT_KEY_ALIASES, getBuiltinMarkerId(), getBuiltinMarkerDotKey(), resolveBuiltinMarkerDotKey(), CUSTOM_MARKER_ID_PREFIX, and isCustomMarkerId().
See Marker model and category placement for the authoring and migration contract.
custom-marker-identity.js
Creates and migrates category-independent custom:* IDs while preserving existing custom-marker dot keys. Legacy IDs are deterministic and migration is idempotent so offline devices converge.
Key exports: createCustomMarkerId(), deriveLegacyCustomMarkerId(), ensureCustomMarkerIdentity(), migrateCustomMarkerIdentities(), getCustomMarkerId(), getCustomMarkerDotKey(), and resolveCustomMarkerDotKey().
marker-placement.js
Pure marker placement engine and storage/display boundary. It validates visual category assignments, keeps unknown metadata forward-compatible, applies placement as the final active-data projection, and resolves mutation keys back to immutable storage locations.
Key exports: migrateMarkerPlacements(), resolveMarkerIdentity(), getMarkerPlacementPlan(), setMarkerPlacement(), clearMarkerPlacement(), applyMarkerPlacements(), getMarkerStorageDotKey(), and active-marker lookup helpers.
marker-terminology.js
Generated, optional mapping registry for LOINC, NPU, NČLP, and UCUM metadata. It is not part of application startup, profile persistence, import/export, backup, sharing, or sync.
Key exports: TERMINOLOGY_CATALOGS, MARKER_TERMINOLOGY_REGISTRY, getMarkerTerminologyMappings(), and findMarkerTerminologyMapping().
See Laboratory terminology registry for the mapping and verification contract.
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? }(220 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)— compatibility re-export for Local AI request planning and adapter inference inapi-local.jscallOpenAICompatibleAPI(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 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, timeoutMs?)— guards one streaming read; Local AI uses the extended allowance only before its first tokenSTREAM_STALL_TIMEOUT_MS,LOCAL_AI_FIRST_TOKEN_STALL_MS,FETCH_REQUEST_TIMEOUT_MS,AI_IMPORT_REQUEST_TIMEOUT_MS— transport timeout constants
Local AI provider modules
Local AI uses a normalized adapter layer so compatible endpoints work without hiding richer Ollama and LM Studio capabilities. Key modules and exports:local-ai-provider-registry.js—LOCAL_AI_PROVIDER_ADAPTERS,getLocalAiProviderAdapter(), capability lookup, and detection precedencelocal-ai-provider-ollama.js— native discovery, streaming inference, context override, performance diagnostics, and unloadlocal-ai-provider-lmstudio.js— native discovery/model enrichment, guarded unload/load-at-context, streaming compatible generation, native fallback, and truncation diagnosticslocal-ai-provider-openai-compatible.js— generic/v1/modelsdiscovery and/v1/chat/completionsinferencelocal-ai-provider-shared.js— base URL normalization, execution-location classification, compatible-model normalization, and secret redactionlocal-ai-discovery.js— short-lived discovery cache and loaded-model metadata updatesapi-local.js— prompt-token estimation, context/output replanning after a native load, adapter selection, and normalized inference diagnosticslocal-ai-lifecycle.js— memory-only runtime handoff and best-effort model release across same-machine endpoints
Import model-testing modules
import-benchmarks.js captures durable, device-local diagnostics around production PDF/image imports. import-reference-benchmark.js runs and scores the bundled reference report. settings-import-benchmark-controller.js and the benchmark helpers in settings-data.js own the user-facing history and comparison UI.
See AI model testing internals for record statuses, scoring layers, same-input comparison, persistence, and fixture maintenance.
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()— builds or reuses the active projection: schema and custom markers, personal ranges, date-aligned values and entry context, phase/context ranges, deterministic calculated markers, unit conversion, and final display placementsinvalidateActiveDataCache()— clears the projection cache after a tracked mutationsaveImportedData()— persistsstate.importedDatato localStorage (or encrypted store), triggers backupfilterDatesByRange(data, options?)— returns a date-filtered projection without mutating the cached active datasetregisterRefreshCallback(fn)— registers the refresh function fromapp-event-listeners.jsgetFocusCardFingerprint()— hash of lab/profile inputs relevant to the Focus card- Compatibility re-exports from
marker-analysis.jskeep existingwindow.*helper access stable.
saveImportedData, clearAllData (via export.js), filterDatesByRange
Lab marker projection helpers
data-calculated-markers.js— direct-result-first calculated ratios, indices, free water deficit, PhenoAge, Bortz Age, combined Biological Age, and dated calculation guidance.marker-context-ranges.js— whole-age-at-draw, sex/age band selection, collection-time parsing, and cortisol range resolution.cycle-draw-phases.js— normalization of explicit recorded phase, phase detail, cycle day, and recorded/predicted source.marker-range-suggestions.js— privacy-safe public issue payload and gating to untouched built-in ranges.profile-marker-alias-migrations.js— canonical dotKey migrations across values, snapshots, custom markers, ranges, notes, labels, and date-scoped manual metadata.
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)— dated phase, contextual optimal/reference, and static/personal range lookupgetEffectiveRangeLabelForDate(marker, dateIndex)— matching user-facing source/policy label such as Lab reference, Target, or a phase labelgetPhaseRefEnvelope(marker)— widest span across all cycle phases for chart ref bandsgetContextRefEnvelope(marker)/getContextOptimalEnvelope(marker)— chart envelopes across dated context rangesgetLatestValueIndex(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— compact phase pills at observed points, with optional cycle day and recorded/predicted tooltip context
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
Supplement and medication modules
The feature is split by responsibility.supplements.js orchestrates the editor and persistence; supplement-medication-domain.js owns identity, lifecycle, periods, schedules, quantities, units, and additive migration; supplement-form-ui.js and supplement-import-controller.js own the structured form and reviewed import workflow; supplement-dashboard.js and supplement-impact.js own current display and historical analysis; supplement-quality.js, supplement-context.js, and supplement-warnings.js own evidence and bounded projections.
Key exports:
openSupplementsEditor(index?)— opens the supplement editor modalsaveSupplement(idx)— persists current form state toimportedData.supplementspauseSupplement(idx)/endSupplement(idx)— close the current period while preserving historyrestartSupplement(idx)/beginSupplementDoseChange(idx)— append or edit period-based lifecycle statedeleteSupplement(idx)— removes by indexrenderSupplementsSection()— renders current records and claim-grouped mitochondrial evidencerenderSupplementImpact(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|getSupplementStatus()/getSupplementsOverlappingRange()— period-derived current/history selectionbuildSupplementAIContext()— compact/detail source-quality context with hard character limitsparseSupplementQuantity(str)— structured quantity parser;parseAmount()remains the impact compatibility wrappereffectiveTimesPerDay(ing, supp)— row override wins, else supp-level defaultingredientDailyTotal(ing, supp)— computedamount × effectiveTimesPerDay
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
Health-context card rendering and lifecycle facade. It owns the grid, save-and-refresh flow, context notes, demo live-AI confirmation controls, card-tip launchers, and compatibility exports for the split editor, summary, dashboard-AI, and health-dot modules.
Key exports:
renderProfileContextCards()— renders the responsive nine-card grid, progress, demo AI status, and additional-context notesrenderInterpretiveLensSection()— 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()— compatibility facade for stale-card assessment incontext-card-health-dots.jsgetCardFingerprint(key)— djb2 hash of lab data, card data, shared notes/lens, sex, and DOB for cache invalidation- Per-card editor functions:
openDiagnosesEditor,openDietEditor,openExerciseEditor,openSleepRestEditor,openLightCircadianEditor,openStressEditor,openLoveLifeEditor,openEnvironmentEditor,openHealthGoalsEditor; Medical History helpers come fromcontext-card-medical-history-editor.js, and lifestyle editors come through the cold-safecontext-card-lifestyle-editors.jsfacade - Matching save/clear functions for all nine context areas are re-exported from their owning editor modules
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)
context-card-health-dots.js
AI-backed profile summaries, colored health dots, and short marker-linked tips for context cards. It fingerprints and caches each card independently, sends only stale cards, normalizes model output, and falls back to gray on malformed or failed responses. Demo profiles use bundled precomputed insights; local models can refresh them automatically, while cloud or paid models require in-memory consent bound to the current demo profile, provider, and model.
Key exports: getDemoContextAIMode(), enableDemoContextLiveAI(), disableDemoContextLiveAI(), applyDotColor(), applyAISummary(), applyAIProfileSummary(), getCardFingerprint(), loadContextHealthDots(), refreshAllHealthDots().
Window exports: none directly; compatibility functions are exposed through context-cards.js.
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.
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.
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.
context-card-lifestyle-editors.js
Cold-safe facade for all lifestyle context editors. It keeps the small diet-contaminant badge path available during dashboard render, lazy-loads context-card-lifestyle-editors-impl.js on first editor action, retries a failed module fetch once with a fixed alternate URL, and forwards the save/change callbacks owned by context-cards.js.
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.
context-card-lifestyle-editors-impl.js
Main editor implementation for Diet & Digestion, Sleep & Rest, Exercise, Stress, Love Life & Relationships, and Environment. It renders the current option sets, progressive detail sections, SI/US hydration labels, diet contaminant badge, and save/clear handlers. Light, goals, interpretive lens, and the contaminant detail modal are delegated to context-card-lifestyle-special-editors.js and re-exported.
Window exports: none; called through the cold-safe lifestyle facade.
context-card-lifestyle-special-editors.js
Specialized editors for Light & Circadian, prioritized Health Goals, Interpretive Lens, and diet contaminant details. It mirrors relevant Light setup values and keeps Health Goals sorted by priority.
Window exports: none; re-exported through the lifestyle editor modules and context-cards.js.
Layer 5 — Feature Modules
Genome modules
The Genome feature is a lazy-loaded 10-module family.dna.js is the public orchestration barrel; parsing, evidence, UI, mtDNA, and shell integration remain separated by responsibility.
dna-actions.js— delegated Genome action handlers.dna-evidence.js— association/evidence/relevance labels, ranking, focused Ask AI prompts, publication labels, and privacy-safe catalog issue links.dna-file-detection.js— provider, annotated-report, 23andMe MT/Y, and Living DNA motherline classification.dna-genotype.js— allele/repeat normalization and strand-aware catalog matching.dna-mtdna.js— mutation parsing, parent/subclade resolution, mitochondrial climate-adaptation context, preview, persistence, and manual haplogroup entry.dna-parser.js— Web Worker raw-file parser plus deterministic annotated/clinical report extraction.dna-runtime-bridge.js— cold-safe function registry used before the Genome bundle is loaded.dna-runtime.js— lazy stylesheet, pending-import, shell refresh, profile, and chat dependencies.dna-ui.js— Genome section, raw/report/manual entry, association groups, evidence controls, and import previews.dna.js— catalog loading, persistence, APOE resolution, re-import merge rules, AI context assembly, and public bridge registration.
detectDNAFile(text)— detects AncestryDNA, 23andMe autosomal/MT/Y, MyHeritage/FTDNA CSV, Living DNA autosomal/motherline, Illumina GSGT, and annotated SNP report formats by content.parseDNAFile(file)— scans a raw file in a Web Worker against the 60-entrydata/snp-health.jsoncatalog and returns normalized matches with association, evidence, and relevance metadata; preview/save resolve APOE from the two component calls.parseClinicalSnpReportText()/parseManualSnpRows()— deterministic report and small-list entry paths, including allele calls and supported numeric repeats such as6/7.upsertGeneticsSnp(profileData, rsid, genotype, source)— validates one catalog call and preserves source metadata for an explicit manual/report override.saveGeneticsData(profileData, result)— refreshes raw-file calls while preserving mtDNA and manual/report overrides; an overlapping explicit override remains authoritative.buildGeneticsContext(genetics, activeMarkerKeys, options)— serializes separately gated APOE/mtDNA, bounded priority findings, and optional all-call inventory. Full evidence scope/context is opt-in.buildFullGeneticsContext(genetics)— explicit genetics-question path with inventory and evidence details.buildSnpAIInterpretationPrompt(rsid, stored, entry)— focused, editable Ask AI baseline for one finding.getRelevantSNPs(markerKey)— marker-linked findings sorted by association, relevance, and evidence presentation rank.renderGeneticsSection()— Genome content with evidence/source/correction controls and raw/report/manual entry actions.handleDNAFile(file)/handleSnpReportFile(file)— preview and confirm flows for raw exports and report files.parseMtDNAMutations()/resolveHaplogroup()/detectMtDNAMismatch()— maternal marker parsing, specific-subclade resolution, and mitochondrial climate-adaptation latitude context.
configureDnaModuleBridge(). Shell and dashboard callers use health-data-loader.js or dna-runtime-bridge.js; Genome functions are no longer installed as a broad set of window globals.
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, fileName, onProgress)— sends text +buildMarkerReference()to AI, extracts explicit collection time and fasting status, reports reading/writing phases, rejects truncated output, and maps complete 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, stageLabel?)— streaming AI progress and reading/writing phase-label 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-ai-utils.js
Shared AI-import transport helpers.
Key exports:
callImportAIWithStreamFallback(request, label)— retries browser-aborted import streams once without streamingcreateImportAIProgress(options)— estimates prefill from prior per-model performance, then switches from Reading report to Writing results on the first generated textsaveImportAIPerf(key, result)— persists bounded per-model timing used by later progress estimatestryParseJSON(text)/formatImportError(error)— tolerant parse and user-facing error helpers; caller-side truncation checks run before reviewIMPORT_COLLECTION_CONTEXT_PROMPT/normalizeImportedCollectionContext()— accept only explicit specimen collection time and fasting state; reject processing/report-time substitution and clock-based fasting inference
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 marker and unit helpers
pdf-import-marker-mapping.js— canonical schema/custom/specialty matching, alias resolution, allowed calculated destinations, and thebuildMarkerReference()prompt catalog.pdf-import-ratio-units.js— importable calculated-marker allowlist and SI-versus-conventional convention metadata for unitless report ratios.pdf-import-unit-conversions.js— valid-unit lists plus round-trip display/SI conversion for recognized and custom markers.pdf-import-review-formatting.js— responsive unit controls, viewport-safe picker positioning, and range formatting used by the review modal.
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 stateapplyManualImportCollectionContext(patch)— updates review-timesampleTimeor tri-statefastingmapUnmatchedMarkerInput(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
pdf-import-commit.js
Snapshot-aware import commit, re-review, deletion, range adoption, and collection-context ownership.
Key contracts:
- direct lab-reported ratios and indices normalize to their canonical Calculated Ratios destination; computed fallbacks fill only missing dates;
- active adopted ranges are recomputed by collection date and then import time, while manual overrides preserve a stashed lab fallback;
collectionContextSourcestrackssampleTimeandfastingindependently so same-date snapshot removal restores the newest remaining owner;- mutation paths maintain marker/snapshot tombstones and roll back on durable-save failure.
pdf-import.js and import-history controls.
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, including entries, context, custom marker identities,markerPlacements, notes, supplements, biometrics, genetics, Light/Sun data, and supported chat statebuildClientExportObject(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 and re-exports the public helpers from the feature modules. The composer/draft, bounded transcript, scroll, edit/fork, recommendation-disclosure, persona persistence, and discussion-round modules keep durable state and high-churn UI behavior out of the public barrel. See Chat internals for the end-to-end ownership, storage, Sync, and backup contract.
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, thread-bound 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 delegates textarea/draft behavior to chat-composer.js, concise assistive status to chat-stream-status.js, continuation handling to chat-continuation.js, and collapsed recommendation state to chat-recommendation-disclosure.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, latest-turn and fork action placement, lens-source disclosures, assistant footnotes, image badges, EMF hints, and persisted recommendation sections. It renders only the range supplied by chat-render-range.js, delegates scroll ownership to chat-scroll.js, and reveals earlier batches without truncating stored history.
Key exports: renderChatMessages, showEarlierChatMessages, revealChatMessage, _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-composer.js
Growing textarea and active-thread draft coordinator. It binds visible input to { profileId, threadId }, restores drafts after async thread switches, clears a sent draft, and prevents a late decrypt from writing into a newly selected thread.
Key exports: configureChatComposer, initChatComposer, resizeChatInput, saveChatDraft, getChatDraft, restoreChatDraft, clearChatDraft, resetChatComposer, setChatInputValue.
Window exports: none.
chat-draft-storage.js
Device-local draft cache and 300 ms debounced persistence. Draft keys use the sensitive storage wrapper but are intentionally excluded from Sync and every backup/export path. Its ordered write chain prevents a pending save from resurrecting a cleared draft.
Key exports: chatDraftStorageKey, getCachedChatDraft, loadChatDraft, rememberChatDraft, clearStoredChatDraft, flushStoredChatDraft.
Window exports: none.
chat-render-range.js, chat-scroll.js, and chat-stream-status.js
Transcript-scale and interaction helpers. chat-render-range.js exposes the latest 120 records and expands in 120-record batches; chat-scroll.js follows streaming only while the user remains near the latest message; chat-stream-status.js emits concise ARIA status changes without making every streamed token a live-region update.
Window exports: none.
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 sequential per-persona API calls, progress and assistive status, pause/abort state, origin-thread persistence, typewriter updates, usage footnotes, partial-response preservation, and targeted failure records. It returns the remaining participants so resume and per-participant retry do not replay successful responses.
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, one-at-a-time participant addition, request-count/charge disclosure, keyboard dismissal, 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
Personality selection and workflow facade. It renders the picker and chat header, invokes the dedicated custom-persona dialog, streams an editable generated draft, persists through chat-personality-storage.js, and updates the active thread’s personality metadata.
Key exports: getActivePersonality, getCustomPersonalities, loadCustomPersonalities, saveCustomPersonalities, getCustomPersonality, setChatPersonality, loadChatPersonality, updateChatHeaderTitle, updateChatHeaderModel, updatePersonalityBar, togglePersonalityBar, generateCustomPersonality, saveCustomPersonality, startNewCustomPersonality, editCustomPersonality, deleteCustomPersonality.
Window exports: assigned by chat-window-bindings.js for existing inline handlers and cross-module callbacks.
chat-personality-editor.js
Custom persona modal and host policy. The official getbased.health host requires a versioned acknowledgement that a persona is an AI-generated interpretation and cannot be used to impersonate or imply endorsement. Self-hosted origins receive the responsibility notice without a required checkbox.
Key exports: isOfficialHostedPersonaApp, hasCurrentPersonaAgreement, isCustomPersonalityUsable, buildPersonaAgreementRecord, openPersonaEditorDialog.
Window exports: none.
chat-personality-storage.js and chat-personality-merge.js
Encrypted-wrapper persistence, synchronous decrypted cache, deletion tombstones, and deterministic per-persona Sync merge. Persona updates resolve by updatedAt/createdAt; a tombstone at least as new as the record removes it without replacing unrelated personas.
Key exports: storage-key helpers, load/save/cache helpers, recordCustomPersonalityDeletion, customPersonalityUpdatedAtMs, and mergeCustomPersonalityState.
Window exports: none.
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-threads.js
Conversation index CRUD, active-thread switching, linked fork creation, rail rendering, and thread deletion tombstones. pruneOldThreads() is a compatibility no-op. An existing index that cannot be decrypted or parsed blocks writes and new-chat creation rather than replacing saved conversations with an empty index.
Key exports: loadChatThreads, saveChatThreadIndex, ensureActiveThread, createNewThread, createForkedThread, switchToThread, deleteThread, renameThread, renderThreadList, and the search compatibility exports.
Window exports: assigned through chat-window-bindings.js where legacy callers still require them.
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 rendering and delegated handlers. It owns Retry/Regenerate, Copy, Listen, context details, responsive overflow actions, discussion pause/resume/retry controls, and callbacks into latest-message editing and linked forks. Voice actions cross the lazy boundary through voice-loader.js.
Key exports: configureChatMessageActionDeps, installChatMessageActionDelegates, buildActionBar, buildUserActionBar, buildForkSourceNotice, regenerateLastMessage, copyMessage, toggleContextDetails.
Window exports: assigned by the module directly and re-exported by chat.js for existing inline handlers.
chat-message-edit.js
Latest-turn inline editor and non-destructive assistant-reply forks. Edit-and-retry is limited to the latest visible text-only user message while no response is streaming; fork creation copies normalized history through the selected assistant message into a linked thread.
Key exports: configureChatMessageEditDeps, getLatestUserMessageIndex, beginChatMessageEdit, cancelChatMessageEdit, submitChatMessageEdit, prepareChatMessageEditSend, forkChatFromMessage.
Window exports: none; chat-actions.js receives callbacks.
chat-recommendation-disclosure.js and chat-storage-safety.js
chat-recommendation-disclosure.js persists related suggestions collapsed and marks only the first or materially changed slot set as new. chat-storage-safety.js normalizes untrusted chat, thread, persona, tombstone, discussion/fork, usage, and image shapes before import, restore, or Sync apply.
Window exports: none.
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
Private-transport attestation display helpers shared by the chat header and assistant-message cost footnotes. Tinfoil uses 🔒 verified after its full policy passes. Venice uses 🔒 TEE + GPU after its required DCAP and signed NRAS checks pass, while the tooltip keeps code-measurement, co-location, and response-source limits visible.
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.
Voice subsystem
Voice is a first-use chat subsystem rather than part of the startup bundle.voice-loader.js keeps microphone capture and speech dependencies cold until the user records, listens, or enables automatic reading. It binds each pending action to the active chat thread and message so late transcription or speech work cannot update a stale conversation.
Chat orchestration:
voice-controller.jsowns microphone state, transcript insertion, per-message playback, automatic reading, cancellation, and thread/message identity checks.voice-capture.js,voice-player.js,voice-audio.js, andvoice-text.jsown ephemeral recording, progressive audio playback, PCM/WAV handling, and safe speech-text normalization/chunking.voice-service.jsandvoice-provider-registry.jsselect the configured STT/TTS provider without coupling chat controls to provider implementations.
voice-provider-browser-local.jsruns downloaded Whisper STT and Kokoro TTS throughvoice-local-stt-worker.js,voice-local-tts-worker.js, and the serializedvoice-local-engine.jsworker controller.voice-provider-local-server.jscalls OpenAI-compatible/v1/audio/transcriptions,/v1/audio/speech, and/v1/modelsendpoints directly from the browser.voice-provider-xai.jsandvoice-provider-elevenlabs.jsusevoice-provider-cloud-shared.jsto call the bounded same-origin/api/voicerelay.voice-provider-catalog.jsowns capability and execution-location metadata;voice-model-catalog.jspins local models, voices, languages, download sizes, and CPU/WebGPU modes.
settings-voice-panel.js,settings-voice-view.js,settings-voice-model-controller.js, andsettings-voice-hardware.jsown the Settings → Voice UI, downloads, connection tests, voice catalogs, and hardware guidance.voice-settings-schema.jsis the authority for device-local, syncable, secret, and backup keys.voice-settings-storage.jsvalidates preferences and delegates secret writes to encrypted provider storage.- Downloaded model assets and fetched voice catalogs are rebuildable caches. They are not sync payloads or backup data.
api/voice.js delegates to lib/voice-relay-handler.js; lib/voice-relay-policy.js allowlists providers/actions, bounds request and response sizes, validates identifiers and languages, and maps normalized requests to xAI or ElevenLabs.
Key exports: loadVoiceModule, toggleVoiceRecording, toggleMessageSpeech, maybeAutoReadAssistantMessage, stopVoiceActivity, getVoiceSettings, setVoiceSetting, transcribeVoice, createVoiceSynthesizer
Window exports: none; chat and shell actions use module callbacks.
settings.js
Settings modal shell with profile, display, AI, Voice, privacy, data, wearables, and Agent Access tabs. Delegates AI provider panels to provider-panels.js, Voice rendering and actions to settings-voice-panel.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
Cold facade for the Cross-device Sync and Agent Access settings graph. A first Settings render returns marked loading placeholders and starts settings-sync-panel-impl.js; when the import resolves, the facade replaces both placeholders in place so the real controls appear without closing and reopening Settings. Action calls use the same loader and retry boundary.
Key exports:
renderSyncSection()— renders the Settings → Data sync panelrenderMessengerSection()— compatibility export that renders the Settings → Agent Access panel throughsettings-agent-access-panel.jshydrateSettingsSyncPanel()— forwards post-paint mnemonic and relay hydration after the implementation loadsshowSyncSetupModal()— loads the implementation and opens the setup wizard
showSyncSetupModal, toggleSync, toggleMnemonicVisibility, copyMnemonic, saveSyncRelay, openRestoreMnemonicDialog, closeRestoreMnemonicDialog, confirmRestoreMnemonic, closeSyncSetup, syncSetupNew, syncSetupRestore, syncSetupBack, syncSetupDoRestore, syncSetupDone, toggleMessenger, toggleMessengerToken, copyMessengerToken, regenerateMessengerToken
settings-sync-panel-impl.js
Loaded implementation for the Settings → Data sync section. It owns setup/restore UI, mnemonic and relay controls, diagnostics entry points, and Agent Access delegation. Existing-mnemonic joins call the controlled restore path in sync-identity.js.
Key exports: configureSettingsSyncPanelDeps, renderSyncSection, renderMessengerSection, showSyncSetupModal, closeSyncSetup, closeRestoreMnemonicDialog, hydrateSettingsSyncPanel.
Window exports: none directly; the facade owns compatibility bindings.
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
category-order.js
Shared, DOM-independent ordering for lab navigation and category controls. getLabCategoryEntriesInSidebarOrder() keeps regular categories first and preserves schema order within specialty groups so the placement picker and sidebar agree.
marker-detail-placement.js
Marker-detail category picker and persistence controller. It lists only destinations accepted by marker-placement.js, groups categories present in the profile before other compatible categories, preserves sidebar order, serializes per-profile mutations, and provides restore-to-native behavior.
Key exports: configureMarkerDetailPlacement(), getMarkerPlacementChoices(), renderMarkerPlacementSummary(), openMarkerPlacementModal(), saveMarkerPlacement(), and restoreMarkerPlacement().
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, manual database backup, and restore. backup-chat-storage.js supplements profile collection with raw thread index/message envelopes so a locked or partially recovered index cannot make a full backup omit ciphertext. Unsent draft keys are intentionally excluded.
Key exports:
scheduleAutoBackup()— debounced five-minute trigger; saves up to 5 snapshots to IndexedDB + writes to folder backup if configuredbuildBackupSnapshot()— legacy synchronous localStorage snapshot retained for focused tests and compatibilitybuildFullBackupSnapshot()— asynchronously captures IndexedDB-backed profile blobs, chat records, preferences, and device-local dataexportEncryptedBackup()/importEncryptedBackup()— manual full-database bundle export and restoregetAutoBackupSnapshots()— reads the retained IndexedDB snapshot listrestoreAutoBackup(id)— restores localStorage plus profile, wearable, and cycle IndexedDB records, then reloadsinitFolderBackup(),pickFolderForBackup(),reauthorizeFolderBackup(),removeFolderBackup()— File System Access lifecycle for latest and daily folder snapshots
restoreAutoBackup, pickBackupFolder, showBackupReminder
lab-context.js
Central AI context serializer. Extracted from chat.js.
Key exports:
buildLabContext()— serializes enabled lab groups, effective dated ranges, explicit collection context, profile/context cards, cycle data, notes, and other enabled sources into tagged AI context
lab-context-collection.js
Builds [section:labCollectionContext] from explicit per-draw metadata. It emits collection time, tri-state fasting when known, cycle day, and recorded phase; missing fields are omitted with an instruction not to infer them.
Key export: buildLabCollectionContextSection(entries).
Window exports: none.
lab-context-change-timeline.js
Builds the [section:changeHistory] profile-context timeline used by buildLabContext(). It filters the timeline by enabled Insight Context Cards and Light & Sun sources, orders snapshots by date, and renders field-level changes.
Window exports: none.
lab-context-wearables.js
Builds compact wearable context and optional Agent Access series. It also detects contradictions between manually selected Sleep & Rest duration/quality and recent wearable data, returning an explicit mismatch warning instead of silently choosing one source.
Key exports: getSleepContextMismatch(), buildWearableContext(), buildWearableSeriesSection(), and the in-app/Agent Access wearable-context setting helpers.
Window exports: none.
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 9 registered sources (Oura / Withings / Ultrahuman / WHOOP / legacy Fitbit / Google Health / 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()applyOAuthConfigured(map)/isOAuthAdapterConfigured(adapterOrId)— apply and read server-confirmed capability flags; Google Health uses this gate independently from its client-ID overridegetOAuthClientId(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 returned public client-ID overrides and capability booleans, and clears failed cached requests so a later scheduler pass can retry. A 1.5s soft timeout keeps startup non-blocking
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, and …-google-health.js + …-google-health-auth.js. Secrets live in .env.local + /api/proxy. Google Health additionally requires the explicit server capability gate and encrypts its credentials and raw rows with its device-local credential vault key.
OAuth2 PKCE (no secret): wearables-whoop.js + …-whoop-auth.js. The Fitbit PKCE modules remain only to sync already-connected legacy users during the migration window; the adapter is hidden for new connections.
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.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— claim-level, primary-study mitochondrial evidence matching and bounded context;food-contaminants.jsseparately owns deterministic diet-source warnings.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, missing-profile-data rejection, unchanged-payload suppression, generation-safe dirty clearing, exact source-commit tracking, relay-storage refresh scheduling, in-flight watchdog, 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; force-publishes pending backup restores, flushes dirty local work, tracks source-tab commits, and 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, origin-aware 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, thread/persona delete tombstones, per-persona timestamp merge, 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; existing-identity joins suppress Evolu’s internal reload, persist enabled owner state, then perform one controlled reload.sync-settings-state.js— persisted configured/active/paused state.labcharts-sync-enabledmeans an identity is configured;labcharts-sync-pausedsuppresses traffic without forgetting it.sync-lifecycle.js— runtime start, identity-preserving pause/resume, explicit disconnect/reset, and backup-restore push preflight.sync-backup-restore-state.js— durable restored-profile handoff; clears stale delta/cutover state, marks profiles dirty, and retains the retry list until a recovery push succeeds.sync-subscriptions.js— Evolu profile/settings subscriptions and debounce timers; paused state clears and blocks inbound delivery until resume rebinds them.sync-dirty-state.js— durable per-profile edit generations, captured-generation clearing, and dirty-state inspection for pull and compaction safety.sync-origin-state.js— tab-local committedsyncedAttracking used to distinguish source-browser echoes from updates received elsewhere.sync-profile-fields.js— deterministic shared profile metadata field list used by outbound payload collection and inbound profile merge.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, dirty-profile compaction preflight, fail-closed unreadable-profile guard, relay snapshot rebuild, and compatibility re-exports for save hooks and storage cleanup.sync-save-hooks.js— save/chat/profile-metadata debounce hooks, durable dirty marking, AI-setting push scheduling, per-profile timer cleanup, and canonical IndexedDB-backed profile reads that returnnullrather than an empty default on failure.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 thread messages/tombstones, custom personas, persona tombstones, and synced setting allowlists.sync-payload.js— Evolu wire-payload helpers; deterministic profile-field 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.