Skip to content

Enable global SSR for SEO with responsive CSS and chart guards - #73

Open
google-labs-jules[bot] wants to merge 1 commit into
mainfrom
jules/seo-job-board-responsive-css-js0-89bd343d-bde1-4cad-be80-9ba036ed5ca0
Open

Enable global SSR for SEO with responsive CSS and chart guards#73
google-labs-jules[bot] wants to merge 1 commit into
mainfrom
jules/seo-job-board-responsive-css-js0-89bd343d-bde1-4cad-be80-9ba036ed5ca0

Conversation

@google-labs-jules

Copy link
Copy Markdown
Contributor

Summary

This Pull Request re-enables global server-side rendering (SSR) to allow search engines to index public job listings, while resolving previous issues with server-side crashes and hydration mismatches. By offloading layout responsiveness to pure CSS and wrapping browser-dependent scripts/charts in client-side mounting guards, we achieve full search-engine crawlability without compromising layout stability or runtime performance.


Why These Changes Are Necessary

The Problem

Previously, global SSR was disabled (export const ssr = false;) to prevent server-side crashes caused by client-dependent analytics scripts, device detection, and DOM-dependent data visualizations (Vega-Lite). However, disabling SSR meant that search engine crawlers received empty HTML shells, preventing them from indexing public job listings and hurting organic traffic acquisition.

The Solution

We have re-enabled global SSR to ensure crawlers get fully-rendered HTML from the initial response. To prevent the crashes and hydration mismatches that previously plagued the system, we adopted three design patterns:

  1. Strict Client-Side Initialization: Moved environment-dependent initializations (like Vercel Analytics) into client-only hooks (onMount).
  2. CSS-First Responsiveness: Eliminated runtime JS device detection (Device.isMobile) in favor of fluid Tailwind CSS responsive classes. This ensures the initial server render matches the client paint, dropping hydration errors to zero.
  3. Mount Guards with Fluid Skeletons: Deferred rendering of interactive charts until Svelte's onMount fires, using structured pulse skeletons to reserve layout space and eliminate Cumulative Layout Shift (CLS).

What Changed

1. Re-enabled Server-Side Rendering (SSR)

  • File: src/routes/+layout.server.ts
  • Change: Changed export const ssr = false; to export const ssr = true;.
  • Impact: Public job list and detail pages are now pre-rendered on the server, exposing structured job data directly in the raw HTML payload.

2. Isolated Client-Only Analytics

  • File: src/routes/+layout.svelte
  • Change: Wrapped the Vercel Analytics inject() function inside Svelte's onMount lifecycle hook.
  • Impact: Prevents server-side pre-rendering failures caused by referencing browser-specific globals (window and document).

3. Transitioned to Pure CSS Responsive Layouts

  • File: src/routes/+page.svelte
  • Change: Completely removed svelte-device-info import and runtime Device.isMobile checks. Replaced the sidebar container styles with Tailwind CSS responsive utilities:
    class="transition-all duration-300 ease-in-out w-0 opacity-0 overflow-hidden md:w-[300px] md:opacity-100 md:overflow-visible flex shrink-0 flex-col gap-2"
  • Impact: Prevents structural layout shifts and hydration errors during loading across different screen sizes.

4. Added Mount Guards and Skeletons for Interactive Charts

  • File: src/lib/components/PostFilters.svelte
  • Change: Introduced an isMounted state variable that switches to true on mount. While false, we render fluid, pulse-animated SVG skeletons in place of the Vega-Lite charts.
  • Impact: Eliminates DOM-dependent charting crashes on the server, while preserving layout geometry to prevent visual jumps on hydration.

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
vis-positions Ready Ready Preview Aug 1, 2026 9:24am

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.

0 participants