From 5c0a5128ac790c956e9f5d6724dd4231c7e1e385 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Thu, 11 Jul 2024 11:06:58 +0800 Subject: [PATCH 01/14] fix the image of provider, read more button --- ui/components/ContextItem.tsx | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/ui/components/ContextItem.tsx b/ui/components/ContextItem.tsx index 87dfed4..03f25b1 100644 --- a/ui/components/ContextItem.tsx +++ b/ui/components/ContextItem.tsx @@ -7,7 +7,14 @@ interface ContextItemProperties { name: string; url: string; description: string; - provider: { name: string; image?: { thumbnail: { contentUrl: string } } }[]; + provider: { + name: string; + image?: { + thumbnail: { + contentUrl: string; + }; + }; + }[]; datePublished: string; image?: { contentUrl: string; @@ -32,11 +39,30 @@ const ContextItem: React.FC = ({ item }) => {
- + Read more -
- {item.provider[0].name} | {new Date(item.datePublished).toLocaleDateString()} +
+
+ {item.provider[0].image && ( + {`${item.provider[0].name} + )} + {item.provider[0].name} +
+
+ {new Date(item.datePublished).toLocaleDateString()} +
); From 14294f8a14b974b6485ae299d89331ac24eba11e Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Thu, 11 Jul 2024 12:14:33 +0800 Subject: [PATCH 02/14] news list now can load local json file --- ui/app/api/news/route.ts | 16 ++++++++++++++++ ui/components/NewsPage.tsx | 4 +--- .../1fa9b398-080f-54de-9a4f-3ba386acce11.json | 0 .../73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json | 0 .../869d933c-e186-51b0-a225-edc2d338b6fa.json | 0 .../b84c7962-2971-53de-a99b-3c9e45492c79.json | 0 .../ed701716-e443-5804-aaa9-99e7e04c33e2.json | 0 .../fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json | 0 {public => ui/public}/data/index.json | 0 9 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 ui/app/api/news/route.ts rename {public => ui/public}/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json (100%) rename {public => ui/public}/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json (100%) rename {public => ui/public}/data/869d933c-e186-51b0-a225-edc2d338b6fa.json (100%) rename {public => ui/public}/data/b84c7962-2971-53de-a99b-3c9e45492c79.json (100%) rename {public => ui/public}/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json (100%) rename {public => ui/public}/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json (100%) rename {public => ui/public}/data/index.json (100%) diff --git a/ui/app/api/news/route.ts b/ui/app/api/news/route.ts new file mode 100644 index 0000000..40cedbc --- /dev/null +++ b/ui/app/api/news/route.ts @@ -0,0 +1,16 @@ +import { NextResponse } from "next/server"; +import fs from "node:fs/promises"; +import path from "node:path"; + +export async function GET() { + try { + const dataDirectory = path.join(process.cwd(), "public", "data"); + const filePath = path.join(dataDirectory, "index.json"); + const fileContents = await fs.readFile(filePath, "utf8"); + const data = JSON.parse(fileContents); + return NextResponse.json(data); + } catch (error) { + console.error("Error reading news data:", error); + return NextResponse.json({ error: "Failed to load news data" }, { status: 500 }); + } +} diff --git a/ui/components/NewsPage.tsx b/ui/components/NewsPage.tsx index 62072c2..b39551b 100644 --- a/ui/components/NewsPage.tsx +++ b/ui/components/NewsPage.tsx @@ -19,9 +19,7 @@ const NewsPage = () => { const fetchNews = async () => { try { console.log("Fetching news..."); - const response = await fetch( - "https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/index.json", - ); + const response = await fetch("/api/news"); console.log("Response status:", response.status); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); diff --git a/public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json b/ui/public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json similarity index 100% rename from public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json rename to ui/public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json diff --git a/public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json b/ui/public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json similarity index 100% rename from public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json rename to ui/public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json diff --git a/public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json b/ui/public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json similarity index 100% rename from public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json rename to ui/public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json diff --git a/public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json b/ui/public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json similarity index 100% rename from public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json rename to ui/public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json diff --git a/public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json b/ui/public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json similarity index 100% rename from public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json rename to ui/public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json diff --git a/public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json b/ui/public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json similarity index 100% rename from public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json rename to ui/public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json diff --git a/public/data/index.json b/ui/public/data/index.json similarity index 100% rename from public/data/index.json rename to ui/public/data/index.json From deb82d38b882062a7c7f575d4b869d219fc10f34 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Thu, 11 Jul 2024 12:33:19 +0800 Subject: [PATCH 03/14] now can load local detail news --- ui/app/api/news/[id]/router.ts | 12 ++++++++++++ ui/app/news/[id]/page.tsx | 2 +- ui/lib/fetchNewsData.ts | 15 ++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 ui/app/api/news/[id]/router.ts diff --git a/ui/app/api/news/[id]/router.ts b/ui/app/api/news/[id]/router.ts new file mode 100644 index 0000000..02d52a2 --- /dev/null +++ b/ui/app/api/news/[id]/router.ts @@ -0,0 +1,12 @@ +import { NextResponse } from "next/server"; +import { fetchNewsData } from "../../../../lib/fetchNewsData"; + +export async function GET(request: Request, { params }: { params: { id: string } }) { + const newsData = await fetchNewsData(params.id); + + if (!newsData) { + return NextResponse.json({ error: "News not found" }, { status: 404 }); + } + + return NextResponse.json(newsData); +} diff --git a/ui/app/news/[id]/page.tsx b/ui/app/news/[id]/page.tsx index b9b0a3c..a98b18f 100644 --- a/ui/app/news/[id]/page.tsx +++ b/ui/app/news/[id]/page.tsx @@ -5,7 +5,7 @@ export default async function NewsPage({ params }: { params: { id: string } }) { const newsData = await fetchNewsData(params.id); if (!newsData) { - return
News not found
; + return
News not found or failed to load
; } return ; diff --git a/ui/lib/fetchNewsData.ts b/ui/lib/fetchNewsData.ts index b5568f8..9fd902a 100644 --- a/ui/lib/fetchNewsData.ts +++ b/ui/lib/fetchNewsData.ts @@ -1,9 +1,14 @@ +import fs from "node:fs/promises"; +import path from "node:path"; + export async function fetchNewsData(id: string) { - const response = await fetch( - `https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/${id}.json`, - ); - if (!response.ok) { + try { + const dataDirectory = path.join(process.cwd(), "public", "data"); + const filePath = path.join(dataDirectory, `${id}.json`); + const fileContents = await fs.readFile(filePath, "utf8"); + return JSON.parse(fileContents); + } catch (error) { + console.error("Error reading news data:", error); return null; } - return response.json(); } From e8e90d84cc811730b104ca1cafe2a2100bdb2cfe Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 11:05:55 +0800 Subject: [PATCH 04/14] change the wrong file name --- ui/app/api/news/[id]/{router.ts => route.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ui/app/api/news/[id]/{router.ts => route.ts} (100%) diff --git a/ui/app/api/news/[id]/router.ts b/ui/app/api/news/[id]/route.ts similarity index 100% rename from ui/app/api/news/[id]/router.ts rename to ui/app/api/news/[id]/route.ts From 07a66489d1b3d5c01fb2bed87d1dac179a596b5b Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 12:48:33 +0800 Subject: [PATCH 05/14] combine the lib/fetnewsdata.tsx to app/api/news/[id]/page.tsx --- ui/app/api/news/[id]/route.ts | 15 ++++++++++----- ui/app/news/[id]/page.tsx | 11 +++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ui/app/api/news/[id]/route.ts b/ui/app/api/news/[id]/route.ts index 02d52a2..3843011 100644 --- a/ui/app/api/news/[id]/route.ts +++ b/ui/app/api/news/[id]/route.ts @@ -1,12 +1,17 @@ import { NextResponse } from "next/server"; -import { fetchNewsData } from "../../../../lib/fetchNewsData"; +import fs from "node:fs/promises"; +import path from "node:path"; export async function GET(request: Request, { params }: { params: { id: string } }) { - const newsData = await fetchNewsData(params.id); + try { + const dataDirectory = path.join(process.cwd(), "public", "data"); + const filePath = path.join(dataDirectory, `${params.id}.json`); + const fileContents = await fs.readFile(filePath, "utf8"); + const newsData = JSON.parse(fileContents); - if (!newsData) { + return NextResponse.json(newsData); + } catch (error) { + console.error("Error reading news data:", error); return NextResponse.json({ error: "News not found" }, { status: 404 }); } - - return NextResponse.json(newsData); } diff --git a/ui/app/news/[id]/page.tsx b/ui/app/news/[id]/page.tsx index a98b18f..0c47af4 100644 --- a/ui/app/news/[id]/page.tsx +++ b/ui/app/news/[id]/page.tsx @@ -1,8 +1,15 @@ -import { fetchNewsData } from "../../../lib/fetchNewsData"; import NewsDetail from "../../../components/NewsDetail"; +async function getNewsData(id: string) { + const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/news/${id}`, { next: { revalidate: 60 } }); + if (!res.ok) { + throw new Error("Failed to fetch news"); + } + return res.json(); +} + export default async function NewsPage({ params }: { params: { id: string } }) { - const newsData = await fetchNewsData(params.id); + const newsData = await getNewsData(params.id); if (!newsData) { return
News not found or failed to load
; From 8e918dd24439ec67f2b453c1c80545d7e47048bc Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 12:49:56 +0800 Subject: [PATCH 06/14] delete the unused file --- ui/lib/fetchNewsData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/lib/fetchNewsData.ts b/ui/lib/fetchNewsData.ts index 9fd902a..11b08be 100644 --- a/ui/lib/fetchNewsData.ts +++ b/ui/lib/fetchNewsData.ts @@ -1,4 +1,4 @@ -import fs from "node:fs/promises"; +mport fs from "node:fs/promises"; import path from "node:path"; export async function fetchNewsData(id: string) { From 7c5ab7c65fad92cac2531489f8ad65f21b320fac Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 12:57:37 +0800 Subject: [PATCH 07/14] delete the unused file --- ui/lib/fetchNewsData.ts | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 ui/lib/fetchNewsData.ts diff --git a/ui/lib/fetchNewsData.ts b/ui/lib/fetchNewsData.ts deleted file mode 100644 index 11b08be..0000000 --- a/ui/lib/fetchNewsData.ts +++ /dev/null @@ -1,14 +0,0 @@ -mport fs from "node:fs/promises"; -import path from "node:path"; - -export async function fetchNewsData(id: string) { - try { - const dataDirectory = path.join(process.cwd(), "public", "data"); - const filePath = path.join(dataDirectory, `${id}.json`); - const fileContents = await fs.readFile(filePath, "utf8"); - return JSON.parse(fileContents); - } catch (error) { - console.error("Error reading news data:", error); - return null; - } -} From 4007efcc577e1ae15aae7c5d9d68d09791dce5d4 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 14:14:59 +0800 Subject: [PATCH 08/14] add a constant file to read the env variables --- ui/app/api/news/[id]/route.ts | 1 + ui/app/news/[id]/layout.tsx | 30 ++++++++++++++---------------- ui/app/news/[id]/page.tsx | 3 ++- ui/lib/constants.ts | 20 ++++++++++++++++++++ 4 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 ui/lib/constants.ts diff --git a/ui/app/api/news/[id]/route.ts b/ui/app/api/news/[id]/route.ts index 3843011..5b4f5ba 100644 --- a/ui/app/api/news/[id]/route.ts +++ b/ui/app/api/news/[id]/route.ts @@ -1,6 +1,7 @@ import { NextResponse } from "next/server"; import fs from "node:fs/promises"; import path from "node:path"; +import { VALIDATED_ENV } from "../../../../lib/constants"; export async function GET(request: Request, { params }: { params: { id: string } }) { try { diff --git a/ui/app/news/[id]/layout.tsx b/ui/app/news/[id]/layout.tsx index 4131370..5eecd46 100644 --- a/ui/app/news/[id]/layout.tsx +++ b/ui/app/news/[id]/layout.tsx @@ -1,17 +1,15 @@ -import Link from "next/link"; -import { ArrowLeft } from "lucide-react"; +import { Metadata } from "next"; +import React from "react"; +import { ENV, assertEnvVariables } from "../../../lib/constants"; -export default function NewsDetailLayout({ children }: { children: React.ReactNode }) { - return ( -
- - - Back - - {children} -
- ); -} +export const metadata: Metadata = { + title: "News - Perplexica", +}; + +assertEnvVariables(ENV); + +const Layout = ({ children }: { children: React.ReactNode }) => { + return
{children}
; +}; + +export default Layout; diff --git a/ui/app/news/[id]/page.tsx b/ui/app/news/[id]/page.tsx index 0c47af4..a2fbfcc 100644 --- a/ui/app/news/[id]/page.tsx +++ b/ui/app/news/[id]/page.tsx @@ -1,7 +1,8 @@ import NewsDetail from "../../../components/NewsDetail"; +import { VALIDATED_ENV } from "../../../lib/constants"; async function getNewsData(id: string) { - const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/news/${id}`, { next: { revalidate: 60 } }); + const res = await fetch(`${VALIDATED_ENV.API_URL}/news/${id}`, { next: { revalidate: 60 } }); if (!res.ok) { throw new Error("Failed to fetch news"); } diff --git a/ui/lib/constants.ts b/ui/lib/constants.ts new file mode 100644 index 0000000..9bd682e --- /dev/null +++ b/ui/lib/constants.ts @@ -0,0 +1,20 @@ +export const ENV = { + WS_URL: process.env.NEXT_PUBLIC_WS_URL, + API_URL: process.env.NEXT_PUBLIC_API_URL, +} as const; + +export type ENV = typeof ENV; + +// Type guard function +export function assertEnvVariables(ENV: ENV): asserts ENV is Required { + const missingVariables = Object.entries(ENV).filter(([_, value]) => value === undefined); + if (missingVariables.length > 0) { + throw new Error(`Missing environment variables: ${missingVariables.map(([key]) => key).join(", ")}`); + } +} + +// Call this function early in your app's initialization +assertEnvVariables(ENV); + +// After assertion, we can safely use ENV +export const VALIDATED_ENV: Required = ENV as Required; From 3b2a91cf3b9f82cea78fe8fe00670778d7ef5a28 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 14:16:38 +0800 Subject: [PATCH 09/14] fixed the bugs --- ui/lib/constants.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui/lib/constants.ts b/ui/lib/constants.ts index 9bd682e..00e3940 100644 --- a/ui/lib/constants.ts +++ b/ui/lib/constants.ts @@ -13,8 +13,6 @@ export function assertEnvVariables(ENV: ENV): asserts ENV is Required { } } -// Call this function early in your app's initialization assertEnvVariables(ENV); -// After assertion, we can safely use ENV export const VALIDATED_ENV: Required = ENV as Required; From 047df7e3d244c946dcc8cde494a2c81bbd193721 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 14:19:37 +0800 Subject: [PATCH 10/14] fix the constants --- ui/app/api/news/[id]/route.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/app/api/news/[id]/route.ts b/ui/app/api/news/[id]/route.ts index 5b4f5ba..366d3e5 100644 --- a/ui/app/api/news/[id]/route.ts +++ b/ui/app/api/news/[id]/route.ts @@ -5,14 +5,20 @@ import { VALIDATED_ENV } from "../../../../lib/constants"; export async function GET(request: Request, { params }: { params: { id: string } }) { try { + console.log(`Fetching news data for id: ${params.id}`); + console.log(`API URL: ${VALIDATED_ENV.API_URL}`); // Log the API URL + const dataDirectory = path.join(process.cwd(), "public", "data"); const filePath = path.join(dataDirectory, `${params.id}.json`); const fileContents = await fs.readFile(filePath, "utf8"); const newsData = JSON.parse(fileContents); + // You could use VALIDATED_ENV.API_URL here if you needed to make any external API calls + return NextResponse.json(newsData); } catch (error) { console.error("Error reading news data:", error); + console.log(`WS URL: ${VALIDATED_ENV.WS_URL}`); // Log the WebSocket URL, just as an example return NextResponse.json({ error: "News not found" }, { status: 404 }); } } From c50197d3a2911d8847e4d2f80e6e4b9d4ec2a32a Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 14:25:15 +0800 Subject: [PATCH 11/14] fix the bugs --- ui/lib/constants.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/lib/constants.ts b/ui/lib/constants.ts index 00e3940..78ba926 100644 --- a/ui/lib/constants.ts +++ b/ui/lib/constants.ts @@ -1,6 +1,6 @@ export const ENV = { - WS_URL: process.env.NEXT_PUBLIC_WS_URL, - API_URL: process.env.NEXT_PUBLIC_API_URL, + WS_URL: process.env.NEXT_PUBLIC_WS_URL || "ws://localhost:3001", + API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/api", } as const; export type ENV = typeof ENV; @@ -9,10 +9,11 @@ export type ENV = typeof ENV; export function assertEnvVariables(ENV: ENV): asserts ENV is Required { const missingVariables = Object.entries(ENV).filter(([_, value]) => value === undefined); if (missingVariables.length > 0) { - throw new Error(`Missing environment variables: ${missingVariables.map(([key]) => key).join(", ")}`); + console.warn(`Warning: Missing environment variables: ${missingVariables.map(([key]) => key).join(", ")}`); + console.warn("Using default values for missing variables."); } } assertEnvVariables(ENV); -export const VALIDATED_ENV: Required = ENV as Required; +export const VALIDATED_ENV: Required = ENV as Required; \ No newline at end of file From ffb744c9acbb6452815c6d6869c5487694e48261 Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 14:25:49 +0800 Subject: [PATCH 12/14] fix the port --- ui/.env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/.env.example b/ui/.env.example index 57a3ed9..4032dc3 100644 --- a/ui/.env.example +++ b/ui/.env.example @@ -1,2 +1,2 @@ -NEXT_PUBLIC_WS_URL=ws://localhost:3001 -NEXT_PUBLIC_API_URL=http://localhost:3001/api \ No newline at end of file +NEXT_PUBLIC_WS_URL=ws://localhost:3000 +NEXT_PUBLIC_API_URL=http://localhost:3000/api \ No newline at end of file From 1ac51ee7a4609d54ec2c451fc8ca2fcb9f8e9a7d Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 15:12:14 +0800 Subject: [PATCH 13/14] fix the bugs --- ui/lib/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/lib/constants.ts b/ui/lib/constants.ts index 78ba926..692b990 100644 --- a/ui/lib/constants.ts +++ b/ui/lib/constants.ts @@ -16,4 +16,4 @@ export function assertEnvVariables(ENV: ENV): asserts ENV is Required { assertEnvVariables(ENV); -export const VALIDATED_ENV: Required = ENV as Required; \ No newline at end of file +export const VALIDATED_ENV: Required = ENV as Required; From 52fd0b2e805aca4bbb7caadf5b3f9b2c91e434be Mon Sep 17 00:00:00 2001 From: Yifei Hu Date: Fri, 12 Jul 2024 15:21:29 +0800 Subject: [PATCH 14/14] fix the constants of ENV --- ui/app/api/news/[id]/route.ts | 2 -- ui/lib/constants.ts | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ui/app/api/news/[id]/route.ts b/ui/app/api/news/[id]/route.ts index 366d3e5..e6295e2 100644 --- a/ui/app/api/news/[id]/route.ts +++ b/ui/app/api/news/[id]/route.ts @@ -13,8 +13,6 @@ export async function GET(request: Request, { params }: { params: { id: string } const fileContents = await fs.readFile(filePath, "utf8"); const newsData = JSON.parse(fileContents); - // You could use VALIDATED_ENV.API_URL here if you needed to make any external API calls - return NextResponse.json(newsData); } catch (error) { console.error("Error reading news data:", error); diff --git a/ui/lib/constants.ts b/ui/lib/constants.ts index 692b990..d038f2a 100644 --- a/ui/lib/constants.ts +++ b/ui/lib/constants.ts @@ -1,6 +1,6 @@ export const ENV = { - WS_URL: process.env.NEXT_PUBLIC_WS_URL || "ws://localhost:3001", - API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001/api", + WS_URL: process.env.NEXT_PUBLIC_WS_URL || "ws://localhost:3000", + API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:3000/api", } as const; export type ENV = typeof ENV;