Skip to content

Conversation

@archduke1337
Copy link

@archduke1337 archduke1337 commented Aug 17, 2025

This PR adds a complete README.md file for the project.

The README includes:

  • Project introduction and live demo link
  • Features overview
  • Tech stack details
  • Setup and installation guide
  • Environment variables info
  • Deployment instructions (Vercel)
  • Contributing guidelines
  • License and acknowledgments

This will help new developers and users quickly understand, set up, and contribute to the project.

Summary by CodeRabbit

  • New Features

    • Live, locale-aware clock/date on home page.
    • One-click “Copy Invitation” with meeting details and success/error toasts.
    • Unified call/recording list with play/start actions and improved error handling.
    • Environment-aware meeting links across the app.
  • Style

    • Rebranded UI and metadata from “YOOM” to “Ro0m,” including logo and alt text.
  • Documentation

    • Rewrote README with streamlined setup, live demo link, and deployment guidance.
  • Chores

    • Added/organized environment variables and .gitignore entries.
    • Introduced .nvmrc (Node 18).
    • Renamed package to “ro0m” and updated Next.js to ^14.2.31.

@coderabbitai
Copy link

coderabbitai bot commented Aug 17, 2025

Walkthrough

Updates branding from YOOM to Ro0m, adds environment variables and ignores, pins Node via .nvmrc, revises README, bumps Next.js, introduces a meeting link utility, refactors meeting link generation and invitation copy, enhances home time display to tick every second, and restructures CallList with unified rendering and error-handled recording fetches.

Changes

Cohort / File(s) Summary
Environment & Config
/.env, /.gitignore, /.nvmrc, /package.json
Added Clerk/Stream/base URL env vars; refined env ignores; added Node 18 via .nvmrc; renamed package to "ro0m" and updated Next to ^14.2.31.
Docs
/README.md
Rewrote README with new project name, streamlined setup, env guidance, and deployment notes.
Branding Updates
/app/layout.tsx, /app/(root)/(home)/layout.tsx, /components/MobileNav.tsx, /components/Navbar.tsx
Changed app title, logo path/alt text, and displayed brand from YOOM to Ro0m.
Home Page Clock
/app/(root)/(home)/page.tsx
Made time/date stateful with useEffect interval and locale-aware formatting.
Personal Room Invitation
/app/(root)/(home)/personal-room/page.tsx
Added environment-aware meeting link, invitation text builder, clipboard copy with success/error toasts, and icon.
Meeting Link Utility
/lib/meeting-utils.ts, /components/MeetingTypeList.tsx
Introduced and consumed getMeetingLink to compute URLs based on env/server/browser context.
Call List Refactor
/components/CallList.tsx
Unified rendering for ended/upcoming/recordings, added robust recording fetch with toasts, simplified mapping, and centralized meeting navigation.

Sequence Diagram(s)

sequenceDiagram
  participant C as Component (PersonalRoom/MeetingTypeList)
  participant U as getMeetingLink(id)
  participant E as process.env.NEXT_PUBLIC_BASE_URL
  participant W as window.location.origin

  C->>U: getMeetingLink(id)
  alt Server-side (no window)
    U-->>C: /meeting/{id}
  else Client + BASE_URL set and not localhost
    U->>E: read BASE_URL
    U-->>C: {BASE_URL}/meeting/{id}
  else Client fallback
    U->>W: read origin
    U-->>C: {origin}/meeting/{id}
  end
Loading
sequenceDiagram
  participant V as CallList
  participant S as Stream API
  participant T as Toast
  participant R as Router/Window

  V->>V: useEffect(type)
  alt type == "recordings"
    V->>S: list recordings
    alt success
      loop per recording
        V->>S: fetch recording data
        alt item fail
          V->>T: destructive toast (error)
        end
      end
      V-->>V: set recordings
    else failure
      V->>T: destructive toast
      V-->>V: clear recordings
    end
  else ended/upcoming
    V-->>V: use provided calls
  end
  V->>R: onClick item -> open recording URL or navigate to meeting
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I twitch my ears at Ro0m’s new light,
Env keys planted, links set right.
Tick-tock clocks and toasts that sing,
Meetings hop with a safer string.
Brand-new burrow, same swift zoom—
Come nibble bytes inside our Ro0m. 🥕✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (1)
app/(root)/(home)/personal-room/page.tsx (1)

54-57: Guard against undefined user/meetingId to avoid non-null assertion crashes and poor UI states

meetingId! and string interpolation with user?.username can render “undefined” or throw if the hook expects a non-empty id. Guard and provide fallbacks in the UI.

Apply this diff:

-  const meetingId = user?.id;
+  const meetingId = user?.id ?? '';

@@
-        <Table title="Topic" description={`${user?.username}'s Meeting Room`} />
-        <Table title="Meeting ID" description={meetingId!} />
-        <Table title="Invite Link" description={meetingLink} />
+        <Table title="Topic" description={`${user?.username ?? 'Personal'}'s Meeting Room`} />
+        <Table title="Meeting ID" description={meetingId || '—'} />
+        <Table title="Invite Link" description={meetingLink || '—'} />

If useGetCallById cannot accept an empty string, update that hook to short-circuit when the id is falsy, or change the call site to defer usage until meetingId is present. If helpful, I can provide a patch to make the hook tolerant of undefined ids.

Also applies to: 92-95

🧹 Nitpick comments (16)
.nvmrc (1)

1-1: Optional: also enforce Node version via package.json engines

.nvmrc helps local devs using nvm, but CI/Vercel/other environments won’t read it. Consider adding an engines field to package.json to enforce Node 18.x (Next 14 typically requires ≥18.17):

Add this to package.json:

{
  "engines": {
    "node": ">=18.17 <19"
  }
}

If your team uses asdf, adding a .tool-versions or .node-version file can further reduce drift across environments.

components/MobileNav.tsx (1)

32-32: Nit: capitalize the brand in alt text for consistency

Use "Ro0m logo" to match the visible brand capitalization.

-              alt="ro0m logo"
+              alt="Ro0m logo"
components/Navbar.tsx (1)

15-15: Nit: capitalize the brand in alt text for consistency

Align alt text with the visible brand capitalization.

-          alt="ro0m logo"
+          alt="Ro0m logo"
app/layout.tsx (1)

14-15: Brand rename applied — LGTM; minor copy tweak optional

The title update to Ro0m looks good. Optional: “Video calling App” reads better as “Video calling app.”

-  description: "Video calling App",
+  description: "Video calling app",
.gitignore (1)

12-18: Solid env ignores; add a generic pattern and keep an example tracked

Nice addition. Consider also ignoring any other future stage-specific env files while keeping a sample checked in.

Apply this diff to generalize and preserve an example:

 # environment variables
 .env
 .env.local
 .env.development.local
 .env.test.local
 .env.production.local
+.env.*
+!.env.example

Note: Since a real .env is currently committed in this PR, the ignore rule won’t untrack it. See my comment on .env for steps to remove and rotate secrets.

package.json (1)

2-2: Next.js bump looks intentional; align eslint tooling and engines, and confirm scope

  • Align eslint-config-next to the same 14.2 line to avoid rule/plugin mismatches.
  • Add an engines field to enforce the Node version your .nvmrc pins (Node 18).
  • Given the PR title mentions only README, please confirm these framework/branding bumps are intended here; otherwise consider splitting for cleaner history.

Suggested updates outside the shown lines:

{
  "engines": {
    "node": ">=18.17.0"
  },
  "devDependencies": {
    "eslint-config-next": "^14.2.31"
  }
}

Also applies to: 24-24

lib/meeting-utils.ts (1)

1-12: Harden link building: guard empty id, normalize base URL, and encode the id
Prevents double slashes and handles unexpected characters in IDs. Low-risk polish.

Apply this diff:

 export const getMeetingLink = (id: string) => {
+  if (!id) return '';
   if (typeof window === 'undefined') {
-    return `/meeting/${id}`;
+    return `/meeting/${encodeURIComponent(id)}`;
   }
 
-  const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
+  const baseUrl = process.env.NEXT_PUBLIC_BASE_URL?.replace(/\/+$/, '');
   if (baseUrl && !baseUrl.includes('localhost')) {
-    return `${baseUrl}/meeting/${id}`;
+    return `${baseUrl}/meeting/${encodeURIComponent(id)}`;
   }
 
-  return `${window.location.origin}/meeting/${id}`;
+  return `${window.location.origin.replace(/\/+$/, '')}/meeting/${encodeURIComponent(id)}`;
 };
components/MeetingTypeList.tsx (1)

70-85: Deduplicate: reuse shared getMeetingLink(...) instead of redefining it locally
This logic now lives in lib/meeting-utils.ts. Importing it avoids divergence and keeps URL rules centralized.

Apply this diff:

-  const getMeetingLink = () => {
-    if (!callDetail?.id) return '';
-    
-    const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
-    // In production, use the configured URL
-    if (baseUrl && !baseUrl.includes('localhost')) {
-      return `${baseUrl}/meeting/${callDetail.id}`;
-    }
-    // In development or if BASE_URL is not set, use the current origin
-    return typeof window !== 'undefined' 
-      ? `${window.location.origin}/meeting/${callDetail.id}`
-      : `/meeting/${callDetail.id}`;
-  };
-  
-  const meetingLink = getMeetingLink();
+  const meetingLink = callDetail?.id ? getMeetingLink(callDetail.id) : '';

Add this import near the top of the file:

import { getMeetingLink } from '../lib/meeting-utils';
app/(root)/(home)/page.tsx (1)

7-14: Prevent potential hydration mismatch from server-rendered Date

Initializing now with new Date() can cause hydration warnings because Client Components still render on the server during SSR. The client time will differ from the server-rendered time. Initialize to null and set it on mount, and optionally suppress hydration warnings on the time/date elements.

Apply this diff:

-  const [now, setNow] = useState<Date>(() => new Date());
+  const [now, setNow] = useState<Date | null>(null);

   useEffect(() => {
-    // update every second to keep minutes accurate and avoid drift
-    const tick = () => setNow(new Date());
-    const id = setInterval(tick, 1000);
-    return () => clearInterval(id);
+    // set once on mount, then update every second
+    setNow(new Date());
+    const id = setInterval(() => setNow(new Date()), 1000);
+    return () => clearInterval(id);
   }, []);

-  const time = now.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
-  const date = new Intl.DateTimeFormat(undefined, { dateStyle: 'full' }).format(now);
+  const time = now
+    ? now.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
+    : '';
+  const date = now
+    ? new Intl.DateTimeFormat(undefined, { dateStyle: 'full' }).format(now)
+    : '';

Outside the selected range, add the following attributes to suppress hydration warnings until now is set:

<h1 className="text-4xl font-extrabold lg:text-7xl" suppressHydrationWarning>
  {time || '—'}
</h1>
<p className="text-lg font-medium text-sky-1 lg:text-2xl" suppressHydrationWarning>
  {date || '—'}
</p>

Also applies to: 16-17, 27-28

app/(root)/(home)/personal-room/page.tsx (3)

74-87: Deduplicate meeting link logic by importing the shared utility

You’re re-implementing meeting link generation locally. Import and reuse the shared getMeetingLink from lib/meeting-utils to keep behavior consistent across the app and avoid drift.

Apply this diff:

@@
-import Image from "next/image";
+import Image from "next/image";
+import { getMeetingLink as buildMeetingLink } from "@/lib/meeting-utils";
@@
-  const getMeetingLink = () => {
-    const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
-    // In production, use the configured URL
-    if (baseUrl && !baseUrl.includes('localhost')) {
-      return `${baseUrl}/meeting/${meetingId}?personal=true`;
-    }
-    // In development or if BASE_URL is not set, use the current origin
-    return typeof window !== 'undefined' 
-      ? `${window.location.origin}/meeting/${meetingId}?personal=true`
-      : `/meeting/${meetingId}?personal=true`;
-  };
-  
-  const meetingLink = getMeetingLink();
+  const meetingLink = meetingId ? `${buildMeetingLink(meetingId)}?personal=true` : "";

58-72: Harden startRoom with missing-id guard and error handling

Network calls can fail; also, meetingId may be empty on first render. Add a guard and surface errors via toast.

Apply this diff:

   const startRoom = async () => {
-    if (!client || !user) return;
+    if (!client || !user) return;
+    if (!meetingId) {
+      toast({ title: "Error", description: "Meeting ID is not ready yet. Please try again.", variant: "destructive" });
+      return;
+    }
 
     const newCall = client.call("default", meetingId!);
 
-    if (!call) {
-      await newCall.getOrCreate({
-        data: {
-          starts_at: new Date().toISOString(),
-        },
-      });
-    }
+    try {
+      if (!call) {
+        await newCall.getOrCreate({
+          data: { starts_at: new Date().toISOString() },
+        });
+      }
+    } catch (err) {
+      console.error("Failed to start room:", err);
+      toast({ title: "Error", description: "Failed to start the meeting. Please try again.", variant: "destructive" });
+      return;
+    }
 
     router.push(`/meeting/${meetingId}?personal=true`);
   };

101-105: Avoid “undefined” in invitation topic and improve copy text robustness

If user?.username is not set, the invitation currently prints “undefined’s Meeting Room”. Provide a sensible fallback.

Apply this diff:

-            const inviteText = `Join my meeting room!\n\nTopic: ${user?.username}'s Meeting Room\nMeeting ID: ${meetingId}\nJoin Link: ${meetingLink}`;
+            const displayName = user?.username ?? user?.fullName ?? "Personal";
+            const inviteText = `Join my meeting room!\n\nTopic: ${displayName}'s Meeting Room\nMeeting ID: ${meetingId || 'TBD'}\nJoin Link: ${meetingLink || 'TBD'}`;
README.md (3)

36-45: Wrap install commands in code fences

Without fences, markdownlint flags and formatting suffer. Fence these commands.

Apply this diff:

 Install dependencies:
-npm install
-# or
-yarn install
+```bash
+npm install
+# or
+yarn install
+```

46-50: Fence dev commands for consistency and readability

Same as above for the dev server commands.

Apply this diff:

 Run the development server:
-npm run dev
-# or
-yarn dev
+```bash
+npm run dev
+# or
+yarn dev
+```

51-51: Avoid bare URL (MD034) by formatting the localhost link

This also reads better.

Apply this diff:

-Open your browser at http://localhost:3000 🎉
+Open your browser at [`http://localhost:3000`](http://localhost:3000) 🎉
components/CallList.tsx (1)

20-50: Avoid setState on unmounted component during async recordings fetch

Add a cancellation flag to prevent setRecordings after unmount or type switch.

Apply this diff:

   useEffect(() => {
-    const fetchRecordings = async () => {
+    let cancelled = false;
+    const fetchRecordings = async () => {
       if (!callRecordings?.length) {
-        setRecordings([]);
+        if (!cancelled) setRecordings([]);
         return;
       }
 
       try {
         const callData = await Promise.all(
           callRecordings.map((meeting) =>
             meeting.queryRecordings().catch((error) => {
               console.error("Error fetching recording:", error);
               return { recordings: [] } as any;
             }),
           ),
         );
 
         const newRecordings = callData
           .filter((c) => c.recordings?.length > 0)
           .flatMap((c) => c.recordings);
 
-        setRecordings(newRecordings);
+        if (!cancelled) setRecordings(newRecordings);
       } catch (error) {
         console.error("Error fetching recordings:", error);
         toast({ title: "Error", description: "Failed to fetch recordings.", variant: "destructive" });
-        setRecordings([]);
+        if (!cancelled) setRecordings([]);
       }
     };
 
-    if (type === "recordings") fetchRecordings();
-  }, [type, callRecordings, toast]);
+    if (type === "recordings") fetchRecordings();
+    return () => {
+      cancelled = true;
+    };
+  }, [type, callRecordings, toast]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4a08170 and 48831bf.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • .env (1 hunks)
  • .gitignore (1 hunks)
  • .nvmrc (1 hunks)
  • README.md (1 hunks)
  • app/(root)/(home)/layout.tsx (1 hunks)
  • app/(root)/(home)/page.tsx (1 hunks)
  • app/(root)/(home)/personal-room/page.tsx (4 hunks)
  • app/layout.tsx (2 hunks)
  • components/CallList.tsx (1 hunks)
  • components/MeetingTypeList.tsx (1 hunks)
  • components/MobileNav.tsx (1 hunks)
  • components/Navbar.tsx (1 hunks)
  • lib/meeting-utils.ts (1 hunks)
  • package.json (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
components/MeetingTypeList.tsx (1)
lib/meeting-utils.ts (1)
  • getMeetingLink (1-12)
app/(root)/(home)/personal-room/page.tsx (2)
components/ui/use-toast.ts (1)
  • toast (194-194)
lib/meeting-utils.ts (1)
  • getMeetingLink (1-12)
components/CallList.tsx (2)
hooks/useGetCalls.ts (1)
  • useGetCalls (5-52)
components/ui/use-toast.ts (2)
  • useToast (194-194)
  • toast (194-194)
🪛 dotenv-linter (3.3.0)
.env

[warning] 2-2: [UnorderedKey] The CLERK_SECRET_KEY key should go before the NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY key

(UnorderedKey)


[warning] 10-10: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🪛 LanguageTool
README.md

[grammar] ~1-~1: There might be a mistake here.
Context: # Ro0m 🎥 An open-source, browser-based alternative...

(QB_NEW_EN)


[grammar] ~6-~6: There might be a mistake here.
Context: ...y. 🔗 Live Demo: ro0m.vercel.app --- ## ✨ Features - 🔊 **Real-time video & audio...

(QB_NEW_EN)


[grammar] ~10-~10: There might be a mistake here.
Context: ...s://ro0m.vercel.app) --- ## ✨ Features - 🔊 Real-time video & audio powered b...

(QB_NEW_EN)


[grammar] ~12-~12: There might be a mistake here.
Context: ...e video & audio** powered by WebRTC - 💬 Chat support during calls - 🖥️ *...

(QB_NEW_EN)


[grammar] ~13-~13: There might be a mistake here.
Context: ... 💬 Chat support during calls - 🖥️ Screen sharing - 📱 **Responsive ...

(QB_NEW_EN)


[grammar] ~14-~14: There might be a mistake here.
Context: ...calls - 🖥️ Screen sharing - 📱 Responsive design (works on desktop &...

(QB_NEW_EN)


[grammar] ~15-~15: There might be a mistake here.
Context: ...gn** (works on desktop & mobile) - 🔗 Instant room creation with unique shar...

(QB_NEW_EN)


[grammar] ~16-~16: There might be a mistake here.
Context: ...** with unique shareable links - 🌐 Self-hostable — deploy on your own serv...

(QB_NEW_EN)


[grammar] ~16-~16: There might be a mistake here.
Context: ...eable links - 🌐 Self-hostable — deploy on your own server or Vercel --- ## 🛠️ T...

(QB_NEW_EN)


[grammar] ~20-~20: There might be a mistake here.
Context: ... your own server or Vercel --- ## 🛠️ Tech Stack - [Next.js](https://nextjs.org/...

(QB_NEW_EN)


[grammar] ~21-~21: There might be a mistake here.
Context: ... or Vercel --- ## 🛠️ Tech Stack - Next.js – React fra...

(QB_NEW_EN)


[grammar] ~22-~22: There might be a mistake here.
Context: ...s://nextjs.org/) – React framework - WebRTC – Real-time ...

(QB_NEW_EN)


[grammar] ~23-~23: There might be a mistake here.
Context: ...tc.org/) – Real-time communication - Tailwind CSS –...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...m/) – Modern utility-first styling - Vercel – Deployment...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...ps://vercel.com/) – Deployment & hosting --- ## 🚀 Getting Started ### Prerequisites Mak...

(QB_NEW_EN)


[grammar] ~28-~28: There might be a mistake here.
Context: ... & hosting --- ## 🚀 Getting Started ### Prerequisites Make sure you have the foll...

(QB_NEW_EN)


[grammar] ~30-~30: There might be a mistake here.
Context: ...## 🚀 Getting Started ### Prerequisites Make sure you have the following install...

(QB_NEW_EN)


[grammar] ~31-~31: There might be a mistake here.
Context: ...e sure you have the following installed: - Node.js (v16 or la...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ...have the following installed: - Node.js (v16 or later) - npm or yarn package ma...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ....js](https://nodejs.org/) (v16 or later) - npm or yarn package manager ### Install...

(QB_NEW_EN)


[grammar] ~35-~35: There might be a mistake here.
Context: ...r yarn package manager ### Installation 1. Clone the repo: ```bash git clone ...

(QB_NEW_EN)


[grammar] ~41-~41: There might be a mistake here.
Context: ...0m.git cd Ro0m Install dependencies: npm install # or yarn install Run the d...

(QB_NEW_EN)


[grammar] ~42-~42: There might be a mistake here.
Context: ... Ro0m Install dependencies: npm install # or yarn install Run the development ser...

(QB_NEW_EN)


[grammar] ~43-~43: There might be a mistake here.
Context: ... Install dependencies: npm install # or yarn install Run the development server...

(QB_NEW_EN)


[grammar] ~46-~46: There might be a mistake here.
Context: ...arn install Run the development server: npm run dev # or yarn dev Open your bro...

(QB_NEW_EN)


[grammar] ~47-~47: There might be a mistake here.
Context: ... Run the development server: npm run dev # or yarn dev Open your browser at http:/...

(QB_NEW_EN)


[grammar] ~48-~48: There might be a mistake here.
Context: ...the development server: npm run dev # or yarn dev Open your browser at http://lo...

(QB_NEW_EN)


[grammar] ~51-~51: There might be a mistake here.
Context: ...your browser at http://localhost:3000 🎉 ⚙️ Environment Variables NEXT_PUBLIC_PEER...

(QB_NEW_EN)


[grammar] ~53-~53: There might be a mistake here.
Context: ...alhost:3000 🎉 ⚙️ Environment Variables NEXT_PUBLIC_PEER_SERVER=your-peer-server...

(QB_NEW_EN)


[grammar] ~54-~54: There might be a mistake here.
Context: ...NEXT_PUBLIC_PEER_SERVER=your-peer-server NEXT_PUBLIC_TURN_SERVER=your-turn-server...

(QB_NEW_EN)


[grammar] ~55-~55: There might be a mistake here.
Context: ...NEXT_PUBLIC_TURN_SERVER=your-turn-server NEXT_PUBLIC_STUN_SERVER=your-stun-server...

(QB_NEW_EN)


[grammar] ~56-~56: There might be a mistake here.
Context: ...NEXT_PUBLIC_STUN_SERVER=your-stun-server 👉 You can use free Google STUN servers ...

(QB_NEW_EN)


[grammar] ~57-~57: There might be a mistake here.
Context: ...oy your own TURN server for reliability. ☁️ Deployment Deploy instantly with Verce...

(QB_NEW_EN)


[grammar] ~59-~59: There might be a mistake here.
Context: ...N server for reliability. ☁️ Deployment Deploy instantly with Vercel: Fork this ...

(QB_NEW_EN)


[grammar] ~60-~60: There might be a mistake here.
Context: ...Deployment Deploy instantly with Vercel: Fork this repo Push to your GitHub accou...

(QB_NEW_EN)


[grammar] ~65-~65: There might be a mistake here.
Context: ...es (if any) Done 🎉 — your Ro0m is live! 🤝 Contributing Contributions are welcome...

(QB_NEW_EN)


[style] ~71-~71: Consider using a more formal and expressive alternative to ‘awesome’.
Context: ...Commit your changes (git commit -m 'Add awesome feature') Push to the branch (git push ...

(AWESOME)


[grammar] ~75-~75: There might be a mistake here.
Context: ...eature) Open a Pull Request 📜 License This project is licensed under the MIT Li...

(QB_NEW_EN)


[grammar] ~76-~76: There might be a mistake here.
Context: ...This project is licensed under the MIT License – see the LICENSE file for details. 🙏 Acknow...

(QB_NEW_EN)


[grammar] ~76-~76: There might be a mistake here.
Context: ...ense – see the LICENSE file for details. 🙏 Acknowledgments adrianhajdin/zoom-clon...

(QB_NEW_EN)


[grammar] ~78-~78: There might be a mistake here.
Context: ...E file for details. 🙏 Acknowledgments adrianhajdin/zoom-clone – Original inspir...

(QB_NEW_EN)


[grammar] ~79-~79: There might be a mistake here.
Context: ... 🙏 Acknowledgments adrianhajdin/zoom-clone – Original inspiration & base project The open-sou...

(QB_NEW_EN)


[grammar] ~79-~79: There might be a mistake here.
Context: ...ne – Original inspiration & base project The open-source community ❤️

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)
README.md

48-48: Multiple headings with the same content

(MD024, no-duplicate-heading)


51-51: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (6)
.nvmrc (1)

1-1: Pinning Node 18 is appropriate for Next.js 14 — LGTM

This aligns with Next 14’s supported Node range and common Vercel defaults.

components/MobileNav.tsx (1)

32-35: Branding update looks good

Alt text and visible brand updated to Ro0m consistently with the rename.

components/Navbar.tsx (1)

15-20: Branding update looks good

Alt text and brand text updated to Ro0m consistently with other components.

app/layout.tsx (1)

30-31: Logo path update looks correct

ClerkProvider’s logoImageUrl now points to /icons/logo.svg, consistent with the rest of the app and metadata icons.

app/(root)/(home)/layout.tsx (1)

8-9: Brand rename applied — LGTM

Metadata title updated to Ro0m; consistent with top-level layout and Navbar/MobileNav.

components/CallList.tsx (1)

54-60: Unified rendering and toast-backed error handling look solid

The consolidation into a single rendering path, selective iconography, and per-item click handling reads cleaner and easier to maintain.

Also applies to: 65-101

Comment on lines +1 to +10
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_YWNjZXB0ZWQtY2hvdy05NS5jbGVyay5hY2NvdW50cy5kZXYk
CLERK_SECRET_KEY=sk_test_mpfZe0XiSoV5SZgUn8ZqCNT9pVTu4fYMTAdcpIH8X7

NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up

NEXT_PUBLIC_STREAM_API_KEY=wmvqzwwh9s4q
STREAM_SECRET_KEY=86e88tqe2h82zvah5ge99ct584fn2gwd8mhewyy87vkesk4zmm6z62bgqegwer7j

NEXT_PUBLIC_BASE_URL=https://ro0m.vercel.app No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Secrets are committed to the repo (.env). Remove and rotate immediately.
Committing CLERK_SECRET_KEY and STREAM_SECRET_KEY (even test keys) is a high-severity leak. These credentials should be considered compromised.

Immediate actions:

  • Revoke/rotate the exposed secrets in Clerk and Stream dashboards.
  • Remove the file from Git and from history:
    • In this PR: run git rm --cached .env, commit, and push (the file will remain in history).
    • To purge history (recommended for public repos): use BFG Repo-Cleaner or git filter-repo to remove .env from all commits, then force-push.
  • Add a non-sensitive .env.example with placeholders and keep .env ignored (rules are already in .gitignore).

Optionally, I can provide a .env.example template with the correct keys and comments.

🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 2-2: [UnorderedKey] The CLERK_SECRET_KEY key should go before the NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY key

(UnorderedKey)


[warning] 10-10: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🤖 Prompt for AI Agents
.env lines 1-10: Sensitive secrets (CLERK_SECRET_KEY, STREAM_SECRET_KEY, etc.)
are committed and must be removed and rotated immediately; revoke/rotate the
exposed keys in Clerk and Stream dashboards, delete the file from the repo with
git rm --cached .env then commit and push, and purge the secret from history
using BFG or git filter-repo (force-push after cleaning) for public repos; add a
non-sensitive .env.example with placeholder values, ensure .env is listed in
.gitignore, and avoid re-committing real secrets.

Comment on lines +72 to +75
const date =
(isRecording ? (meeting as CallRecording).start_time : (meeting as Call).state?.startsAt)?.toLocaleString?.() ||
"No date";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix date formatting for strings vs Dates

Calling .toLocaleString?.() on a string does not format the date; you’ll get the unformatted string. Normalize to a Date before formatting.

Apply this diff:

-          const date =
-            (isRecording ? (meeting as CallRecording).start_time : (meeting as Call).state?.startsAt)?.toLocaleString?.() ||
-            "No date";
+          const rawDate = isRecording
+            ? (meeting as CallRecording).start_time
+            : (meeting as Call).state?.startsAt;
+          const date = rawDate ? new Date(rawDate as any).toLocaleString() : "No date";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const date =
(isRecording ? (meeting as CallRecording).start_time : (meeting as Call).state?.startsAt)?.toLocaleString?.() ||
"No date";
const rawDate = isRecording
? (meeting as CallRecording).start_time
: (meeting as Call).state?.startsAt;
const date = rawDate ? new Date(rawDate as any).toLocaleString() : "No date";
🤖 Prompt for AI Agents
In components/CallList.tsx around lines 72 to 75, the code calls toLocaleString
on values that may be strings, so the string won’t be normalized to a Date;
instead, extract the raw timestamp (use meeting as CallRecording).start_time
when isRecording else (meeting as Call).state?.startsAt, check if that value is
an instance of Date and use it directly, otherwise construct a new
Date(rawValue) and verify it’s valid (date.getTime() is not NaN); then call
toLocaleString on the Date and fall back to "No date" if the value is missing or
invalid. Ensure the branch handles null/undefined safely and does not call
toLocaleString on a string.

Comment on lines +90 to +98
handleClick={() => {
if (isRecording) {
const url = (meeting as CallRecording).url;
if (url) router.push(url);
else toast({ title: "Error", description: "Recording URL not found", variant: "destructive" });
} else {
openMeeting((meeting as Call).id);
}
}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use window.open for external recording URLs instead of router.push

next/navigation’s router only supports internal navigation. Pushing an absolute URL can fail. Open recordings in a new tab.

Apply this diff:

-              handleClick={() => {
+              handleClick={() => {
                 if (isRecording) {
                   const url = (meeting as CallRecording).url;
-                  if (url) router.push(url);
+                  if (url) window.open(url, "_blank", "noopener,noreferrer");
                   else toast({ title: "Error", description: "Recording URL not found", variant: "destructive" });
                 } else {
                   openMeeting((meeting as Call).id);
                 }
               }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
handleClick={() => {
if (isRecording) {
const url = (meeting as CallRecording).url;
if (url) router.push(url);
else toast({ title: "Error", description: "Recording URL not found", variant: "destructive" });
} else {
openMeeting((meeting as Call).id);
}
}}
handleClick={() => {
if (isRecording) {
const url = (meeting as CallRecording).url;
if (url) window.open(url, "_blank", "noopener,noreferrer");
else toast({ title: "Error", description: "Recording URL not found", variant: "destructive" });
} else {
openMeeting((meeting as Call).id);
}
}}
🤖 Prompt for AI Agents
In components/CallList.tsx around lines 90 to 98, the click handler currently
uses router.push for recording URLs which only supports internal navigation;
change it to open the recording in a new browser tab using window.open(url,
'_blank', 'noopener,noreferrer') when url exists, and keep the toast fallback
for missing URL; leave the non-recording branch calling openMeeting((meeting as
Call).id) unchanged.

Comment on lines +32 to +33
- [Node.js](https://nodejs.org/) (v16 or later)
- npm or yarn package manager
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect Node.js version requirement for Next.js 14

The project (per package.json in this PR) uses Next.js ^14.2.x, which requires Node.js 18+. Update the prerequisite to avoid setup failures on Node 16.

Apply this diff:

-- [Node.js](https://nodejs.org/) (v16 or later)
+- [Node.js](https://nodejs.org/) (v18 LTS or later)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [Node.js](https://nodejs.org/) (v16 or later)
- npm or yarn package manager
- [Node.js](https://nodejs.org/) (v18 LTS or later)
- npm or yarn package manager
🧰 Tools
🪛 LanguageTool

[grammar] ~32-~32: There might be a mistake here.
Context: ...have the following installed: - Node.js (v16 or later) - npm or yarn package ma...

(QB_NEW_EN)


[grammar] ~32-~32: There might be a mistake here.
Context: ....js](https://nodejs.org/) (v16 or later) - npm or yarn package manager ### Install...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In README.md around lines 32-33, the Node.js prerequisite is incorrect (lists
Node v16) while package.json requires Next.js ^14.2.x which needs Node.js 18+,
so update the prerequisite to state Node.js v18 or later (and optionally mention
an LTS recommendation), leaving the package manager line as-is; ensure the
README reflects Node 18+ to prevent setup failures.

Comment on lines +38 to 40
git clone https://github.com/archduke1337/Ro0m.git
cd Ro0m

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Repository clone URL likely does not match this project

The README instructs cloning a different repository. Use this repo’s canonical slug or a parameterized placeholder to prevent confusion.

Apply this diff (adjust the URL to the actual canonical repo):

-   git clone https://github.com/archduke1337/Ro0m.git
-   cd Ro0m
+   git clone https://github.com/adrianhajdin/zoom-clone.git
+   cd zoom-clone
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
git clone https://github.com/archduke1337/Ro0m.git
cd Ro0m
git clone https://github.com/adrianhajdin/zoom-clone.git
cd zoom-clone
🤖 Prompt for AI Agents
In README.md around lines 38 to 40, the git clone URL points to
"https://github.com/archduke1337/Ro0m.git" which is likely for a different
project; replace it with the repository’s canonical slug or a parameterized
placeholder (e.g. "https://github.com/<org>/<repo>.git" or the actual repo URL)
so cloning instructions match this project and avoid confusion.

Comment on lines +53 to +57
⚙️ Environment Variables
NEXT_PUBLIC_PEER_SERVER=your-peer-server
NEXT_PUBLIC_TURN_SERVER=your-turn-server
NEXT_PUBLIC_STUN_SERVER=your-stun-server
👉 You can use free Google STUN servers or deploy your own TURN server for reliability.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Environment variables are mismatched with the current codebase

The app uses Clerk and Stream Video SDK across multiple files and relies on NEXT_PUBLIC_BASE_URL for meeting links. The listed WebRTC STUN/TURN variables aren’t used, which will mislead new contributors. Document the actual required variables and remove or clearly separate optional ones.

Proposed replacement (verify names used in your codebase before merging):

-⚙️ Environment Variables
-NEXT_PUBLIC_PEER_SERVER=your-peer-server
-NEXT_PUBLIC_TURN_SERVER=your-turn-server
-NEXT_PUBLIC_STUN_SERVER=your-stun-server
-👉 You can use free Google STUN servers or deploy your own TURN server for reliability.
+⚙️ Environment Variables
+Create a `.env.local` file with:
+```env
+# Clerk
+NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
+CLERK_SECRET_KEY=sk_test_...
+
+# Stream
+NEXT_PUBLIC_STREAM_API_KEY=your_stream_api_key
+# STREAM_SECRET=your_stream_secret   # if you use server-side tokens
+
+# App base URL (used for invitation links)
+NEXT_PUBLIC_BASE_URL=https://your-domain.com
+```
+If you’re running your own WebRTC infra, list STUN/TURN config separately as optional.

If you’d like, I can scan the repository and produce an authoritative list of env vars referenced in code.


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

declare -a vars=(
  "NEXT_PUBLIC_PEER_SERVER"
  "NEXT_PUBLIC_TURN_SERVER"
  "NEXT_PUBLIC_STUN_SERVER"
  "NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY"
  "CLERK_SECRET_KEY"
  "NEXT_PUBLIC_STREAM_API_KEY"
  "STREAM_SECRET"
  "NEXT_PUBLIC_BASE_URL"
)

echo "Searching for environment variable references in the codebase..."
for var in "${vars[@]}"; do
  echo "=== $var ==="
  rg -n --color never "$var" || echo "No matches"
  echo
done

Length of output: 2344


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "1) Searching for any process.env.*CLERK references..."
rg -n --color never 'process\.env\..*CLERK' -g '*.ts' -g '*.tsx' || echo "No matches for process.env.*CLERK"

echo
echo "2) Locating where ClerkProvider is used:"
rg -n --color never 'ClerkProvider' -g '*.tsx' -g '*.ts' || echo "No matches for ClerkProvider"

echo
echo "3) Broad search for 'clerk' to catch imports or config keys:"
rg -ni --color never 'clerk' -g '*.ts' -g '*.tsx' || echo "No general matches for 'clerk'"

Length of output: 1892


Update README.md to reflect actual environment variables

The current snippet lists NEXT_PUBLIC_PEER_SERVER, NEXT_PUBLIC_TURN_SERVER, and NEXT_PUBLIC_STUN_SERVER, but none of these are referenced anywhere in the codebase—they only appear in README.md. Instead, the app and its dependencies read the following from process.env.*:

  • Clerk (@clerk/nextjs + middleware)
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • CLERK_SECRET_KEY
  • Stream Video SDK (providers/StreamClientProvider.tsx, actions/stream.actions.ts)
    • NEXT_PUBLIC_STREAM_API_KEY
    • STREAM_SECRET_KEY
  • App invitation links (lib/meeting-utils.ts, components/MeetingTypeList.tsx, etc.)
    • NEXT_PUBLIC_BASE_URL

Please remove the unused STUN/TURN entries and replace with this diff in README.md (around lines 53–57):

--- README.md
@@ 53,57
-⚙️ Environment Variables
-NEXT_PUBLIC_PEER_SERVER=your-peer-server
-NEXT_PUBLIC_TURN_SERVER=your-turn-server
-NEXT_PUBLIC_STUN_SERVER=your-stun-server
-👉 You can use free Google STUN servers or deploy your own TURN server for reliability.
+⚙️ Environment Variables
+Create a `.env.local` file with:
+```env
+# Clerk
+NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
+CLERK_SECRET_KEY=sk_test_...
+
+# Stream Video
+NEXT_PUBLIC_STREAM_API_KEY=your_stream_api_key
+STREAM_SECRET_KEY=your_stream_secret_key
+
+# App base URL (used for invitation links)
+NEXT_PUBLIC_BASE_URL=https://your-domain.com
+```
+
+_Optional (only if you run your own WebRTC servers):_
+```env
+STUN_SERVER=your-stun-server
+TURN_SERVER=your-turn-server
+```

This aligns the docs with the variables actually consumed by the codebase.

🧰 Tools
🪛 LanguageTool

[grammar] ~53-~53: There might be a mistake here.
Context: ...alhost:3000 🎉 ⚙️ Environment Variables NEXT_PUBLIC_PEER_SERVER=your-peer-server...

(QB_NEW_EN)


[grammar] ~54-~54: There might be a mistake here.
Context: ...NEXT_PUBLIC_PEER_SERVER=your-peer-server NEXT_PUBLIC_TURN_SERVER=your-turn-server...

(QB_NEW_EN)


[grammar] ~55-~55: There might be a mistake here.
Context: ...NEXT_PUBLIC_TURN_SERVER=your-turn-server NEXT_PUBLIC_STUN_SERVER=your-stun-server...

(QB_NEW_EN)


[grammar] ~56-~56: There might be a mistake here.
Context: ...NEXT_PUBLIC_STUN_SERVER=your-stun-server 👉 You can use free Google STUN servers ...

(QB_NEW_EN)


[grammar] ~57-~57: There might be a mistake here.
Context: ...oy your own TURN server for reliability. ☁️ Deployment Deploy instantly with Verce...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In README.md around lines 53 to 57, the listed environment variables
(NEXT_PUBLIC_PEER_SERVER, NEXT_PUBLIC_TURN_SERVER, NEXT_PUBLIC_STUN_SERVER) are
not used by the codebase; update the section to remove those unused entries and
replace them with the actual env vars consumed: add Clerk keys
(NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY and CLERK_SECRET_KEY), Stream Video keys
(NEXT_PUBLIC_STREAM_API_KEY and STREAM_SECRET_KEY), and NEXT_PUBLIC_BASE_URL for
invitation links, and move STUN/TURN into an optional block labeled for
self-hosted WebRTC servers (STUN_SERVER and TURN_SERVER).

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.

1 participant