diff --git a/apps/api-reference/jsx.d.ts b/apps/api-reference/jsx.d.ts
new file mode 100644
index 0000000000..34544d616c
--- /dev/null
+++ b/apps/api-reference/jsx.d.ts
@@ -0,0 +1,9 @@
+import type { JSX as Jsx } from "react/jsx-runtime";
+
+declare global {
+ namespace JSX {
+ type ElementClass = Jsx.ElementClass;
+ type Element = Jsx.Element;
+ type IntrinsicElements = Jsx.IntrinsicElements;
+ }
+}
diff --git a/apps/api-reference/next-env.d.ts b/apps/api-reference/next-env.d.ts
index 40c3d68096..1b3be0840f 100644
--- a/apps/api-reference/next-env.d.ts
+++ b/apps/api-reference/next-env.d.ts
@@ -2,4 +2,4 @@
///
// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/apps/api-reference/src/markdown-components.tsx b/apps/api-reference/src/markdown-components.tsx
index 2bcf89a06a..dd9297c0ba 100644
--- a/apps/api-reference/src/markdown-components.tsx
+++ b/apps/api-reference/src/markdown-components.tsx
@@ -31,9 +31,6 @@ export const MARKDOWN_COMPONENTS = {
);
} else {
- // @ts-expect-error react-markdown doesn't officially support react 19
- // yet; there's no issues here in practice but the types don't currently
- // unify
return
;
}
},
diff --git a/apps/insights/next-env.d.ts b/apps/insights/next-env.d.ts
index 40c3d68096..1b3be0840f 100644
--- a/apps/insights/next-env.d.ts
+++ b/apps/insights/next-env.d.ts
@@ -2,4 +2,4 @@
///
// NOTE: This file should not be edited
-// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/apps/insights/package.json b/apps/insights/package.json
index 0b7be3ac1a..a3c34f9500 100644
--- a/apps/insights/package.json
+++ b/apps/insights/package.json
@@ -35,7 +35,7 @@
"clsx": "catalog:",
"cryptocurrency-icons": "catalog:",
"dnum": "catalog:",
- "framer-motion": "catalog:",
+ "motion": "catalog:",
"next": "catalog:",
"next-themes": "catalog:",
"nuqs": "catalog:",
diff --git a/apps/insights/src/app/price-feeds/[slug]/layout.ts b/apps/insights/src/app/price-feeds/[slug]/layout.ts
new file mode 100644
index 0000000000..3bc3a95f54
--- /dev/null
+++ b/apps/insights/src/app/price-feeds/[slug]/layout.ts
@@ -0,0 +1,13 @@
+import type { Metadata } from "next";
+
+import { client } from "../../../services/pyth";
+export { PriceFeedLayout as default } from "../../../components/PriceFeed/layout";
+
+export const metadata: Metadata = {
+ title: "Price Feeds",
+};
+
+export const generateStaticParams = async () => {
+ const data = await client.getData();
+ return data.symbols.map((symbol) => ({ slug: encodeURIComponent(symbol) }));
+};
diff --git a/apps/insights/src/app/price-feeds/[slug]/page.ts b/apps/insights/src/app/price-feeds/[slug]/page.ts
new file mode 100644
index 0000000000..8f31450e3a
--- /dev/null
+++ b/apps/insights/src/app/price-feeds/[slug]/page.ts
@@ -0,0 +1 @@
+export { Chart as default } from "../../../components/PriceFeed/chart";
diff --git a/apps/insights/src/app/price-feeds/[slug]/price-components/page.tsx b/apps/insights/src/app/price-feeds/[slug]/price-components/page.tsx
new file mode 100644
index 0000000000..cd1074e5ff
--- /dev/null
+++ b/apps/insights/src/app/price-feeds/[slug]/price-components/page.tsx
@@ -0,0 +1 @@
+export { PriceComponents as default } from "../../../../components/PriceFeed/price-components";
diff --git a/apps/insights/src/app/price-feeds/layout.ts b/apps/insights/src/app/price-feeds/layout.ts
new file mode 100644
index 0000000000..146de5525c
--- /dev/null
+++ b/apps/insights/src/app/price-feeds/layout.ts
@@ -0,0 +1 @@
+export { PriceFeedsLayout as default } from "../../components/PriceFeeds/layout";
diff --git a/apps/insights/src/app/price-feeds/page.ts b/apps/insights/src/app/price-feeds/page.ts
index ef49f0ada8..343ef24c4b 100644
--- a/apps/insights/src/app/price-feeds/page.ts
+++ b/apps/insights/src/app/price-feeds/page.ts
@@ -1 +1,7 @@
+import type { Metadata } from "next";
+
export { PriceFeeds as default } from "../../components/PriceFeeds";
+
+export const metadata: Metadata = {
+ title: "Price Feeds",
+};
diff --git a/apps/insights/src/app/publishers/page.ts b/apps/insights/src/app/publishers/page.ts
index d9e5e904c1..0df43b651f 100644
--- a/apps/insights/src/app/publishers/page.ts
+++ b/apps/insights/src/app/publishers/page.ts
@@ -1 +1,7 @@
+import type { Metadata } from "next";
+
export { Publishers as default } from "../../components/Publishers";
+
+export const metadata: Metadata = {
+ title: "Publishers",
+};
diff --git a/apps/insights/src/components/AsyncValue/index.tsx b/apps/insights/src/components/AsyncValue/index.tsx
deleted file mode 100644
index 949cb3acb1..0000000000
--- a/apps/insights/src/components/AsyncValue/index.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-"use client";
-
-import { Skeleton } from "@pythnetwork/component-library/Skeleton";
-import { Suspense, use } from "react";
-
-type Props = {
- placeholderWidth: number;
- valuePromise: Promise;
-};
-
-export const AsyncValue = ({
- placeholderWidth,
- valuePromise,
-}: Props) => (
- }>
-
-
-);
-
-const ResolvedValue = ({ valuePromise }: Pick, "valuePromise">) =>
- use(valuePromise);
diff --git a/apps/insights/src/components/PriceFeeds/change-percent.module.scss b/apps/insights/src/components/ChangePercent/index.module.scss
similarity index 93%
rename from apps/insights/src/components/PriceFeeds/change-percent.module.scss
rename to apps/insights/src/components/ChangePercent/index.module.scss
index 94f5a2e8c5..2005df4aa0 100644
--- a/apps/insights/src/components/PriceFeeds/change-percent.module.scss
+++ b/apps/insights/src/components/ChangePercent/index.module.scss
@@ -1,7 +1,6 @@
@use "@pythnetwork/component-library/theme";
.changePercent {
- font-size: theme.font-size("sm");
transition: color 100ms linear;
display: flex;
flex-flow: row nowrap;
diff --git a/apps/insights/src/components/PriceFeeds/change-percent.tsx b/apps/insights/src/components/ChangePercent/index.tsx
similarity index 69%
rename from apps/insights/src/components/PriceFeeds/change-percent.tsx
rename to apps/insights/src/components/ChangePercent/index.tsx
index c2a53d918b..79635d088f 100644
--- a/apps/insights/src/components/PriceFeeds/change-percent.tsx
+++ b/apps/insights/src/components/ChangePercent/index.tsx
@@ -2,11 +2,12 @@
import { CaretUp } from "@phosphor-icons/react/dist/ssr/CaretUp";
import { Skeleton } from "@pythnetwork/component-library/Skeleton";
+import clsx from "clsx";
import { type ComponentProps, createContext, use } from "react";
import { useNumberFormatter } from "react-aria";
import { z } from "zod";
-import styles from "./change-percent.module.scss";
+import styles from "./index.module.scss";
import { StateType, useData } from "../../use-data";
import { useLivePrice } from "../LivePrices";
@@ -18,20 +19,17 @@ const REFRESH_YESTERDAYS_PRICES_INTERVAL = ONE_HOUR_IN_MS;
const CHANGE_PERCENT_SKELETON_WIDTH = 15;
type Props = Omit, "value"> & {
- symbolsToFeedKeys: Record;
+ feeds: (Feed & { symbol: string })[];
};
const YesterdaysPricesContext = createContext<
undefined | ReturnType>>
>(undefined);
-export const YesterdaysPricesProvider = ({
- symbolsToFeedKeys,
- ...props
-}: Props) => {
+export const YesterdaysPricesProvider = ({ feeds, ...props }: Props) => {
const state = useData(
- ["yesterdaysPrices", Object.values(symbolsToFeedKeys)],
- () => getYesterdaysPrices(symbolsToFeedKeys),
+ ["yesterdaysPrices", feeds.map((feed) => feed.symbol)],
+ () => getYesterdaysPrices(feeds),
{
refreshInterval: REFRESH_YESTERDAYS_PRICES_INTERVAL,
},
@@ -41,17 +39,21 @@ export const YesterdaysPricesProvider = ({
};
const getYesterdaysPrices = async (
- symbolsToFeedKeys: Record,
+ feeds: (Feed & { symbol: string })[],
): Promise