Skip to content

Commit 6c8d648

Browse files
committed
Initial SSR support for stations
1 parent 3b9a084 commit 6c8d648

8 files changed

Lines changed: 79 additions & 76 deletions

File tree

package-lock.json

Lines changed: 14 additions & 52 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
"concurrently": "^9.2.1"
1717
},
1818
"dependencies": {
19-
"@neaps/api": "https://pkg.pr.new/openwatersio/neaps/@neaps/api@249",
20-
"@neaps/react": "https://pkg.pr.new/openwatersio/neaps/@neaps/react@249",
19+
"@neaps/api": "https://pkg.pr.new/openwatersio/neaps/@neaps/api@2b4cce8",
20+
"@neaps/react": "https://pkg.pr.new/openwatersio/neaps/@neaps/react@2b4cce8",
2121
"@neaps/tide-database": "^0.7.20260304",
22-
"@neaps/tide-predictor": "https://pkg.pr.new/openwatersio/neaps/@neaps/tide-predictor@249",
23-
"neaps": "https://pkg.pr.new/openwatersio/neaps@249"
22+
"@neaps/tide-predictor": "https://pkg.pr.new/openwatersio/neaps/@neaps/tide-predictor@2b4cce8",
23+
"neaps": "https://pkg.pr.new/openwatersio/neaps@2b4cce8"
2424
}
2525
}

website/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"clsx": "^2.1.1",
2828
"coordinate-format": "^1.0.0",
2929
"maplibre-gl": "^5.19.0",
30-
"neaps": "https://pkg.pr.new/openwatersio/neaps@d84bf68",
30+
"neaps": "*",
3131
"react": "^18.3.1",
3232
"react-dom": "^18.3.1",
3333
"react-map-gl": "^8.1.0",

website/src/components/tides/NearbyStations.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
1-
import { useRef, useCallback } from "react";
1+
import { useRef, useCallback, useMemo } from "react";
22
import {
33
NeapsProvider,
44
StationsMap,
55
NearbyStations,
6+
createQueryClient,
67
type StationSummary,
78
} from "@neaps/react";
9+
import { hydrate, type DehydratedState } from "@tanstack/react-query";
810
import type { MapRef } from "react-map-gl/maplibre";
911
import "@neaps/react/styles.css";
1012
import { API_HOST } from "../../utils/constants";
11-
import { preferredUnits } from "../../utils/units";
1213
import { useMapStyle } from "../../utils/useMapStyle";
1314

1415
interface Props {
1516
stationId: string;
1617
latitude: number;
1718
longitude: number;
19+
dehydratedState?: DehydratedState;
1820
}
1921

2022
export function NearbyStationsIsland({
2123
stationId,
2224
latitude,
2325
longitude,
26+
dehydratedState,
2427
}: Props) {
28+
const queryClient = useMemo(() => {
29+
const client = createQueryClient();
30+
if (dehydratedState) {
31+
hydrate(client, dehydratedState);
32+
}
33+
return client;
34+
}, [dehydratedState]);
35+
2536
const mapStyle = useMapStyle();
2637
const mapRef = useRef<MapRef>(null);
2738

@@ -38,7 +49,7 @@ export function NearbyStationsIsland({
3849
}, [longitude, latitude]);
3950

4051
return (
41-
<NeapsProvider baseUrl={API_HOST} units={preferredUnits}>
52+
<NeapsProvider baseUrl={API_HOST} queryClient={queryClient}>
4253
<div className="flex flex-col gap-4">
4354
<StationsMap
4455
ref={mapRef}

website/src/components/tides/StationsMapIsland.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { type ReactNode, useCallback } from "react";
22
import { NeapsProvider, StationsMap, StationSearch } from "@neaps/react";
33
import "@neaps/react/styles.css";
44
import { API_HOST } from "../../utils/constants";
5-
import { preferredUnits } from "../../utils/units";
65
import { BottomDrawer } from "../ui/BottomDrawer";
76
import { useMapStyle } from "../../utils/useMapStyle";
87

@@ -17,7 +16,7 @@ export function StationsMapIsland({ children }: Props) {
1716
}, []);
1817

1918
return (
20-
<NeapsProvider baseUrl={API_HOST} units={preferredUnits}>
19+
<NeapsProvider baseUrl={API_HOST}>
2120
{/* Inline height so h-full on StationsMap resolves; calc subtracts the fixed header */}
2221
<div className="absolute inset-0 h-full w-full">
2322
<StationsMap
@@ -32,7 +31,10 @@ export function StationsMapIsland({ children }: Props) {
3231
>
3332
{/* Desktop sidebar */}
3433
<div className="header-padding absolute top-0 left-4 z-10 hidden w-96 flex-col gap-4 md:flex">
35-
<StationSearch onSelect={handleStationSelect} />
34+
<StationSearch
35+
onSelect={handleStationSelect}
36+
className="card-glass rounded-3xl p-0"
37+
/>
3638
{children}
3739
</div>
3840

website/src/components/tides/TideStationIsland.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Component, type ReactNode } from "react";
2-
import { NeapsProvider, TideStation } from "@neaps/react";
1+
import { Component, type ReactNode, useMemo } from "react";
2+
import { NeapsProvider, TideStation, createQueryClient } from "@neaps/react";
3+
import { hydrate, type DehydratedState } from "@tanstack/react-query";
34
import "@neaps/react/styles.css";
45
import { API_HOST } from "../../utils/constants";
5-
import { preferredUnits } from "../../utils/units";
66

77
class ErrorBoundary extends Component<
88
{ children: ReactNode },
@@ -27,12 +27,21 @@ class ErrorBoundary extends Component<
2727

2828
interface Props {
2929
id: string;
30+
dehydratedState?: DehydratedState;
3031
}
3132

32-
export function TideStationIsland({ id }: Props) {
33+
export function TideStationIsland({ id, dehydratedState }: Props) {
34+
const queryClient = useMemo(() => {
35+
const client = createQueryClient();
36+
if (dehydratedState) {
37+
hydrate(client, dehydratedState);
38+
}
39+
return client;
40+
}, [dehydratedState]);
41+
3342
return (
3443
<ErrorBoundary>
35-
<NeapsProvider baseUrl={API_HOST} units={preferredUnits}>
44+
<NeapsProvider baseUrl={API_HOST} queryClient={queryClient}>
3645
<TideStation id={id} />
3746
</NeapsProvider>
3847
</ErrorBoundary>

website/src/pages/tides/stations/[...id].astro

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import { TideStationIsland } from "../../../components/tides/TideStationIsland";
77
import { NearbyStationsIsland } from "../../../components/tides/NearbyStations";
88
import { Icon } from "astro-icon/components";
99
import { API_HOST } from "../../../utils/constants";
10+
import {
11+
createQueryClient,
12+
prefetchTideStation,
13+
prefetchNearbyStations,
14+
dehydrate,
15+
} from "@neaps/react";
1016
1117
// Enable server-side rendering for this route
1218
export const prerender = false;
@@ -26,6 +32,21 @@ if (station.offsets?.reference) {
2632
referenceStation = await refResponse.json();
2733
}
2834
}
35+
36+
// Determine locale from Accept-Language header
37+
const acceptLang = Astro.request.headers.get("accept-language") ?? "";
38+
const locale = acceptLang.split(",")[0]?.split(";")[0]?.trim() || "en-US";
39+
40+
// Prefetch tide data so React islands render with data immediately
41+
const queryClient = createQueryClient();
42+
await Promise.all([
43+
prefetchTideStation(queryClient, API_HOST, station.id, { locale }),
44+
prefetchNearbyStations(queryClient, API_HOST, {
45+
latitude: station.latitude,
46+
longitude: station.longitude,
47+
}),
48+
]);
49+
const dehydratedState = dehydrate(queryClient);
2950
---
3051

3152
<MainLayout title={station.name} description={`Tide station: ${station.name}`}>
@@ -58,7 +79,11 @@ if (station.offsets?.reference) {
5879
)
5980
}
6081

61-
<TideStationIsland client:load id={station.id} />
82+
<TideStationIsland
83+
client:load
84+
id={station.id}
85+
dehydratedState={dehydratedState}
86+
/>
6287

6388
<Card class="mt-8">
6489
<section>
@@ -288,6 +313,7 @@ console.log(extremes);`}</code></pre>
288313
stationId={station.id}
289314
latitude={station.latitude}
290315
longitude={station.longitude}
316+
dehydratedState={dehydratedState}
291317
/>
292318
</div>
293319
</div>

website/src/utils/units.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)