Skip to content

Stabilize calculations, reconcile docs, and optimize Three.js#9

Merged
keithce merged 2 commits intomainfrom
codex/stabilize-docs-threejs
Feb 22, 2026
Merged

Stabilize calculations, reconcile docs, and optimize Three.js#9
keithce merged 2 commits intomainfrom
codex/stabilize-docs-threejs

Conversation

@keithce
Copy link
Copy Markdown
Owner

@keithce keithce commented Feb 22, 2026

Summary

  • fix timezone propagation in enhanced calculation actions and add timezone-sensitive Julian Day coverage
  • stabilize globe layer behavior (heatmap intensity/update path, hot-count correctness, city-marker stale-layer cleanup)
  • resolve TypeScript failures (uniform typing, texture typing, dominant planet type narrowing, unused imports)
  • improve scoring-grid performance stability via ACG candidate filtering and latitude early-exit checks
  • reconcile implementation/docs status across README + planning/architecture docs and mark historical planning artifacts
  • add docs:check with scripts/check-doc-paths.ts to fail on broken markdown file references
  • optimize Three.js delivery/runtime with lazy route/component boundaries, Vite manual chunks, reduced hot-path allocations, and shader color-space consistency fixes

Validation

  • bun run typecheck
  • bun run test
  • bun run build
  • bun run docs:check

Notes

  • saved/shared route parity is documented as current limitation where TODO placeholders remain
  • build still reports existing chunk-size warnings and the pre-existing GlobeCanvas mixed static/dynamic import warning

Summary by CodeRabbit

  • New Features

    • Timezone-aware calculations for more accurate, locale-sensitive results.
    • Loader/fallback UI while the globe loads.
  • Performance

    • Lazy-loaded globe component and code-splitting for faster initial loads.
    • Faster ACG line filtering via spatial precomputation.
  • Bug Fixes

    • Improved globe textures, color-space handling, and heatmap update stability.
  • Documentation

    • Consolidated docs with current product state and known limitations.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
declination-living Ready Ready Preview, Comment Feb 22, 2026 1:44pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

This PR adds timezone awareness to calculation actions, standardizes planet identifiers to PlanetId, prunes and reconciles large documentation sets, optimizes ACG line scoring with latitude-bound precomputation, implements frontend lazy-loading and rollup chunking for globe code, improves heatmap/shader colorspace handling, and adds a docs-checking script.

Changes

Cohort / File(s) Summary
Documentation Reconciliation
README.md, docs/PlanetsAlign_WebApp_Plan_v3.md, docs/claude/architecture.md, docs/implementation-plan/*, docs/*
Replaced long-form plans and guides with concise reconciled/archival notes and simplified API/docs sections; removed many procedural and detailed implementation blocks for traceability.
Timezone Awareness Integration
convex/calculations/enhanced_actions.ts, convex/calculations/ephemeris/__tests__/julian.test.ts, convex/calculations/ephemeris/*
Added timezone: string to many Convex action schemas and handlers; switched dateToJulianDay calls to timezone-aware variants; updated downstream position, ACG, paran, dignity, vibe, and complete-enhanced calculations; added julian test covering timezone differences.
Type System Refactor (PlanetId)
convex/calculations/enhanced_actions.ts, convex/calculations/optimizer.ts, src/components/globe/EnhancedGlobeCanvas.tsx, src/components/globe/layers/types
Replaced freeform dominantPlanet/planet id strings with PlanetId-typed fields/usages across actions, optimizer types, and globe weight helpers; adjusted imports and internal helpers to use PlanetId.
Geospatial Optimization
convex/calculations/geospatial/search.ts, convex/calculations/geospatial/grid.ts
Introduced ACGLatitudeBound and precomputeACGLatitudeBounds; added latitude-bound filtering and per-point latitude early-skip logic to reduce ACG line scoring work and hoisted candidate filtering outside inner longitude loops.
Frontend Performance & Code Splitting
src/components/results/FullPageGlobeLayout.tsx, src/routes/calculator.tsx, src/routes/results.$chartId.tsx, vite.config.ts
Converted heavy globe/layout components to React.lazy + Suspense boundaries with fallbacks; added manualChunks rollup rules to isolate three and globe bundles for better code-splitting.
Globe Rendering & Shaders
src/components/globe/EnhancedGlobeCanvas.tsx, src/components/globe/layers/HeatmapLayer.ts, src/components/globe/shaders/earthShader.ts, src/components/globe/shaders/atmosphereShader.ts, src/components/globe/shaders/loadEarthTextures.ts
Added buildHeatmapWeights helper and persistent HeatmapState; refactored heatmap array population and pulsing behavior; adjusted texture placeholder colorSpaces and disposal handling; injected colorspace fragment into atmosphere shader.
Tooling: Docs Validation
scripts/check-doc-paths.ts, package.json
Added scripts/check-doc-paths.ts to validate local Markdown references and a docs:check npm script to run it; reports missing references and fails with exit code 1 on errors.
Minor
src/routes/why.tsx
Removed an unused icon import.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/stabilize-docs-threejs

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@convex/calculations/geospatial/search.ts`:
- Around line 449-464: The precomputeACGLatitudeBounds function currently
produces minLatitude=Infinity and maxLatitude=-Infinity for ACGLine entries with
empty points, which creates inverted bounds and causes the candidate filter
(used in the grid filtering logic) to silently exclude valid latitudes; change
precomputeACGLatitudeBounds to skip/filter out any ACGLine where line.points is
empty (e.g., if (line.points.length === 0) continue or build the map and then
.filter(Boolean)) so only lines with at least one point produce an
ACGLatitudeBound and are returned; keep the function name
precomputeACGLatitudeBounds and the ACGLine/ACGLatitudeBound types the same so
downstream code reading these bounds doesn't need changes.

In `@docs/implementation-plan/phase-6-ui.md`:
- Line 18: Change the phrase "calculator enhanced output" to
"calculator-enhanced output" in the document so the compound adjective correctly
hyphenates before "output"; search for the exact string "calculator enhanced
output" and replace it with "calculator-enhanced output".

In `@scripts/check-doc-paths.ts`:
- Line 6: The use of shell commands via execSync ('ls -1' used to build
repoTopLevel and 'rg' later in the file) is platform-dependent and can fail on
non-Unix systems; replace these with Node APIs instead: replace the execSync('ls
-1', ...) that creates repoTopLevel with a cross-platform directory read using
fs.readdirSync(process.cwd()) (or fs.promises.readdir with recursion) and build
the Set from that array, and replace the ripgrep execSync call with a recursive
directory walk (using fs and path) or a cross-platform glob library (e.g.,
fast-glob or glob) to collect matching files; update any code using repoTopLevel
and the rg results to accept arrays/Sets from these Node-based methods (look for
symbols repoTopLevel and the execSync('rg ...') invocation to locate the spots
to change).

In `@src/components/globe/shaders/loadEarthTextures.ts`:
- Around line 69-84: When a promise in results resolves, the pre-created
fallback texture in textures[key] must be disposed before assigning the loaded
texture to avoid leaking GPU resources; update the success branch (where you
check result.status === 'fulfilled') to call textures[key].dispose() (or safely
dispose if not null) before setting textures[key] = result.value, using the
existing TEXTURE_ENTRIES loop, textures object, and createFallbackTexture
pattern so both success and failure paths consistently release the initial
fallback.

In `@vite.config.ts`:
- Around line 20-27: The manualChunks function's three-vendor condition
redundantly checks both id.includes('/node_modules/three/') and
id.includes('/node_modules/three/examples/'); remove the latter redundant
includes check and keep only id.includes('/node_modules/three/') in the
manualChunks callback so files under three (including examples) are grouped into
'three-vendor' while leaving the globe chunk and default return unchanged.

Comment thread convex/calculations/geospatial/search.ts
Comment thread docs/implementation-plan/phase-6-ui.md Outdated
Comment thread scripts/check-doc-paths.ts Outdated
Comment thread src/components/globe/shaders/loadEarthTextures.ts
Comment thread vite.config.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/globe/shaders/loadEarthTextures.ts`:
- Around line 82-86: The failure branch is redundantly disposing and recreating
a fallback texture even though a correct fallback was already created earlier
for this key; in the else branch that handles load failure (referencing
textures[key], TEXTURE_ENTRIES[i].path and createFallbackTexture), remove the
textures[key].dispose() and the textures[key] = createFallbackTexture(...)
assignment so the preexisting fallback texture is retained instead of being
recreated.

In `@vite.config.ts`:
- Around line 17-31: The manualChunks function uses the raw id string for path
checks which should be normalized; update the manualChunks callback in
vite.config.ts to call Vite's normalizePath(id) (or import { normalizePath }
from 'vite') and use the normalized value for the includes checks (e.g., replace
id.includes('/node_modules/three/') and id.includes('/src/components/globe/')
with normalizedId.includes(...)) so path separators are consistent across
platforms and future Rollup changes.

---

Duplicate comments:
In `@scripts/check-doc-paths.ts`:
- Around line 1-13: No changes required: the cross-platform use of readdirSync
and the SKIP_DIRECTORIES Set are correct in this file; leave the repoRoot,
repoTopLevel, and SKIP_DIRECTORIES definitions (repoRoot, repoTopLevel,
SKIP_DIRECTORIES) as-is and no further fixes are necessary.

Comment on lines 82 to 86
} else {
console.warn(`Failed to load texture "${key}" (${TEXTURE_ENTRIES[i].path}):`, result.reason)
textures[key].dispose()
textures[key] = createFallbackTexture(colorSpace, maxAnisotropy)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Redundant dispose/recreate on failure path.

The fallback texture for this key already exists (created at lines 69–74) with the correct colorSpace. Disposing and recreating an identical fallback is wasteful—just keep the existing one.

Proposed fix
     } else {
       console.warn(`Failed to load texture "${key}" (${TEXTURE_ENTRIES[i].path}):`, result.reason)
-      textures[key].dispose()
-      textures[key] = createFallbackTexture(colorSpace, maxAnisotropy)
+      // Keep the pre-created fallback; no action needed
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/globe/shaders/loadEarthTextures.ts` around lines 82 - 86, The
failure branch is redundantly disposing and recreating a fallback texture even
though a correct fallback was already created earlier for this key; in the else
branch that handles load failure (referencing textures[key],
TEXTURE_ENTRIES[i].path and createFallbackTexture), remove the
textures[key].dispose() and the textures[key] = createFallbackTexture(...)
assignment so the preexisting fallback texture is retained instead of being
recreated.

Comment thread vite.config.ts
Comment on lines +17 to +31
build: {
rollupOptions: {
output: {
manualChunks: (id) => {
if (id.includes('/node_modules/three/')) {
return 'three-vendor'
}
if (id.includes('/src/components/globe/')) {
return 'globe'
}
return undefined
},
},
},
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🌐 Web query:

Vite manualChunks id path normalization Windows

💡 Result:

On Windows, the id you get in build.rollupOptions.output.manualChunks(id) (and in Vite plugin hooks like resolveId/load/transform) is typically already normalized by Vite to use POSIX separators (/), while Node’s path.* (and plain Windows paths) use \. So comparisons like id.includes('\\node_modules\\') or id.startsWith(path.resolve(...)) can fail on Windows. (vite.dev)

Fix: normalize before comparing (recommended)

Use Vite’s normalizePath() and compare against normalized strings:

// vite.config.ts
import { defineConfig, normalizePath } from 'vite'
import path from 'node:path'

const src = normalizePath(path.resolve(__dirname, 'src')) // "C:/.../src" on Windows

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          id = normalizePath(id)

          if (id.includes('/node_modules/')) return 'vendor'
          if (id.startsWith(src + '/')) return 'app'
        }
      }
    }
  }
})

Vite documents this explicitly: normalize paths to POSIX before doing “resolved id” comparisons, and provides normalizePath() for that purpose. (vite.dev)

Quick alternative (less robust)

Just write your checks using /:

manualChunks(id) {
  if (id.includes('/node_modules/')) return 'vendor'
}

This works because Vite normalizes resolved ids to / even on Windows. (vite.dev)

Citations:


🌐 Web query:

Vite normalizePath rollup manualChunks documentation

💡 Result:

  • Vite normalizePath (what/where): Vite exports normalizePath to convert Windows \ separators to POSIX / so plugin/path comparisons against resolved ids behave consistently across OSes (especially when using Rollup-style include/exclude filtering). See Vite Plugin API → Path Normalization. [1]

    import { normalizePath } from 'vite'
    normalizePath('foo\\bar') // 'foo/bar'
  • Rollup output.manualChunks (what/where): Rollup’s output.manualChunks lets you control code-splitting either via:

    • object form { chunkName: [moduleIds...] }
    • function form (id, { getModuleInfo, getModuleIds }) => chunkName | void
      See Rollup Configuration Options → output.manualChunks. [2]
    // function form example
    manualChunks(id) {
      if (id.includes('node_modules')) return 'vendor'
    }
  • Vite note about manualChunks going forward: In newer Vite docs (Rolldown transition), the object form is removed and the function form is deprecated in favor of Rolldown’s code-splitting options (e.g. codeSplitting / advancedChunks, depending on the doc section/version). See Vite’s migration / Rolldown integration docs. [3]

Sources: [1] [2] [3]


🌐 Web query:

Vite rollup module id path separator behavior

💡 Result:

  • What you’ll see in id (Rollup/Vite plugin hooks):

    • Vite normalizes resolved filesystem ids to POSIX separators (/), keeping the Windows drive/volume prefix intact. Rollup (by default) keeps the platform path “as-is”, so on Windows it can be \-separated. Therefore, code that compares/matches id can behave differently between Rollup-on-Windows and Vite. [1]
  • What to do in plugins (recommended):

    • Normalize before comparing:

      import { normalizePath } from 'vite' // or from '@rollup/pluginutils'
      if (normalizePath(id).includes('/node_modules/')) { /* ... */ }

      Vite exports normalizePath, and @rollup/pluginutils also provides it (it converts \/). [1][2]

    • When using RegExp matching, make separators OS-agnostic:

      • Use [\\/] instead of / in patterns that may run under Rollup on Windows, e.g. /node_modules[\\/]react/. [3]
  • Related Rollup output behavior (chunk ids):

    • Rollup fixed Windows-related slash issues so that when preserveModules is used, chunk ids use forward slashes even on Windows (Rollup v3.2.4). [4]

Sources: Vite Plugin API (Path Normalization) [1], @rollup/pluginutils docs (normalizePath) [2], separator-safe regex guidance [3], Rollup release note mentioning forward slashes in chunk ids with preserveModules [4].


Use normalizePath() to align with Vite's best practices for path handling.

While Vite automatically normalizes the id parameter to POSIX separators (/) even on Windows, using normalizePath() explicitly is the documented best practice and future-proofs the code against Rollup behavior differences.

♻️ Suggested refactor
-import { defineConfig } from 'vite'
+import { defineConfig, normalizePath } from 'vite'
@@
-        manualChunks: (id) => {
-          if (id.includes('/node_modules/three/')) {
+        manualChunks: (id) => {
+          const normalizedId = normalizePath(id)
+          if (normalizedId.includes('/node_modules/three/')) {
             return 'three-vendor'
           }
-          if (id.includes('/src/components/globe/')) {
+          if (normalizedId.includes('/src/components/globe/')) {
             return 'globe'
           }
           return undefined
         },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vite.config.ts` around lines 17 - 31, The manualChunks function uses the raw
id string for path checks which should be normalized; update the manualChunks
callback in vite.config.ts to call Vite's normalizePath(id) (or import {
normalizePath } from 'vite') and use the normalized value for the includes
checks (e.g., replace id.includes('/node_modules/three/') and
id.includes('/src/components/globe/') with normalizedId.includes(...)) so path
separators are consistent across platforms and future Rollup changes.

@keithce keithce merged commit 50e790e into main Feb 22, 2026
7 checks passed
@keithce keithce deleted the codex/stabilize-docs-threejs branch February 22, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant