Problems Solved
Session: January 30, 2026
Project: fogserv.cloud Website Rebuild
This document tracks technical issues encountered during development and their solutions, serving as a troubleshooting guide for future sessions.
Problem #1: React Hydration Error - HTML in JSX
Timestamp: January 30, 2026 03:02 AM
Error Message
In HTML, <html> cannot be a child of <div>.
This will cause a hydration error.
validateDOMNesting @ react-dom_client.js:2148
Root Cause
React root component (__root.tsx) was rendering full HTML structure:
function Root() {
return (
<html lang="en">
<head>...</head>
<body>...</body>
</html>
)
}
But React mounts inside <div id="root"> in index.html, causing invalid nesting.
Solution
Changed: src/routes/__root.tsx
function Root() {
return (
<div className="min-h-screen">
<Outlet />
</div>
)
}
Changed: index.html (proper HTML structure)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>fogserv.cloud</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Key Insight
React hydration expects to find existing DOM nodes, not create the entire HTML document. The HTML shell must exist before React mounts.
Prevention
- Understand SSR/CSR boundaries
- Keep static HTML in index.html
- React components manage content within #root only
Problem #2: PostCSS Configuration Error
Timestamp: January 30, 2026 03:03 AM
Error Message
[plugin:vite:css] Failed to load PostCSS config
ReferenceError: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension
and package.json contains "type": "module"
Root Cause
postcss.config.js used CommonJS syntax:
module.exports = {
plugins: { ... }
}
But package.json has "type": "module", making all .js files ES modules by default.
Solution
Changed: postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Key Insight
When "type": "module" is set in package.json, use:
- ES modules:
export default(for.jsfiles) - CommonJS:
module.exports(for.cjsfiles only)
Prevention
- Check package.json type field
- Use consistent module syntax across config files
- Or explicitly use
.cjsextension for CommonJS
Problem #3: Tailwind CSS Plugin Error
Timestamp: January 30, 2026 03:03 AM
Error Message
[postcss] It looks like you're trying to use `tailwindcss` directly as a PostCSS plugin.
The PostCSS plugin has moved to a separate package, so to continue using Tailwind CSS
with PostCSS you'll need to install `@tailwindcss/postcss`
Root Cause
Tailwind v4 architecture changed. The PostCSS plugin is now a separate package.
Old config (doesn't work in v4):
export default {
plugins: {
tailwindcss: {}, // ❌ Wrong in v4
},
}
Solution
Installed:
bun add -d @tailwindcss/postcss
Changed: postcss.config.js
export default {
plugins: {
'@tailwindcss/postcss': {}, // ✅ Correct for v4
},
}
Changed: src/index.css
/* Old v3 syntax */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* New v4 syntax */
@import "tailwindcss";
Key Insight
Tailwind v4 is a major architectural shift. Check migration guide when upgrading.
Prevention
- Read changelog for major version bumps
- Test in dev environment first
- Update all related config files together
Problem #4: TanStack Router Type Errors
Timestamp: January 30, 2026 03:04 AM (Minor issue)
Error Message
Argument of type '"/"' is not assignable to parameter of type 'undefined'
Root Cause
Importing route components incorrectly from separate files caused type mismatches.
Solution
Consolidated router setup into src/main.tsx with inline component definitions:
const rootRoute = createRootRoute({ component: RootLayout })
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: HomePage,
})
Key Insight
For MVP, inline route definitions are simpler than file-based routing. Can refactor later with @tanstack/router-plugin.
Prevention
- Start with simplest architecture
- Add complexity only when needed
- File-based routing can come later
Problem #5: Empty Site Complaint
Timestamp: January 30, 2026 03:08 AM
Issue
User feedback: "it's a very empty site"
Root Cause
Initial implementation only had homepage with three cards. No navigation, footer, or additional pages.
Solution
Built comprehensive multi-page site:
- Navigation header with routing
- Footer with resources and links
- Enhanced homepage (hero, mission, blog previews)
- Full About page
- Blog page with article previews
- Knowledge Base page with KB document cards
Added:
- ~400 lines of UI code
- 4 complete pages
- Responsive design
- Proper information architecture
Key Insight
"MVP" doesn't mean "minimal content." A credible site needs:
- Clear navigation
- Multiple pages with substance
- Calls to action
- Footer with context
Prevention
- Define "complete page" criteria upfront
- Show wireframes before coding
- Get feedback early on content depth
Near-Misses (Avoided Problems)
❌ Almost: Hardcoded Secrets
Risk: Could have put database URLs directly in code
Avoided: Setup dotenvx from day one
Prevention: Never commit secrets; use environment variables
❌ Almost: No Documentation
Risk: Could have rushed features without docs
Avoided: Created KB structure immediately
Prevention: Document decisions as they're made
❌ Almost: Monolithic Files
Risk: Could have put entire site in one component
Avoided: Structured with clear component boundaries
Prevention: Plan component hierarchy before coding
Troubleshooting Checklist
When encountering errors, check:
For Module/Import Errors
- ✅ Is
"type": "module"in package.json? - ✅ Using correct syntax (ES or CommonJS)?
- ✅ Are dependencies installed?
- ✅ Is TypeScript config correct?
For React Hydration Errors
- ✅ Is HTML structure only in index.html?
- ✅ Are React components only inside #root?
- ✅ No
<html>,<head>,<body>in JSX? - ✅ Server and client rendering same output?
For PostCSS/Tailwind Errors
- ✅ Is
@tailwindcss/postcssinstalled (not justtailwindcss)? - ✅ Is config using ES module syntax?
- ✅ Is CSS using
@import "tailwindcss"(not directives)? - ✅ Are content paths configured correctly?
For Environment Variable Issues
- ✅ Does
.envfile exist? - ✅ Are scripts wrapped with
dotenvx run --? - ✅ Are variable names spelled correctly?
- ✅ Is dotenvx outputting injection message?
Performance Notes
Build Times
- Initial Vite startup: ~1.7 seconds
- Prisma client generation: ~73ms
- Bun package install: ~80 seconds (825 packages)
- Hot module reload: < 100ms
No Issues Encountered
- ✅ Bun compatibility
- ✅ TypeScript compilation
- ✅ TanStack Router performance
- ✅ Tailwind CSS compilation
- ✅ Vite HMR speed
Resources Used
Documentation
- React 19 docs: https://react.dev
- TanStack Router: https://tanstack.com/router
- Tailwind v4 migration: https://tailwindcss.com/docs/upgrade-guide
- Prisma docs: https://prisma.io/docs
- dotenvx: https://dotenvx.com
Stack Overflow
- React hydration errors
- ES module vs CommonJS
GitHub Issues
- Tailwind v4 PostCSS plugin migration
- TanStack Router type definitions
Future Gotchas to Watch
- Prisma Migrations: Ensure DATABASE_URL points to correct DB for migrations
- Tailwind Purging: Configure content paths carefully for production builds
- Environment Variables: Prefix with VITE_ for client-side access
- React Router: File-based routing will need @tanstack/router-plugin
- TypeScript Strict Mode: May reveal type issues when enabled
Last Updated: January 30, 2026 03:18 AM
Total Problems Solved: 5
Average Resolution Time: < 5 minutes per issue
Related Files:
/kb/lessons-learned.md- Session insights/kb/implementations.md- Architecture decisions/kb/tasks.md- Project tracking
2026-08-28 — Container isolation / CI / Caddy / Auth
- Container deploy uses rootless Podman (
podman run -d --name fogserv-cloud -p 127.0.0.1:8080:8080 --restart=always -v ~/fogserv.db:/app/dev.db -e DATABASE_URL="file:./dev.db" ...). - CI deploy (
deploy-site.yml): builds image, pushes to GHCR, SSH deploys viapodman pull+podman compose up -d(serviceweb), smoke tests port 8080. .dockerignoreexcludesEnterprise/,node_modules,.env,dev.db.- SQLite production DB mounted at
~/fogserv.db. - Auto-admin:
handleAuthRegisterpromotes anyemail.endsWith("@fogserv.cloud")torole: "ADMIN". - Vite preview:
allowedHostsmust includefogserv.cloud. - Caddy:
fogserv.cloud { reverse_proxy 127.0.0.1:8080; encode zstd; header { Cache-Control "public, max-age=86400" } }. - ACME rate limit workaround:
tls internalin Caddy snippet; restore after ~1h. - Traefik killed (
kill -9 2975402); nginx masked/stopped; k3s service masked/disabled; binary remains at/usr/local/bin/k3s(not removed).
Problem #18: ACME Rate-Limited + Traefik Default Cert Conflict (2026-08-28)
Status: Resolved (workaround applied; full resolution pending ACME rate-limit expiry ~13:32 UTC).
Symptoms
curl -k https://fogserv.cloud/returnedTRAEFIK DEFAULT CERT(old k3s ingress).- Caddy ACME errors:
HTTP 429 urn:ietf:params:acme:error:rateLimited. podman psshowed container running but site unreachable.
Root Cause
- Old k3s/Traefik ingress controller (PID 2975402) still serving HTTPS on port 443.
- Caddy could not bind port 80 for ACME because nginx (PID 812) was running.
- After cleaning both, ACME rate limits prevented new cert issuance.
Resolution
- Killed Traefik (
kill -9 2975402) and nginx. - Disabled/masked
k3s.service; binary remains at/usr/local/bin/k3s. - Updated Caddyfile:
fogserv.cloud { tls internal; reverse_proxy 127.0.0.1:8080; ... }(temporary self-signed cert). - Restarted Caddy (
systemctl restart caddy). - Container (
fogserv-cloud) restarted with SQLite volume (~/fogserv.dbmounted to/app/dev.db).
Workaround Note
tls internal serves a self-signed certificate temporarily. Once ACME rate limits expire (~2026-08-28 13:32 UTC), remove tls internal from /etc/caddy/Caddyfile, restart Caddy (systemctl restart caddy), and a real Let's Encrypt cert will be obtained.