issue with notch
This commit is contained in:
262
DIAGNOSIS_COMPLETE.md
Normal file
262
DIAGNOSIS_COMPLETE.md
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
# Production Theme Notch Styling Issue - Complete Diagnostic Report
|
||||||
|
|
||||||
|
**Date**: 2026-02-10
|
||||||
|
**Status**: ✅ ROOT CAUSE IDENTIFIED
|
||||||
|
**Severity**: CRITICAL
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Summary
|
||||||
|
|
||||||
|
The theme notch component on production (https://santhoshj.com) appears as plain buttons in normal document flow instead of a fixed, positioned element in the top-right corner.
|
||||||
|
|
||||||
|
**Root Cause**: The production server is serving a **STALE CSS file** (17,628 bytes) that was built BEFORE the theme-notch CSS rules were added. The local build correctly generates a 24,279 byte CSS file with all rules.
|
||||||
|
|
||||||
|
**Fix**: Rebuild and redeploy the Docker image with the latest source code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
### 1. CSS File Size Mismatch
|
||||||
|
|
||||||
|
| Metric | Local Build | Production | Status |
|
||||||
|
|--------|-------------|-----------|--------|
|
||||||
|
| File size | 24,279 bytes | ~17,628 bytes | ❌ MISMATCH |
|
||||||
|
| Difference | - | -6,651 bytes (27% smaller) | ❌ CRITICAL |
|
||||||
|
| theme-notch rules | 30 matches | 0 matches | ❌ MISSING |
|
||||||
|
|
||||||
|
### 2. CSS Rules Comparison
|
||||||
|
|
||||||
|
**Local CSS (site/dist/styles/global.css):**
|
||||||
|
```css
|
||||||
|
.theme-notch {
|
||||||
|
position: fixed;
|
||||||
|
top: var(--theme-notch-top);
|
||||||
|
right: max(8px, env(safe-area-inset-right));
|
||||||
|
z-index: 12;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-notch-panel {
|
||||||
|
position: absolute;
|
||||||
|
right: 60px;
|
||||||
|
top: 0;
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--stroke-mid);
|
||||||
|
background: var(--surface-1);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(10px) scale(0.98);
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 160ms ease, transform 160ms ease, visibility 0s linear 160ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-notch-handle { ... }
|
||||||
|
.theme-notch-glyph { ... }
|
||||||
|
.theme-notch-option { ... }
|
||||||
|
.theme-notch-dot { ... }
|
||||||
|
/* + media queries and forced-colors rules */
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production CSS (https://santhoshj.com/styles/global.css):**
|
||||||
|
```
|
||||||
|
❌ ZERO matches for .theme-notch*
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Computed Styles on Production
|
||||||
|
|
||||||
|
| Property | Actual | Expected | Status |
|
||||||
|
|----------|--------|----------|--------|
|
||||||
|
| .theme-notch position | static | fixed | ❌ WRONG |
|
||||||
|
| .theme-notch top | auto | 84px | ❌ WRONG |
|
||||||
|
| .theme-notch right | auto | max(8px, env(...)) | ❌ WRONG |
|
||||||
|
| .theme-notch z-index | auto | 12 | ❌ WRONG |
|
||||||
|
| .theme-notch-panel position | static | absolute | ❌ WRONG |
|
||||||
|
| .theme-notch-panel display | block | grid | ❌ WRONG |
|
||||||
|
| .theme-notch-panel opacity | 1 | 0 (initially) | ❌ WRONG |
|
||||||
|
| .theme-notch-panel visibility | visible | hidden (initially) | ❌ WRONG |
|
||||||
|
|
||||||
|
### 4. HTML Markup Status
|
||||||
|
|
||||||
|
✅ **Present and correct on both local and production:**
|
||||||
|
- `<aside class="theme-notch" aria-label="Theme" data-theme-notch="" data-open="false">`
|
||||||
|
- `<div class="theme-notch-panel" id="theme-notch-panel" role="radiogroup" aria-label="Theme selector">`
|
||||||
|
- `<button class="theme-notch-option" data-theme-option="dark|light|contrast" role="radio" aria-checked="...">`
|
||||||
|
- SVG glyph present in `.theme-notch-glyph`
|
||||||
|
|
||||||
|
### 5. JavaScript Execution
|
||||||
|
|
||||||
|
✅ **Inline scripts ARE executing** (no CSP block):
|
||||||
|
- Theme initialization script runs
|
||||||
|
- Service worker registration attempted
|
||||||
|
- Navigation toggle script runs
|
||||||
|
- Image lazy-load script runs
|
||||||
|
|
||||||
|
**Console errors (unrelated to theme-notch CSS):**
|
||||||
|
- `[ERROR] An unknown error occurred when fetching the script` (service worker)
|
||||||
|
- `[ERROR] Failed to load resource: net::ERR_INSUFFICIENT_RESOURCES` (analytics)
|
||||||
|
|
||||||
|
### 6. Network & Caching
|
||||||
|
|
||||||
|
- ✅ `/styles/global.css` returns **[200] OK**
|
||||||
|
- ✅ File loads successfully
|
||||||
|
- ❌ Content is stale/outdated
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What's Working
|
||||||
|
|
||||||
|
✅ HTML markup is present and correct
|
||||||
|
✅ JavaScript is executing without CSP errors
|
||||||
|
✅ Local development (`npm run dev`) works perfectly
|
||||||
|
✅ Local build (`npm run build`) generates correct CSS
|
||||||
|
✅ Network requests succeed
|
||||||
|
✅ Accessibility tree shows correct structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What's Broken
|
||||||
|
|
||||||
|
❌ Production CSS file is missing theme-notch rules
|
||||||
|
❌ CSS file size doesn't match local build
|
||||||
|
❌ Theme notch appears inline instead of fixed position
|
||||||
|
❌ Theme notch dropdown panel is not hidden initially
|
||||||
|
❌ Theme notch styling is completely absent
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
### The Problem
|
||||||
|
|
||||||
|
The production Docker image contains an **OLDER version of the CSS file** that was built **BEFORE the theme-notch CSS rules were added** to the source.
|
||||||
|
|
||||||
|
### Why This Happened
|
||||||
|
|
||||||
|
1. The theme-notch CSS rules exist in the source (`site/public/styles/global.css`)
|
||||||
|
2. The local build correctly includes them in the output (`site/dist/styles/global.css` - 24,279 bytes)
|
||||||
|
3. **BUT** the production Docker image contains an older version of the CSS file (~17,628 bytes)
|
||||||
|
4. This suggests:
|
||||||
|
- The Docker image was built from an older commit
|
||||||
|
- OR the CSS file was not updated in the Docker image
|
||||||
|
- OR there's a stale build artifact being served
|
||||||
|
|
||||||
|
### This is a DEPLOYMENT/CACHING issue, not a build issue
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification Performed
|
||||||
|
|
||||||
|
✅ Navigated to https://santhoshj.com and /blog
|
||||||
|
✅ Captured console errors and warnings
|
||||||
|
✅ Checked network requests (global.css loads with [200])
|
||||||
|
✅ Fetched and parsed production CSS file
|
||||||
|
✅ Searched for `.theme-notch` selectors (0 matches found)
|
||||||
|
✅ Inspected computed styles via browser DevTools
|
||||||
|
✅ Verified HTML markup is present and correct
|
||||||
|
✅ Confirmed inline scripts execute without CSP errors
|
||||||
|
✅ Compared with local source CSS (rules present locally)
|
||||||
|
✅ Ran local build and verified CSS includes theme-notch rules
|
||||||
|
✅ Compared file sizes (24,279 bytes local vs ~17,628 bytes production)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Fix
|
||||||
|
|
||||||
|
### Option 1: Rebuild and redeploy Docker image (RECOMMENDED)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In the project root
|
||||||
|
docker compose build --no-cache
|
||||||
|
docker compose push
|
||||||
|
# Deploy new image to production
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: If using CI/CD
|
||||||
|
|
||||||
|
- Ensure the latest commit is being built
|
||||||
|
- Verify the Docker build includes the latest `site/dist/` output
|
||||||
|
- Check that the image is being pushed with the correct tag
|
||||||
|
- Redeploy the image to production
|
||||||
|
|
||||||
|
### Option 3: Quick verification before deploying
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH into production server
|
||||||
|
# Check CSS file size
|
||||||
|
ls -lh /usr/share/nginx/html/styles/global.css
|
||||||
|
# Should show ~24,279 bytes (not ~17,628)
|
||||||
|
|
||||||
|
# Verify theme-notch rules exist
|
||||||
|
grep -c "theme-notch" /usr/share/nginx/html/styles/global.css
|
||||||
|
# Should show 30+ matches (not 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Expected Result After Fix
|
||||||
|
|
||||||
|
✅ Theme notch appears as a fixed button in top-right corner
|
||||||
|
✅ Clicking reveals a dropdown panel with Dark/Light/Contrast options
|
||||||
|
✅ Smooth animations and hover effects work
|
||||||
|
✅ CSS file size matches local build (~24,279 bytes)
|
||||||
|
✅ CSS file contains 30+ matches for "theme-notch"
|
||||||
|
✅ Computed styles show correct positioning and display properties
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Files Involved
|
||||||
|
|
||||||
|
| File | Purpose | Status |
|
||||||
|
|------|---------|--------|
|
||||||
|
| `site/public/styles/global.css` | Source CSS | ✅ Contains theme-notch rules (lines 306-457) |
|
||||||
|
| `site/dist/styles/global.css` | Local build output | ✅ 24,279 bytes, 30 theme-notch matches |
|
||||||
|
| `https://santhoshj.com/styles/global.css` | Production | ❌ ~17,628 bytes, 0 theme-notch matches |
|
||||||
|
| `Dockerfile` | Docker build | ⚠️ Copies from `site/dist/` |
|
||||||
|
| `site/src/components/BaseLayout.astro` | HTML template | ✅ Renders theme-notch markup |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Table
|
||||||
|
|
||||||
|
| Aspect | Local | Production | Status |
|
||||||
|
|--------|-------|-----------|--------|
|
||||||
|
| CSS file exists | ✅ Yes | ✅ Yes | OK |
|
||||||
|
| File size | 24,279 bytes | ~17,628 bytes | ❌ MISMATCH |
|
||||||
|
| theme-notch rules | 30 matches | 0 matches | ❌ MISSING |
|
||||||
|
| HTML markup | ✅ Present | ✅ Present | OK |
|
||||||
|
| JavaScript | ✅ Executing | ✅ Executing | OK |
|
||||||
|
| Computed styles | ✅ Correct | ❌ Wrong | BROKEN |
|
||||||
|
| Visual result | ✅ Fixed notch | ❌ Inline buttons | BROKEN |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
### The issue is NOT:
|
||||||
|
- ❌ CSP blocking inline scripts
|
||||||
|
- ❌ Missing HTML markup
|
||||||
|
- ❌ JavaScript not executing
|
||||||
|
- ❌ Browser caching
|
||||||
|
|
||||||
|
### The issue IS:
|
||||||
|
- ✅ **Production CSS file missing `.theme-notch` rules**
|
||||||
|
- ✅ **Stale Docker image serving outdated CSS**
|
||||||
|
- ✅ **Deployment/caching issue, not a build issue**
|
||||||
|
|
||||||
|
### Action Required:
|
||||||
|
**Rebuild and redeploy Docker image with latest source code.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Verify the fix**: Rebuild Docker image with latest source
|
||||||
|
2. **Deploy**: Pu
|
||||||
162
DIAGNOSIS_SUMMARY.txt
Normal file
162
DIAGNOSIS_SUMMARY.txt
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
================================================================================
|
||||||
|
PRODUCTION THEME NOTCH STYLING ISSUE - EXECUTIVE SUMMARY
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ISSUE: Theme notch appears as plain buttons in normal document flow on production
|
||||||
|
(https://santhoshj.com) instead of a fixed, positioned element in the
|
||||||
|
top-right corner with a dropdown panel.
|
||||||
|
|
||||||
|
ROOT CAUSE: Production server is serving a STALE CSS file (17,628 bytes) that
|
||||||
|
was built BEFORE the theme-notch CSS rules were added. The local
|
||||||
|
build correctly generates a 24,279 byte CSS file with all rules.
|
||||||
|
|
||||||
|
SEVERITY: CRITICAL - Component is completely unstyled and non-functional
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
EVIDENCE SUMMARY
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
1. CSS FILE SIZE MISMATCH
|
||||||
|
Local build: 24,279 bytes ✅ (includes theme-notch rules)
|
||||||
|
Production: ~17,628 bytes ❌ (missing theme-notch rules)
|
||||||
|
Difference: ~6,651 bytes (27% smaller)
|
||||||
|
|
||||||
|
2. THEME-NOTCH RULES
|
||||||
|
Local CSS: 30 matches for "theme-notch" ✅
|
||||||
|
Production CSS: 0 matches for "theme-notch" ❌
|
||||||
|
|
||||||
|
3. COMPUTED STYLES ON PRODUCTION
|
||||||
|
.theme-notch position: static (WRONG - should be: fixed)
|
||||||
|
.theme-notch top: auto (WRONG - should be: 84px)
|
||||||
|
.theme-notch right: auto (WRONG - should be: max(8px, env(...)))
|
||||||
|
.theme-notch z-index: auto (WRONG - should be: 12)
|
||||||
|
.theme-notch-panel display: block (WRONG - should be: grid)
|
||||||
|
.theme-notch-panel opacity: 1 (WRONG - should be: 0 initially)
|
||||||
|
|
||||||
|
4. HTML MARKUP
|
||||||
|
✅ Present and correct on both local and production
|
||||||
|
✅ All classes and attributes in place
|
||||||
|
✅ SVG glyph present
|
||||||
|
|
||||||
|
5. JAVASCRIPT EXECUTION
|
||||||
|
✅ Inline scripts ARE executing (no CSP block)
|
||||||
|
✅ Theme initialization script runs
|
||||||
|
✅ No JavaScript errors related to theme-notch
|
||||||
|
|
||||||
|
6. NETWORK & CACHING
|
||||||
|
✅ /styles/global.css returns [200] OK
|
||||||
|
✅ File loads successfully
|
||||||
|
❌ Content is stale/outdated
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
WHAT'S WORKING
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
✅ HTML markup is present and correct
|
||||||
|
✅ JavaScript is executing without CSP errors
|
||||||
|
✅ Local development (npm run dev) works perfectly
|
||||||
|
✅ Local build (npm run build) generates correct CSS
|
||||||
|
✅ Network requests succeed
|
||||||
|
✅ Accessibility tree shows correct structure
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
WHAT'S BROKEN
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
❌ Production CSS file is missing theme-notch rules
|
||||||
|
❌ CSS file size doesn't match local build
|
||||||
|
❌ Theme notch appears inline instead of fixed position
|
||||||
|
❌ Theme notch dropdown panel is not hidden initially
|
||||||
|
❌ Theme notch styling is completely absent
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
ROOT CAUSE ANALYSIS
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
The production Docker image contains an OLDER version of the CSS file that was
|
||||||
|
built BEFORE the theme-notch CSS rules were added to the source.
|
||||||
|
|
||||||
|
This is a DEPLOYMENT/CACHING issue, not a build issue.
|
||||||
|
|
||||||
|
Possible causes:
|
||||||
|
1. Docker image was built from an older commit
|
||||||
|
2. CSS file was not updated in the Docker image
|
||||||
|
3. Stale build artifact is being served
|
||||||
|
4. CI/CD pipeline didn't rebuild the image with latest source
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
VERIFICATION PERFORMED
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
✅ Navigated to https://santhoshj.com and /blog
|
||||||
|
✅ Captured console errors and warnings
|
||||||
|
✅ Checked network requests (global.css loads with [200])
|
||||||
|
✅ Fetched and parsed production CSS file
|
||||||
|
✅ Searched for .theme-notch selectors (0 matches found)
|
||||||
|
✅ Inspected computed styles via browser DevTools
|
||||||
|
✅ Verified HTML markup is present and correct
|
||||||
|
✅ Confirmed inline scripts execute without CSP errors
|
||||||
|
✅ Compared with local source CSS (rules present locally)
|
||||||
|
✅ Ran local build and verified CSS includes theme-notch rules
|
||||||
|
✅ Compared file sizes (24,279 bytes local vs ~17,628 bytes production)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
RECOMMENDED FIX
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
OPTION 1: Rebuild and redeploy Docker image
|
||||||
|
$ docker compose build --no-cache
|
||||||
|
$ docker compose push
|
||||||
|
# Deploy new image to production
|
||||||
|
|
||||||
|
OPTION 2: If using CI/CD
|
||||||
|
- Ensure latest commit is being built
|
||||||
|
- Verify Docker build includes latest site/dist/ output
|
||||||
|
- Check image is pushed with correct tag
|
||||||
|
- Redeploy image to production
|
||||||
|
|
||||||
|
OPTION 3: Quick verification before deploying
|
||||||
|
- SSH into production server
|
||||||
|
- Check CSS file size: should be ~24,279 bytes (not ~17,628)
|
||||||
|
- Verify /styles/global.css contains "theme-notch" (30+ matches)
|
||||||
|
- If not, redeploy the Docker image
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
EXPECTED RESULT AFTER FIX
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
✅ Theme notch appears as a fixed button in top-right corner
|
||||||
|
✅ Clicking reveals a dropdown panel with Dark/Light/Contrast options
|
||||||
|
✅ Smooth animations and hover effects work
|
||||||
|
✅ CSS file size matches local build (~24,279 bytes)
|
||||||
|
✅ CSS file contains 30+ matches for "theme-notch"
|
||||||
|
✅ Computed styles show correct positioning and display properties
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
FILES INVOLVED
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
Source: site/public/styles/global.css (lines 306-457)
|
||||||
|
Production: https://santhoshj.com/styles/global.css (missing rules)
|
||||||
|
Build: Dockerfile and npm run build process
|
||||||
|
HTML: site/src/components/BaseLayout.astro (renders theme-notch markup)
|
||||||
|
Local dist: site/dist/styles/global.css (24,279 bytes - CORRECT)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
CONCLUSION
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
The issue is NOT:
|
||||||
|
❌ CSP blocking inline scripts
|
||||||
|
❌ Missing HTML markup
|
||||||
|
❌ JavaScript not executing
|
||||||
|
❌ Browser caching
|
||||||
|
|
||||||
|
The issue IS:
|
||||||
|
✅ Production CSS file missing .theme-notch rules
|
||||||
|
✅ Stale Docker image serving outdated CSS
|
||||||
|
✅ Deployment/caching issue, not a build issue
|
||||||
|
|
||||||
|
ACTION REQUIRED: Rebuild and redeploy Docker image with latest source code.
|
||||||
|
|
||||||
|
================================================================================
|
||||||
@@ -4,6 +4,8 @@ WORKDIR /app/site
|
|||||||
|
|
||||||
ARG PUBLIC_ENABLE_SW=true
|
ARG PUBLIC_ENABLE_SW=true
|
||||||
ENV PUBLIC_ENABLE_SW=$PUBLIC_ENABLE_SW
|
ENV PUBLIC_ENABLE_SW=$PUBLIC_ENABLE_SW
|
||||||
|
ARG PUBLIC_ASSET_VERSION
|
||||||
|
ENV PUBLIC_ASSET_VERSION=$PUBLIC_ASSET_VERSION
|
||||||
|
|
||||||
# Public, build-time config (baked into static HTML via Astro/Vite).
|
# Public, build-time config (baked into static HTML via Astro/Vite).
|
||||||
ARG PUBLIC_SITE_URL
|
ARG PUBLIC_SITE_URL
|
||||||
|
|||||||
294
PRODUCTION_DIAGNOSIS.md
Normal file
294
PRODUCTION_DIAGNOSIS.md
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
# Production Theme Notch Styling Issue - Diagnostic Report
|
||||||
|
|
||||||
|
**Date**: 2026-02-10
|
||||||
|
**Status**: CRITICAL - CSS rules missing in production
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
The theme notch component appears as plain buttons in normal document flow on production (https://santhoshj.com) because **the CSS rules for `.theme-notch` and related selectors are completely absent from the served `/styles/global.css` file**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
### 1. CSS File Status
|
||||||
|
- **Local file**: `site/public/styles/global.css` ✅ **CONTAINS** `.theme-notch` rules (lines 306-457)
|
||||||
|
- **Production file**: `https://santhoshj.com/styles/global.css` ❌ **MISSING** `.theme-notch` rules
|
||||||
|
- **File size**: Local = 1215 lines; Production = ~17,628 bytes (109 CSS rules)
|
||||||
|
- **Network status**: [200] OK - file loads successfully
|
||||||
|
|
||||||
|
### 2. CSS Rules Missing in Production
|
||||||
|
|
||||||
|
**Local CSS (lines 306-457) includes:**
|
||||||
|
```css
|
||||||
|
.theme-notch {
|
||||||
|
position: fixed;
|
||||||
|
top: var(--theme-notch-top);
|
||||||
|
right: max(8px, env(safe-area-inset-right));
|
||||||
|
z-index: 12;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-notch-panel {
|
||||||
|
position: absolute;
|
||||||
|
right: 60px;
|
||||||
|
top: 0;
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--stroke-mid);
|
||||||
|
background: var(--surface-1);
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(10px) scale(0.98);
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 160ms ease, transform 160ms ease, visibility 0s linear 160ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-notch-handle { ... }
|
||||||
|
.theme-notch-glyph { ... }
|
||||||
|
.theme-notch-option { ... }
|
||||||
|
.theme-notch-dot { ... }
|
||||||
|
/* + media queries and forced-colors rules */
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production CSS**: ❌ **ZERO** matches for `.theme-notch*` selectors
|
||||||
|
|
||||||
|
### 3. Computed Styles on Production
|
||||||
|
|
||||||
|
**Actual computed styles (from browser DevTools):**
|
||||||
|
```
|
||||||
|
.theme-notch:
|
||||||
|
position: static (WRONG - should be: fixed)
|
||||||
|
top: auto (WRONG - should be: 84px)
|
||||||
|
right: auto (WRONG - should be: max(8px, env(safe-area-inset-right)))
|
||||||
|
display: block (CORRECT - but only by accident)
|
||||||
|
opacity: 1 (CORRECT - but only by accident)
|
||||||
|
visibility: visible (CORRECT - but only by accident)
|
||||||
|
z-index: auto (WRONG - should be: 12)
|
||||||
|
|
||||||
|
.theme-notch-panel:
|
||||||
|
position: static (WRONG - should be: absolute)
|
||||||
|
top: auto (WRONG - should be: 0)
|
||||||
|
right: auto (WRONG - should be: 60px)
|
||||||
|
display: block (WRONG - should be: grid)
|
||||||
|
opacity: 1 (WRONG - should be: 0 initially)
|
||||||
|
visibility: visible (WRONG - should be: hidden initially)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. HTML Markup Status
|
||||||
|
|
||||||
|
✅ **Present and correct:**
|
||||||
|
- `<aside class="theme-notch" aria-label="Theme" data-theme-notch="" data-open="false">`
|
||||||
|
- `<div class="theme-notch-panel" id="theme-notch-panel" role="radiogroup" aria-label="Theme selector">`
|
||||||
|
- `<button class="theme-notch-option" data-theme-option="dark|light|contrast" role="radio" aria-checked="...">`
|
||||||
|
- SVG glyph present in `.theme-notch-glyph`
|
||||||
|
|
||||||
|
### 5. JavaScript Execution
|
||||||
|
|
||||||
|
✅ **Inline scripts ARE executing** (no CSP block):
|
||||||
|
- Theme initialization script runs
|
||||||
|
- Service worker registration attempted (fails due to unrelated script fetch error)
|
||||||
|
- Navigation toggle script runs
|
||||||
|
- Image lazy-load script runs
|
||||||
|
|
||||||
|
**Console errors (unrelated to theme-notch CSS):**
|
||||||
|
- `[ERROR] An unknown error occurred when fetching the script` (service worker)
|
||||||
|
- `[ERROR] Failed to load resource: net::ERR_INSUFFICIENT_RESOURCES` (analytics)
|
||||||
|
|
||||||
|
### 6. Network & Caching
|
||||||
|
|
||||||
|
- `/styles/global.css` returns **[200] OK**
|
||||||
|
- No cache headers preventing updates detected
|
||||||
|
- File loads successfully but content is stale/incomplete
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
### Hypothesis: Build/Deployment Issue
|
||||||
|
|
||||||
|
The production CSS file is **missing the theme-notch rules entirely**, suggesting:
|
||||||
|
|
||||||
|
1. **Build process did not include the CSS** - The CSS file was generated/minified without the theme-notch section
|
||||||
|
2. **Stale build artifact** - An older version of global.css is being served
|
||||||
|
3. **CSS file truncation** - The build process may have failed to include lines 306-457 from the source
|
||||||
|
4. **Incorrect build output** - The CSS bundler/minifier may have stripped unused rules (unlikely, as the HTML uses the classes)
|
||||||
|
|
||||||
|
### Why It Works Locally
|
||||||
|
|
||||||
|
- `npm run dev` serves the source CSS directly from `site/public/styles/global.css`
|
||||||
|
- All rules are present and applied correctly
|
||||||
|
- Theme notch appears as a fixed, positioned element in the top-right corner
|
||||||
|
|
||||||
|
### Why It Fails in Production
|
||||||
|
|
||||||
|
- Docker build likely runs `npm run build` which may:
|
||||||
|
- Minify/bundle CSS differently
|
||||||
|
- Use a different CSS source file
|
||||||
|
- Strip rules based on unused CSS detection
|
||||||
|
- Output to a different location than `site/public/styles/global.css`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Visual Impact
|
||||||
|
|
||||||
|
**Expected (Local):**
|
||||||
|
- Theme notch appears as a fixed button in top-right corner
|
||||||
|
- Clicking reveals a dropdown panel with Dark/Light/Contrast options
|
||||||
|
- Smooth animations and hover effects
|
||||||
|
|
||||||
|
**Actual (Production):**
|
||||||
|
- Theme notch buttons appear inline in normal document flow
|
||||||
|
- No positioning, no dropdown panel
|
||||||
|
- Buttons are unstyled (only inherit default browser styles)
|
||||||
|
- Appears as plain radio buttons in the accessibility tree
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification Steps Performed
|
||||||
|
|
||||||
|
✅ Navigated to https://santhoshj.com and /blog
|
||||||
|
✅ Captured console errors and warnings
|
||||||
|
✅ Checked network requests (global.css loads with [200])
|
||||||
|
✅ Fetched and parsed production CSS file
|
||||||
|
✅ Searched for `.theme-notch` selectors (0 matches)
|
||||||
|
✅ Inspected computed styles via browser DevTools
|
||||||
|
✅ Verified HTML markup is present and correct
|
||||||
|
✅ Confirmed inline scripts execute without CSP errors
|
||||||
|
✅ Compared with local source CSS (rules present locally)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Actions
|
||||||
|
|
||||||
|
1. **Immediate**: Check the Docker build process
|
||||||
|
- Verify `npm run build` output includes theme-notch CSS
|
||||||
|
- Check if CSS is being minified/bundled to a different file
|
||||||
|
- Ensure `site/public/styles/global.css` is copied to the Docker image
|
||||||
|
|
||||||
|
2. **Verify**: Rebuild and redeploy
|
||||||
|
- Run `npm run build` locally and inspect the output CSS
|
||||||
|
- Check if `dist/styles/global.css` (or equivalent) contains theme-notch rules
|
||||||
|
- Verify the Docker image includes the correct CSS file
|
||||||
|
|
||||||
|
3. **Debug**: Add build logging
|
||||||
|
- Log CSS file size before/after minification
|
||||||
|
- Verify the CSS source file is being read correctly
|
||||||
|
- Check for any build warnings about unused CSS
|
||||||
|
|
||||||
|
4. **Test**: Validate production deployment
|
||||||
|
- After fix, verify `/styles/global.css` contains theme-notch rules
|
||||||
|
- Check computed styles in production browser DevTools
|
||||||
|
- Confirm theme notch appears in correct position
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Files Involved
|
||||||
|
|
||||||
|
- **Source**: `site/public/styles/global.css` (lines 306-457)
|
||||||
|
- **Production**: `https://santhoshj.com/styles/global.css` (missing rules)
|
||||||
|
- **Build**: `Dockerfile` and `npm run build` process
|
||||||
|
- **HTML**: `site/src/components/BaseLayout.astro` (renders theme-notch markup)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
**The issue is NOT:**
|
||||||
|
- ❌ CSP blocking inline scripts
|
||||||
|
- ❌ Missing HTML markup
|
||||||
|
- ❌ JavaScript not executing
|
||||||
|
- ❌ Browser caching (file loads fresh)
|
||||||
|
|
||||||
|
**The issue IS:**
|
||||||
|
- ✅ **Production CSS file missing `.theme-notch` rules**
|
||||||
|
- ✅ **Build/deployment process not including complete CSS**
|
||||||
|
|
||||||
|
The fix requires investigating the Docker build and CSS bundling process to ensure all CSS rules are included in the production output.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CRITICAL UPDATE: Root Cause Identified
|
||||||
|
|
||||||
|
### Build Verification Results
|
||||||
|
|
||||||
|
**Local Build (npm run build):**
|
||||||
|
- ✅ CSS file generated: `site/dist/styles/global.css`
|
||||||
|
- ✅ File size: **24,279 bytes**
|
||||||
|
- ✅ Theme-notch rules: **30 matches** found
|
||||||
|
- ✅ All CSS rules present and correct
|
||||||
|
|
||||||
|
**Production Server:**
|
||||||
|
- ❌ CSS file served: `https://santhoshj.com/styles/global.css`
|
||||||
|
- ❌ File size: **~17,628 bytes** (SMALLER than local build)
|
||||||
|
- ❌ Theme-notch rules: **0 matches** found
|
||||||
|
- ❌ CSS is STALE/OUTDATED
|
||||||
|
|
||||||
|
### Conclusion
|
||||||
|
|
||||||
|
**The production server is serving an OLD version of the CSS file that was built BEFORE the theme-notch CSS rules were added to the source.**
|
||||||
|
|
||||||
|
This is a **deployment/caching issue**, not a build issue.
|
||||||
|
|
||||||
|
### Why This Happened
|
||||||
|
|
||||||
|
1. The theme-notch CSS rules exist in the source (`site/public/styles/global.css`)
|
||||||
|
2. The local build correctly includes them in the output (`site/dist/styles/global.css`)
|
||||||
|
3. **BUT** the production Docker image contains an older version of the CSS file
|
||||||
|
4. This suggests:
|
||||||
|
- The Docker image was built from an older commit
|
||||||
|
- OR the CSS file was not updated in the Docker image
|
||||||
|
- OR there's a caching layer serving stale content
|
||||||
|
|
||||||
|
### Fix Required
|
||||||
|
|
||||||
|
**Option 1: Rebuild and redeploy the Docker image**
|
||||||
|
```bash
|
||||||
|
docker compose build --no-cache
|
||||||
|
docker compose push
|
||||||
|
# Deploy new image to production
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2: If using CI/CD**
|
||||||
|
- Ensure the latest commit is being built
|
||||||
|
- Verify the Docker build includes the latest `site/dist/` output
|
||||||
|
- Check that the image is being pushed with the correct tag
|
||||||
|
- Redeploy the image to production
|
||||||
|
|
||||||
|
**Option 3: Quick verification**
|
||||||
|
- SSH into production server
|
||||||
|
- Check the CSS file size: should be ~24,279 bytes (not ~17,628)
|
||||||
|
- Verify `/styles/global.css` contains "theme-notch" (30+ matches)
|
||||||
|
- If not, redeploy the Docker image
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary Table
|
||||||
|
|
||||||
|
| Aspect | Local | Production | Status |
|
||||||
|
|--------|-------|-----------|--------|
|
||||||
|
| CSS file exists | ✅ Yes | ✅ Yes | OK |
|
||||||
|
| File size | 24,279 bytes | ~17,628 bytes | ❌ MISMATCH |
|
||||||
|
| theme-notch rules | 30 matches | 0 matches | ❌ MISSING |
|
||||||
|
| HTML markup | ✅ Present | ✅ Present | OK |
|
||||||
|
| JavaScript | ✅ Executing | ✅ Executing | OK |
|
||||||
|
| Computed styles | ✅ Correct | ❌ Wrong | BROKEN |
|
||||||
|
| Visual result | ✅ Fixed notch | ❌ Inline buttons | BROKEN |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Verify the fix**: Rebuild Docker image with latest source
|
||||||
|
2. **Deploy**: Push new image to production
|
||||||
|
3. **Test**: Verify `/styles/global.css` is ~24,279 bytes and contains theme-notch rules
|
||||||
|
4. **Validate**: Check production site - theme notch should appear in top-right corner
|
||||||
|
5. **Monitor**: Watch for any other stale assets
|
||||||
|
|
||||||
BIN
blog-screenshot.png
Normal file
BIN
blog-screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 971 KiB |
@@ -6,6 +6,16 @@ server {
|
|||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
# Static assets
|
# Static assets
|
||||||
|
location = /sw.js {
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /styles/global.css {
|
||||||
|
add_header Cache-Control "no-cache" always;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
# Serve directory index pages without requiring a trailing slash.
|
# Serve directory index pages without requiring a trailing slash.
|
||||||
# This fixes /videos (and similar) resolving to /videos/index.html.
|
# This fixes /videos (and similar) resolving to /videos/index.html.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ services:
|
|||||||
args:
|
args:
|
||||||
# Build-time toggle for service worker registration in the generated static HTML.
|
# Build-time toggle for service worker registration in the generated static HTML.
|
||||||
PUBLIC_ENABLE_SW: ${PUBLIC_ENABLE_SW:-true}
|
PUBLIC_ENABLE_SW: ${PUBLIC_ENABLE_SW:-true}
|
||||||
|
PUBLIC_ASSET_VERSION: ${PUBLIC_ASSET_VERSION:-}
|
||||||
# Public, build-time config baked into the HTML.
|
# Public, build-time config baked into the HTML.
|
||||||
PUBLIC_SITE_URL: ${PUBLIC_SITE_URL:-}
|
PUBLIC_SITE_URL: ${PUBLIC_SITE_URL:-}
|
||||||
PUBLIC_UMAMI_SCRIPT_URL: ${PUBLIC_UMAMI_SCRIPT_URL:-}
|
PUBLIC_UMAMI_SCRIPT_URL: ${PUBLIC_UMAMI_SCRIPT_URL:-}
|
||||||
|
|||||||
BIN
homepage-screenshot.png
Normal file
BIN
homepage-screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 800 KiB |
@@ -4,14 +4,26 @@
|
|||||||
- Images: cache-first with bounded eviction
|
- Images: cache-first with bounded eviction
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Bump this value on deploy to invalidate caches.
|
const cacheVersionFromUrl = (() => {
|
||||||
const CACHE_VERSION = "v4";
|
try {
|
||||||
|
const v = new URL(self.location.href).searchParams.get("v");
|
||||||
|
if (!v) return null;
|
||||||
|
if (!/^[a-zA-Z0-9._-]{1,64}$/.test(v)) return null;
|
||||||
|
return v;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const CACHE_VERSION = cacheVersionFromUrl ? `v-${cacheVersionFromUrl}` : "v4";
|
||||||
|
|
||||||
const CACHE_SHELL = `shell-${CACHE_VERSION}`;
|
const CACHE_SHELL = `shell-${CACHE_VERSION}`;
|
||||||
const CACHE_PAGES = `pages-${CACHE_VERSION}`;
|
const CACHE_PAGES = `pages-${CACHE_VERSION}`;
|
||||||
const CACHE_MEDIA = `media-${CACHE_VERSION}`;
|
const CACHE_MEDIA = `media-${CACHE_VERSION}`;
|
||||||
|
|
||||||
const SHELL_ASSETS = ["/", "/styles/global.css", "/favicon.png", "/robots.txt"];
|
const assetSuffix = cacheVersionFromUrl ? `?v=${encodeURIComponent(cacheVersionFromUrl)}` : "";
|
||||||
|
|
||||||
|
const SHELL_ASSETS = ["/", `/styles/global.css${assetSuffix}`, "/favicon.png", "/robots.txt"];
|
||||||
|
|
||||||
// Cache.addAll() throws if there are any duplicate requests.
|
// Cache.addAll() throws if there are any duplicate requests.
|
||||||
const SHELL_ASSETS_UNIQUE = Array.from(new Set(SHELL_ASSETS));
|
const SHELL_ASSETS_UNIQUE = Array.from(new Set(SHELL_ASSETS));
|
||||||
|
|||||||
1
site/src/env.d.ts
vendored
1
site/src/env.d.ts
vendored
@@ -5,6 +5,7 @@ interface ImportMetaEnv {
|
|||||||
readonly PUBLIC_UMAMI_SCRIPT_URL?: string;
|
readonly PUBLIC_UMAMI_SCRIPT_URL?: string;
|
||||||
readonly PUBLIC_UMAMI_WEBSITE_ID?: string;
|
readonly PUBLIC_UMAMI_WEBSITE_ID?: string;
|
||||||
readonly PUBLIC_ENABLE_SW?: string;
|
readonly PUBLIC_ENABLE_SW?: string;
|
||||||
|
readonly PUBLIC_ASSET_VERSION?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ const cfg = getPublicConfig();
|
|||||||
|
|
||||||
const siteUrl = (cfg.siteUrl || "http://localhost:4321").replace(/\/$/, "");
|
const siteUrl = (cfg.siteUrl || "http://localhost:4321").replace(/\/$/, "");
|
||||||
const canonicalUrl = `${siteUrl}${canonicalPath.startsWith("/") ? canonicalPath : `/${canonicalPath}`}`;
|
const canonicalUrl = `${siteUrl}${canonicalPath.startsWith("/") ? canonicalPath : `/${canonicalPath}`}`;
|
||||||
|
|
||||||
|
const assetSuffix = cfg.assetVersion ? `?v=${encodeURIComponent(cfg.assetVersion)}` : "";
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -48,7 +50,7 @@ const canonicalUrl = `${siteUrl}${canonicalPath.startsWith("/") ? canonicalPath
|
|||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/styles/global.css" />
|
<link rel="stylesheet" href={`/styles/global.css${assetSuffix}`} />
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
(() => {
|
(() => {
|
||||||
@@ -117,12 +119,13 @@ const canonicalUrl = `${siteUrl}${canonicalPath.startsWith("/") ? canonicalPath
|
|||||||
// Register SW only in production builds (Astro sets import.meta.env.PROD at build time).
|
// Register SW only in production builds (Astro sets import.meta.env.PROD at build time).
|
||||||
// Allow opting out via PUBLIC_ENABLE_SW="false".
|
// Allow opting out via PUBLIC_ENABLE_SW="false".
|
||||||
import.meta.env.PROD && import.meta.env.PUBLIC_ENABLE_SW !== "false" ? (
|
import.meta.env.PROD && import.meta.env.PUBLIC_ENABLE_SW !== "false" ? (
|
||||||
<script is:inline>
|
<script is:inline define:vars={{ assetSuffix }}>
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
// SW requires HTTPS (or localhost). In prod we expect HTTPS.
|
// SW requires HTTPS (or localhost). In prod we expect HTTPS.
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () => {
|
||||||
|
const swUrl = "/sw.js" + assetSuffix;
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register("/sw.js", { scope: "/", updateViaCache: "none" })
|
.register(swUrl, { scope: "/", updateViaCache: "none" })
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// Progressive enhancement; keep failures non-fatal.
|
// Progressive enhancement; keep failures non-fatal.
|
||||||
console.warn("Service worker registration failed", err);
|
console.warn("Service worker registration failed", err);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
type PublicConfig = {
|
type PublicConfig = {
|
||||||
siteUrl?: string;
|
siteUrl?: string;
|
||||||
|
assetVersion?: string;
|
||||||
umami?: {
|
umami?: {
|
||||||
scriptUrl: string;
|
scriptUrl: string;
|
||||||
websiteId: string;
|
websiteId: string;
|
||||||
@@ -23,11 +24,13 @@ type IngestConfig = {
|
|||||||
|
|
||||||
export function getPublicConfig(): PublicConfig {
|
export function getPublicConfig(): PublicConfig {
|
||||||
const siteUrl = import.meta.env.PUBLIC_SITE_URL;
|
const siteUrl = import.meta.env.PUBLIC_SITE_URL;
|
||||||
|
const assetVersion = import.meta.env.PUBLIC_ASSET_VERSION;
|
||||||
const scriptUrl = import.meta.env.PUBLIC_UMAMI_SCRIPT_URL;
|
const scriptUrl = import.meta.env.PUBLIC_UMAMI_SCRIPT_URL;
|
||||||
const websiteId = import.meta.env.PUBLIC_UMAMI_WEBSITE_ID;
|
const websiteId = import.meta.env.PUBLIC_UMAMI_WEBSITE_ID;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
siteUrl,
|
siteUrl,
|
||||||
|
assetVersion,
|
||||||
umami: scriptUrl && websiteId ? { scriptUrl, websiteId } : undefined,
|
umami: scriptUrl && websiteId ? { scriptUrl, websiteId } : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user