From c01ca02d6a6126c80675824838a37fb2d8a7763c Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 18:39:37 +0530 Subject: [PATCH 1/7] add docker file --- .dockerignore | 5 +++++ Dockerfile | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..45e53b8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +.next +.git +Dockerfile +npm-debug.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f42c1e6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# 1. Base image +FROM node:20-alpine + +# 2. Set working directory +WORKDIR /app + +# 3. Copy package files +COPY package*.json ./ + +# 4. Install dependencies +RUN npm install + +# 5. Copy all project files +COPY . . + +# 6. Build Next.js app +RUN npm run build + +# 7. Expose port +EXPOSE 3000 + +# 8. Start app +CMD ["npm", "run", "start"] From c35d03eae99e2fc258bfeda5be124bf35ac8fdab Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 20:28:36 +0530 Subject: [PATCH 2/7] make data apis --- pages/api/artworks.js | 26 ++++++++++++++++++++++++++ pages/api/members.js | 23 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 pages/api/artworks.js create mode 100644 pages/api/members.js diff --git a/pages/api/artworks.js b/pages/api/artworks.js new file mode 100644 index 0000000..dbad535 --- /dev/null +++ b/pages/api/artworks.js @@ -0,0 +1,26 @@ +import { connectDatabase } from '@/database/database'; +import Post from '@/database/schemas/Post'; + +export default async function handler (req, res) { + try { + if (!process.env.MONGO_URL) { + return res.status(200).json([]); + } + await connectDatabase(); + + const limit = parseInt(req.query.limit); + + const artworksRaw = await Post.find( + { type: 'art' }, + { _id: 0, metadata: 0, type: 0, page: 0, hype: 0, __v: 0 } + ) + .sort({ date: -1 }) + .limit(limit) + .lean(); + + res.status(200).json(artworksRaw); + } catch (err) { + console.error(err); + res.status(500).json({ error: 'Failed to fetch artworks' }); + } +} diff --git a/pages/api/members.js b/pages/api/members.js new file mode 100644 index 0000000..6beda0f --- /dev/null +++ b/pages/api/members.js @@ -0,0 +1,23 @@ +import { connectDatabase } from '@/database/database'; +import Member from '@/database/schemas/Member'; + +export default async function handler (req, res) { + try { + if (!process.env.MONGO_URL) { + return res.status(200).json([]); + } + await connectDatabase(); + + + const membersData = await Member.find( + {}, + { _id: 0 } + ) + .lean(); + + res.status(200).json(membersData); + } catch (err) { + console.error(err); + res.status(500).json({ error: 'Failed to fetch members' }); + } +} From 4e2b039e8522ce02175ea74879c88f5602d27886 Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 20:32:18 +0530 Subject: [PATCH 3/7] making it not rely on the db during build and dev --- database/database.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/database/database.js b/database/database.js index 29a422e..86be31f 100644 --- a/database/database.js +++ b/database/database.js @@ -1,5 +1,11 @@ import mongoose from "mongoose"; +const MONGO_URL = process.env.MONGO_URL; + +if (!MONGO_URL && process.env.NODE_ENV === "production") { + throw new Error("MONGO_URL missing in production"); +} + let cached = global.mongoose; if (!cached) { @@ -7,8 +13,9 @@ if (!cached) { } export async function connectDatabase() { - if (!process.env.MONGO_URL) { - throw new Error("Couldn't find MONGO_URL in environment variables"); + if (!MONGO_URL) { + console.log("Skipping mongo connection."); + return null; } // Prevent reconnecting to mongoose on every request @@ -17,7 +24,7 @@ export async function connectDatabase() { } if (!cached.promise) { - cached.promise = mongoose.connect(process.env.MONGO_URL, { + cached.promise = mongoose.connect(MONGO_URL, { // Prevent queries from hanging when mongodb isn't connected bufferCommands: false, }); From c28bd1e77c766acb53c17311eff62993ea119a78 Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 20:32:39 +0530 Subject: [PATCH 4/7] call apis --- pages/art.jsx | 43 +++++++++++++++---------------------------- pages/index.jsx | 20 +++++--------------- pages/members.jsx | 16 ++++++---------- 3 files changed, 26 insertions(+), 53 deletions(-) diff --git a/pages/art.jsx b/pages/art.jsx index 138ae16..4aebed9 100644 --- a/pages/art.jsx +++ b/pages/art.jsx @@ -4,38 +4,25 @@ import SeasonFilter from '@/components/ArtSeasonFilter'; import Carousel from '@/components/Carousel'; import ArtCarouselCard from '@/components/ArtCarosuelCard'; import styles from '@/styles/ArtPage.module.css'; -import { connectDatabase } from '@/database/database'; -import Post from '@/database/schemas/Post'; - -export async function getStaticProps () { - await connectDatabase(); - let artworksRaw = await Post.find( - { type: 'art' }, - { _id: 0, metadata: 0, type: 0, page: 0, hype: 0, __v: 0 } - ).sort({ date: -1 }).lean(); - artworksRaw = artworksRaw.map(item => ({ - ...item, - date: item.date instanceof Date ? item.date.toISOString() : item.date - })); + +export async function getServerSideProps () { + const res = await fetch('http://localhost:3000/api/artworks'); + const artworksRaw = await res.json(); const artworks = artworksRaw.map(item => { - const d = new Date(item.date); - - return { - src: `/assets/art/${item.link}`, - year: String(d.getFullYear()), - author: item.attr?.join(', ') || '', - description: item.name, - season: getSeason(d.getMonth()) - }; - }); + const d = new Date(item.date); - return { - props: { artworks }, + return { + src: `/assets/art/${item.link}`, + year: String(d.getFullYear()), + author: item.attr?.join(', ') || '', + description: item.name, + season: getSeason(d.getMonth()) + }; + }); - revalidate: process.env.NODE_ENV === 'production' - ? 60 * 60 // Once per hour - : 1 // every second for development + return { + props: { artworks } }; } diff --git a/pages/index.jsx b/pages/index.jsx index e9ccf83..deda198 100644 --- a/pages/index.jsx +++ b/pages/index.jsx @@ -4,35 +4,25 @@ import RecentEventsSection from '@/components/home/RecentEventsSection'; import FanartSection from '@/components/home/FanartSection'; import AMVSection from '@/components/home/AMVSection'; import AboutUsSection from '@/components/home/AboutUsSection'; -import { connectDatabase } from '@/database/database'; -import Post from '@/database/schemas/Post'; // TODO: Move this to database import events from '@/data/Events.json'; -export async function getStaticProps () { - await connectDatabase(); - const artworksRaw = await Post.find( - { type: 'art' }, - { _id: 0, metadata: 0, type: 0, page: 0, hype: 0, __v: 0 } - ).sort({ date: -1 }).limit(6).lean(); +export async function getServerSideProps () { + const res = await fetch('http://localhost:3000/api/artworks?limit=6'); + const artworksRaw = await res.json(); const artworks = artworksRaw.map(item => { - const d = item.date instanceof Date ? item.date : new Date(item.date); return { src: `/assets/art/${item.link}` }; }); return { - props: { artworks, events }, - - revalidate: process.env.NODE_ENV === 'production' - ? 60 * 60 - : 1 + props: { artworks } }; } -export default function Home ({ artworks, events }) { +export default function Home ({ artworks }) { return (
diff --git a/pages/members.jsx b/pages/members.jsx index 02ea7b8..80c3867 100644 --- a/pages/members.jsx +++ b/pages/members.jsx @@ -4,19 +4,15 @@ import { FaCaretDown } from 'react-icons/fa'; import { useState } from 'react'; import styles from '@/styles/MembersPage.module.css'; import MemberCard from '@/components/MemberCard'; -import { connectDatabase } from '@/database/database'; -import Member from '@/database/schemas/Member'; -export async function getStaticProps () { - await connectDatabase(); - const membersData = await Member.find({}, { _id: 0 }).lean(); - return { - props: { membersData }, +export async function getServerSideProps () { + const res = await fetch('http://localhost:3000/api/members'); + const membersData = await res.json(); - revalidate: process.env.NODE_ENV === 'production' - ? 60 * 60 // Once per hour - : 1 // every second for development + return { + props: { membersData } }; + } function getMembers (membersData, selectedYear) { From 5db595589b3ec8294fe62e366a6e3ac84480a6ea Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 23:05:23 +0530 Subject: [PATCH 5/7] now it dosent require MONGO_URL to run --- database/database.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/database/database.js b/database/database.js index 86be31f..315c8d9 100644 --- a/database/database.js +++ b/database/database.js @@ -2,9 +2,6 @@ import mongoose from "mongoose"; const MONGO_URL = process.env.MONGO_URL; -if (!MONGO_URL && process.env.NODE_ENV === "production") { - throw new Error("MONGO_URL missing in production"); -} let cached = global.mongoose; From f6c2013997cf4620ffb80471c67c7528d8af5d18 Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 23:06:11 +0530 Subject: [PATCH 6/7] remove localhost from api call and instead use context --- pages/art.jsx | 5 +++-- pages/index.jsx | 5 +++-- pages/members.jsx | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pages/art.jsx b/pages/art.jsx index 4aebed9..8376e63 100644 --- a/pages/art.jsx +++ b/pages/art.jsx @@ -5,8 +5,9 @@ import Carousel from '@/components/Carousel'; import ArtCarouselCard from '@/components/ArtCarosuelCard'; import styles from '@/styles/ArtPage.module.css'; -export async function getServerSideProps () { - const res = await fetch('http://localhost:3000/api/artworks'); +export async function getServerSideProps (context) { + const host = context.req.headers.host; + const res = await fetch(`http://${host}/api/artworks`); const artworksRaw = await res.json(); const artworks = artworksRaw.map(item => { diff --git a/pages/index.jsx b/pages/index.jsx index deda198..7ff94dc 100644 --- a/pages/index.jsx +++ b/pages/index.jsx @@ -7,8 +7,9 @@ import AboutUsSection from '@/components/home/AboutUsSection'; // TODO: Move this to database import events from '@/data/Events.json'; -export async function getServerSideProps () { - const res = await fetch('http://localhost:3000/api/artworks?limit=6'); +export async function getServerSideProps (context) { + const host = context.req.headers.host; + const res = await fetch(`http://${host}/api/artworks?limit=6`); const artworksRaw = await res.json(); const artworks = artworksRaw.map(item => { diff --git a/pages/members.jsx b/pages/members.jsx index 80c3867..3069c77 100644 --- a/pages/members.jsx +++ b/pages/members.jsx @@ -5,8 +5,9 @@ import { useState } from 'react'; import styles from '@/styles/MembersPage.module.css'; import MemberCard from '@/components/MemberCard'; -export async function getServerSideProps () { - const res = await fetch('http://localhost:3000/api/members'); +export async function getServerSideProps (context) { + const host = context.req.headers.host; + const res = await fetch(`http://${host}/api/members`); const membersData = await res.json(); return { From 1a955f761a0e1683752041963725e3dfe3d01f0a Mon Sep 17 00:00:00 2001 From: Jx-ls Date: Sat, 16 May 2026 23:07:14 +0530 Subject: [PATCH 7/7] fixed tests to run without db --- tests/site.test.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/site.test.js b/tests/site.test.js index 9f564c6..8d0b179 100644 --- a/tests/site.test.js +++ b/tests/site.test.js @@ -2,7 +2,6 @@ import { describe, test, expect, beforeAll, afterAll } from "vitest"; import { createServer } from "http"; import next from "next"; import { connectDatabase } from "../database/database.js"; -import Member from "../database/schemas/Member.js"; let appServer; let PORT; @@ -12,6 +11,8 @@ beforeAll(async () => { const handle = app.getRequestHandler(); await app.prepare(); + await connectDatabase(); + appServer = createServer((req, res) => handle(req, res)); await new Promise((resolve) => appServer.listen(0, resolve)); PORT = appServer.address().port; @@ -24,19 +25,10 @@ afterAll(async () => { const pages = ["", "events", "members", "newsletters", "videos", "art"]; describe("Server", () => { - beforeAll(async () => { - await connectDatabase(); - }); - describe("Database", () => { test("should connect without throwing an error", async () => { await expect(connectDatabase()).resolves.not.toThrow(); }); - - test("should find the MASK user", async () => { - const member = await Member.findOne({ name: "Tadi Joshua Raj" }); - expect(member?.name).toBe("Tadi Joshua Raj"); - }); }); pages.forEach(page => {