Skip to content

Update system to include disabling data into the new navbar#21

Merged
hpware merged 7 commits intomasterfrom
canery
Dec 16, 2025
Merged

Update system to include disabling data into the new navbar#21
hpware merged 7 commits intomasterfrom
canery

Conversation

@hpware
Copy link
Owner

@hpware hpware commented Dec 16, 2025

Summary by CodeRabbit

  • New Features

    • Server Owner field in dashboard settings
    • Toggle to expose server version in footer
    • Markdown rendering with list support for content pages
    • New Collections pages and dynamic content display
  • Improvements

    • Lazy loading for images
    • Animated UI transitions and enhanced close controls
    • Simplified API responses and footer version display
  • Chores

    • Dependency added (motion)
    • Version bumped to 0.1.14
    • Removed several automated CI/release workflows

✏️ Tip: You can customize this high-level summary in your review settings.

adding motion!! animations!! and edited the main image viewer, video
viewer is not coming tho, and markdown view is still in beta
@dokploy-hpwartwweb2
Copy link

dokploy-hpwartwweb2 bot commented Dec 16, 2025

Dokploy Preview Deployment

Name Status Preview Updated (UTC)
app ✅ Done Preview URL 2025-12-16T05:14:44.448Z

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

Warning

Rate limit exceeded

@hpware has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between aeafab8 and 78447da.

📒 Files selected for processing (3)
  • apps/web/src/app/dashboard/settings/page.tsx (1 hunks)
  • apps/web/src/components/imageView.tsx (2 hunks)
  • apps/web/src/components/navigation.tsx (4 hunks)

Walkthrough

This PR makes release/versioning changes (treating all versions as stable), removes several GitHub Actions release/build workflows, adds a motion dependency and UI/markdown enhancements, introduces server_owner and displayVersion settings, updates app version to 0.1.14, and modifies a DB migration value.

Changes

Cohort / File(s) Summary
CI/CD & Versioning
\.github/scripts/increment-version.js, \.github/workflows/auto-update-version.yml.disabled, \.github/workflows/build_docker_image.yml.disabled, \.github/workflows/production-release.yml, \.github/workflows/version-and-build.yml
isStableRelease now always returns true (removes prerelease check); auto-update-version.yml trigger changed to pull_request (opened); build_docker_image.yml removed/disabled; production-release.yml and version-and-build.yml deleted, removing automated Docker build/release pipelines.
Project Version & Dependencies
apps/web/projectData.ts, apps/web/package.json, package.json
Bumped app version from "0.1.13-canary-1" to "0.1.14"; added motion dependency ^12.23.26 to both root and app package.json.
Settings API & System Info
apps/web/src/app/api/data/settings/route.ts, apps/web/src/app/api/data/system_info/route.ts
settings/route.ts: added server_owner handling, introduced displayVersion toggle and persistence, expanded validation, simplified JSON responses, added robotsTxt endpoints, and reorganized conditional flow. system_info/route.ts: stopped converting some fields to boolean — feature_status.homePage, feature_status.search, and optionalExposeVersion now return raw string values.
Dashboard Settings UI
apps/web/src/app/dashboard/settings/clientComponents.tsx, apps/web/src/app/dashboard/settings/page.tsx
Added serverOwnerData prop and Server Owner input; introduced displayVersion boolean state and Expose Server Version toggle; propagated displayVersion and server_owner through API payloads and mutation handling; page fetches and passes owner value.
Collection Pages & Client Component
apps/web/src/app/c/[slug]/client.tsx, apps/web/src/app/c/[slug]/page.tsx
Added a new Client component and updated page to fetch content and user info, then delegate rendering to Client; replaced local type alias with explicit inferred schema types.
Markdown & Content Rendering
apps/web/src/app/i/[slug]/page.tsx, apps/web/src/components/markdownRender.tsx, apps/web/src/components/imageView.tsx
Added Markdown rendering (marked-react) and renderer list/listitem methods; improved image modal (motion animations, overlay click handling, rounded container); user avatar image uses lazy loading.
UI Components & Animations
apps/web/src/components/navigation.tsx, apps/web/src/components/publicPostsAndVideos.tsx
Added React Query fetching of /api/data/system_info; wired UI to display owner and optional version; wrapped ImageView in AnimatePresence and motion for animated mount/unmount.
Database Migration
packages/db/src/migrations/0014_reflective_roughhouse.sql
Changed kv_data inserted copyrightOwner value from 'Default Owner' to '"Default Owner"' (quotes included in string).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

  • apps/web/src/app/api/data/settings/route.ts: validate server_owner/displayVersion validation, persistence keys, and simplified response shape.
  • apps/web/src/app/dashboard/settings/clientComponents.tsx: ensure displayVersion and server_owner propagate correctly through UI, mutation payloads, and error paths.
  • apps/web/src/app/api/data/system_info/route.ts and consuming components: confirm consumers handle string-returned feature flags.
  • Workflow removals: verify CI/CD consequences and intentional deletions.
  • Motion integration: confirm the new dependency, component behaviour, and accessibility of animated UI (imageView, publicPostsAndVideos).

Possibly related PRs

Poem

🐰
I hopped the branch and nudged the version free,
From canary crumbs to stable 0.1.14, whee!
I added motion steps and markdown's bright song,
Gave the owner a name and a toggle to show the throng.
Release pipelines nap now — the rabbit hums along.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions 'disabling data into the new navbar' but the actual changes primarily involve version management, workflow modifications, feature toggles, server owner data, and markdown rendering—not navbar disabling functionality. Revise the title to accurately reflect the main changes, such as 'Update version management and add feature toggles for settings' or provide clarity on what navbar disabling entails.
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security
Copy link

socket-security bot commented Dec 16, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedmotion@​12.23.2610010010096100

View full report

Copy link
Contributor

@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: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
apps/web/src/app/c/[slug]/page.tsx (2)

36-39: Add error handling for missing user.

The code accesses getUserInfo[0] without verifying the array is non-empty. If the user referenced by content[0].byUser doesn't exist in the database, this will throw a runtime error.

Apply this diff to add error handling:

 const getUserInfo = await db
   .select()
   .from(auth_schema.user)
   .where(dorm.eq(auth_schema.user.id, content[0].byUser));
+
+if (getUserInfo.length === 0) {
+  notFound();
+}

74-77: Add error handling for missing user in generateMetadata.

Same issue as in the Page component—getUserInfo[0] is accessed without checking if the array is empty.

Apply this diff:

 const getUserInfo = await db
   .select()
   .from(auth_schema.user)
   .where(dorm.eq(auth_schema.user.id, content[0].byUser));
+
+if (getUserInfo.length === 0) {
+  return {
+    title: "Undefined",
+  };
+}
apps/web/src/app/dashboard/settings/clientComponents.tsx (1)

56-56: Typo in Content-Type header.

"appilcation/json" should be "application/json". This may cause the request to fail or be misinterpreted by the server.

           headers: {
-            "Content-Type": "appilcation/json",
+            "Content-Type": "application/json",
           },
.github/workflows/auto-update-version.yml.disabled (1)

1-65: Disabled workflow file has been recently modified—clarify intent.

The .disabled extension prevents GitHub Actions from executing this workflow, yet it contains recently updated trigger configuration (pull_request instead of push). This mismatch suggests unclear intent:

  • If intentionally disabled, the trigger changes are unnecessary and waste maintenance effort.
  • If meant to be active, rename the file to .github/workflows/auto-update-version.yml to enable execution.

Remove the .disabled extension if this workflow should be enabled, or revert the recent trigger modifications if it should remain disabled.

♻️ Duplicate comments (1)
apps/web/src/components/navigation.tsx (1)

50-54: Type mismatch in feature gating logic.

The disabled logic compares feature_status.home and feature_status.search against true, but the API returns strings (see route.ts line 29-30). This will cause the buttons to be incorrectly disabled.

This is already flagged in the route.ts review. Please ensure the types are consistent between the API and consumer.

Also applies to: 65-69

🧹 Nitpick comments (8)
apps/web/src/app/c/[slug]/page.tsx (2)

8-14: Remove unused imports.

The imports for Suspense, CalendarPlusIcon, CalendarSyncIcon, DotIcon, Link, and Badge are no longer used in this component after the refactoring.

Apply this diff to remove unused imports:

-import { Suspense } from "react";
 import { auth } from "@devlogs_hosting/auth";
 import { headers } from "next/headers";
 import type { Metadata } from "next";
-import { CalendarPlusIcon, CalendarSyncIcon, DotIcon } from "lucide-react";
-import Link from "next/link";
-import { Badge } from "@/components/ui/badge";
 import Client from "./client";

27-39: Consider extracting duplicate query logic.

The same database queries are executed in both the Page component and generateMetadata. This duplication can lead to maintenance issues and potential inconsistencies. Consider extracting the query logic into a shared function wrapped with React's cache() to ensure the queries are deduplicated during the same render.

Example implementation:

import { cache } from 'react';

const getCollectionData = cache(async (slug: string) => {
  const content = await db
    .select()
    .from(main_schema.collections)
    .where(dorm.eq(main_schema.collections.id, slug));

  if (content.length === 0) {
    return null;
  }

  const getUserInfo = await db
    .select()
    .from(auth_schema.user)
    .where(dorm.eq(auth_schema.user.id, content[0].byUser));

  if (getUserInfo.length === 0) {
    return null;
  }

  return { content: content[0], userInfo: getUserInfo[0] };
});

Then use this function in both Page and generateMetadata.

Also applies to: 64-77

apps/web/src/app/c/[slug]/client.tsx (1)

9-29: Most data props are currently unused.

The component receives userInfo, slug, createdAt, and updatedAt but only renders data.title. While this may be intentional for an incremental implementation, ensure these props are utilized or removed to maintain a clean API surface.

apps/web/src/components/navigation.tsx (1)

77-83: Handle loading state for dynamic footer content.

The footer displays dynamic content (copyright_owner, version) but doesn't show a loading state. During initial load, empty strings will be displayed.

Consider adding a loading skeleton:

 <span className="text-sm mt-1">
-  &copy; {new Date().getFullYear()}{" "}
-  {querySystemData.data?.copyright_owner || ""}{" "}
-  {querySystemData.data?.optionalExposeVersion === true
-    ? `| v${querySystemData.data?.version}`
-    : null}
+  {querySystemData.isLoading ? (
+    <span className="animate-pulse">Loading...</span>
+  ) : (
+    <>
+      &copy; {new Date().getFullYear()}{" "}
+      {querySystemData.data?.copyright_owner || ""}{" "}
+      {querySystemData.data?.optionalExposeVersion === true
+        ? `| v${querySystemData.data?.version}`
+        : null}
+    </>
+  )}
 </span>
apps/web/package.json (1)

35-35: Duplicate motion dependency in workspace and root.

The motion library (v12.23.26) is declared in both the root package.json and apps/web/package.json. In a monorepo structure, this can lead to:

  • Version drift if updated in one location but not the other
  • Increased bundle size if both versions are installed
  • Dependency management complexity

Choose one approach:

  1. Keep in workspace package only (recommended if only used in web app)
  2. Keep in root only if shared across multiple workspaces
  3. Use workspace catalog (add to catalog section in root package.json)

If using workspace catalog:

// In root package.json
"catalog": {
  "motion": "^12.23.26",
  // ...
}

// In apps/web/package.json
"dependencies": {
  "motion": "catalog:",
  // ...
}
apps/web/src/components/publicPostsAndVideos.tsx (1)

170-185: Add exit animation for consistent user experience.

The AnimatePresence wrapper enables entry animation (fade-in) but lacks an exit prop on the motion.div, causing the ImageView to disappear abruptly when closed instead of fading out smoothly.

Apply this diff to add a fade-out exit animation:

         {imageViewSys.previewOn ? (
           <motion.div
             key="box"
             initial={{ opacity: 0 }}
             animate={{ opacity: 1 }}
+            exit={{ opacity: 0 }}
           >
apps/web/src/components/imageView.tsx (1)

36-42: Consider restoring Next.js Image component for optimization benefits.

Switching from the Next.js Image component to a standard <img> tag loses automatic optimizations including WebP conversion, responsive sizing, lazy loading, and blur placeholders. Note that the Image import on Line 3 is now unused.

If there's no specific reason requiring a standard img tag, apply this diff to restore the optimized Image component:

-            <img
+            <Image
               src={imageSrc}
               alt="Preview Image"
               width={500}
               height={500}
               className="rounded-lg"
             />
apps/web/src/components/markdownRender.tsx (1)

4-4: Remove unused font import.

The Ultra font is imported but never used in this file, adding unnecessary bytes to the bundle.

Apply this diff to remove the unused import:

-import { Ultra } from "next/font/google";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a799a19 and bc1576c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .github/scripts/increment-version.js (1 hunks)
  • .github/workflows/auto-update-version.yml.disabled (1 hunks)
  • .github/workflows/build_docker_image.yml.disabled (0 hunks)
  • .github/workflows/production-release.yml (0 hunks)
  • .github/workflows/version-and-build.yml (0 hunks)
  • apps/web/package.json (1 hunks)
  • apps/web/projectData.ts (1 hunks)
  • apps/web/src/app/api/data/settings/route.ts (10 hunks)
  • apps/web/src/app/api/data/system_info/route.ts (1 hunks)
  • apps/web/src/app/c/[slug]/client.tsx (1 hunks)
  • apps/web/src/app/c/[slug]/page.tsx (4 hunks)
  • apps/web/src/app/dashboard/settings/clientComponents.tsx (14 hunks)
  • apps/web/src/app/dashboard/settings/page.tsx (1 hunks)
  • apps/web/src/app/i/[slug]/page.tsx (3 hunks)
  • apps/web/src/components/imageView.tsx (2 hunks)
  • apps/web/src/components/markdownRender.tsx (2 hunks)
  • apps/web/src/components/navigation.tsx (3 hunks)
  • apps/web/src/components/publicPostsAndVideos.tsx (2 hunks)
  • package.json (1 hunks)
  • packages/db/src/migrations/0014_reflective_roughhouse.sql (1 hunks)
💤 Files with no reviewable changes (3)
  • .github/workflows/production-release.yml
  • .github/workflows/version-and-build.yml
  • .github/workflows/build_docker_image.yml.disabled
🧰 Additional context used
🧬 Code graph analysis (4)
apps/web/src/components/publicPostsAndVideos.tsx (1)
apps/web/src/components/imageView.tsx (1)
  • ImageView (6-48)
apps/web/src/app/c/[slug]/page.tsx (2)
packages/db/src/index.ts (1)
  • db (5-7)
apps/web/src/app/c/[slug]/client.tsx (1)
  • Client (9-29)
apps/web/src/components/navigation.tsx (2)
apps/web/src/components/mode-toggle.tsx (1)
  • ModeToggle (14-39)
apps/web/src/components/user-menu.tsx (1)
  • UserMenu (15-59)
apps/web/src/app/api/data/settings/route.ts (1)
packages/db/src/index.ts (1)
  • db (5-7)
🔇 Additional comments (10)
packages/db/src/migrations/0014_reflective_roughhouse.sql (1)

2-3: Verify the value formatting matches the expected storage format.

The copyrightOwner value is now stored as '"Default Owner"' (a string containing double quotes), while exposeVersion is stored as 'false' (a plain string without inner quotes). This suggests the value column stores JSON-formatted values, where:

  • JSON strings require quotes: "Default Owner"
  • JSON booleans don't: false

However, if the column stores JSON, consider whether 'false' (string literal) should instead be a proper JSON boolean or if the application expects string representations.

Run the following script to verify the schema and how these values are used:

#!/bin/bash
# Description: Check kv_data table schema and usage patterns

# Check the kv_data table schema
echo "=== Checking kv_data table schema ==="
rg -n "CREATE TABLE.*kv_data" -A 10

# Check how copyrightOwner values are retrieved/parsed
echo -e "\n=== Checking copyrightOwner usage ==="
rg -n "copyrightOwner" -C 3

# Check how exposeVersion values are retrieved/parsed
echo -e "\n=== Checking exposeVersion usage ==="
rg -n "exposeVersion" -C 3

# Look for JSON parsing of kv_data values
echo -e "\n=== Checking for JSON parsing patterns ==="
rg -n "JSON\\.parse.*kv_data|parse.*kv_data.*value" -C 2
apps/web/src/app/c/[slug]/page.tsx (1)

41-55: LGTM—Data structure correctly passed to Client component.

The data object structure matches the type definition in the Client component, ensuring type safety between the server and client components.

apps/web/src/app/c/[slug]/client.tsx (2)

1-4: Type imports are correctly structured.

The imports are already using the import type syntax, which is optimal for type-only imports and ensures they're stripped during compilation.


1-29: File naming convention is misleading; no client-side features are required.

The component doesn't use any client-side features (no state, effects, event handlers, or browser APIs), so the "use client" directive is not necessary. The file is being called from a Server Component and serves only as a presentational component. While the filename client.tsx suggests client-side functionality, the directive is only required when actually using client-side features. Consider renaming the file to reflect its actual behavior (e.g., collection-display.tsx) to avoid confusion with the naming convention used elsewhere in the codebase.

Likely an incorrect or invalid review comment.

apps/web/src/app/api/data/settings/route.ts (1)

65-73: LGTM!

The server_owner persistence and simplified response format are correctly implemented.

apps/web/src/app/dashboard/settings/clientComponents.tsx (1)

154-171: LGTM!

The new Server Owner input field is correctly wired to the state and follows the existing pattern for the other input fields.

apps/web/projectData.ts (1)

2-2: LGTM! Version bumped to stable release.

The version has been updated from 0.1.13-canary-1 to 0.1.14, marking a stable release. This aligns with the simplified version management changes in the PR.

apps/web/src/app/i/[slug]/page.tsx (1)

98-98: Good practice: lazy loading attribute added.

Adding loading="lazy" to the user avatar image improves page performance by deferring image loads until they're near the viewport.

apps/web/src/components/navigation.tsx (1)

31-31: QueryClientProvider is properly configured.

The Providers component is correctly imported and used in the root layout (apps/web/src/app/layout.tsx), wrapping the entire application tree. This ensures that useQueryClient() in the navigation component has access to the query client context.

apps/web/src/components/markdownRender.tsx (1)

79-95: LGTM! List rendering implementation is solid.

The list and listitem renderer methods correctly handle both ordered and unordered lists with appropriate styling and attributes. The start parameter for ordered lists is properly handled with a sensible default.

Comment on lines +106 to +111
const displayVersion = (
await db
.select()
.from(main_schema.kvData)
.where(dorm.eq(main_schema.kvData.key, "exposeVersion"))
)[0].value;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "exposeVersion" --type ts

Repository: hpware/log

Length of output: 164


🏁 Script executed:

fd -e "seed" -e "migration" -e "init" --type f | head -20

Repository: hpware/log

Length of output: 36


🏁 Script executed:

sed -n '80,115p' apps/web/src/app/api/data/settings/route.ts | cat -n

Repository: hpware/log

Length of output: 1514


Potential runtime error if exposeVersion key doesn't exist.

The code accesses [0].value without verifying the query returned results. If the exposeVersion key is missing from kvData, this will throw a TypeError. While other queries in this block (lines 82-105) follow the same pattern, applying it to newly added code continues an unsafe practice.

Add null safety:

   const displayVersion = (
     await db
       .select()
       .from(main_schema.kvData)
       .where(dorm.eq(main_schema.kvData.key, "exposeVersion"))
-  )[0].value;
+  )[0]?.value ?? false;
🤖 Prompt for AI Agents
In apps/web/src/app/api/data/settings/route.ts around lines 106 to 111, the code
assumes the query returns an entry and uses [0].value directly which will throw
if the "exposeVersion" key is missing; change the code to capture the query
result into a variable, check whether a row was returned before accessing
.value, and then either use a sensible default (e.g., null or an explicit
default string) or return/throw a clear error/log message; ensure you handle
this the same way other kvData lookups in the file handle missing keys for
consistency.

Comment on lines 27 to 30
const content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.userPosts.postId, slug));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Incorrect table reference in WHERE clause.

The query selects from main_schema.collections but filters using main_schema.userPosts.postId. This appears to be incorrect—the WHERE clause should likely reference main_schema.collections.id to match against the slug parameter.

Apply this diff to fix the table reference:

 const content: (typeof main_schema.collections.$inferSelect)[] = await db
   .select()
   .from(main_schema.collections)
-  .where(dorm.eq(main_schema.userPosts.postId, slug));
+  .where(dorm.eq(main_schema.collections.id, slug));
📝 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 content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.userPosts.postId, slug));
const content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.collections.id, slug));
🤖 Prompt for AI Agents
In apps/web/src/app/c/[slug]/page.tsx around lines 27 to 30, the WHERE clause is
referencing main_schema.userPosts.postId while selecting from
main_schema.collections; replace that reference with the correct collections
column (e.g., main_schema.collections.id) so the filter compares collections.id
to the slug (i.e., use dorm.eq(main_schema.collections.id, slug)). Ensure the
imported schema names are correct and adjust types if necessary.

Comment on lines 64 to 67
const content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.userPosts.postId, resolvedParams.slug));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Same incorrect table reference in generateMetadata.

The same database query error exists here—main_schema.userPosts.postId should be main_schema.collections.id.

Apply this diff:

 const content: (typeof main_schema.collections.$inferSelect)[] = await db
   .select()
   .from(main_schema.collections)
-  .where(dorm.eq(main_schema.userPosts.postId, resolvedParams.slug));
+  .where(dorm.eq(main_schema.collections.id, resolvedParams.slug));
📝 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 content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.userPosts.postId, resolvedParams.slug));
const content: (typeof main_schema.collections.$inferSelect)[] = await db
.select()
.from(main_schema.collections)
.where(dorm.eq(main_schema.collections.id, resolvedParams.slug));
🤖 Prompt for AI Agents
In apps/web/src/app/c/[slug]/page.tsx around lines 64 to 67, the query in
generateMetadata uses the wrong table/column reference
(main_schema.userPosts.postId); change the where clause to compare the
collections primary key instead, e.g. use dorm.eq(main_schema.collections.id,
resolvedParams.slug) so the query selects from main_schema.collections by its
id; ensure the comparison uses the correct column (collections.id) and data type
matching resolvedParams.slug.

Comment on lines 69 to 71
<div className="pl-2">
<Markdown renderer={renderer}>{content[0].textData ?? ""}</Markdown>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, find the markdownRender component
fd -t f "markdownRender" --extension ts --extension tsx --extension js --extension jsx

Repository: hpware/log

Length of output: 96


🏁 Script executed:

# Also search for the file more broadly
find . -type f -name "*markdown*" | grep -i render

Repository: hpware/log

Length of output: 98


🏁 Script executed:

# Check the exact file being reviewed to understand the context
cat -n "apps/web/src/app/i/[slug]/page.tsx" | head -80

Repository: hpware/log

Length of output: 3131


🏁 Script executed:

cat -n "apps/web/src/components/markdownRender.tsx"

Repository: hpware/log

Length of output: 3058


🏁 Script executed:

# Also check if DOMPurify or similar sanitization libraries are installed
rg "dompurify|sanitize|xss" --type=ts --type=tsx --type=json -i

Repository: hpware/log

Length of output: 81


🏁 Script executed:

# Check package.json for security-related dependencies
cat apps/web/package.json | grep -A 50 "dependencies"

Repository: hpware/log

Length of output: 1634


🏁 Script executed:

# Search for marked-react usage and configuration
rg "marked-react" -A 5 -B 5 -t ts -t tsx

Repository: hpware/log

Length of output: 81


🏁 Script executed:

# Check if there are any security configurations in next.config or similar
find . -type f \( -name "next.config.*" -o -name ".eslintrc*" -o -name "tsconfig.json" \) -exec grep -l "marked\|security\|sanitize" {} \;

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Check for any middleware or security headers configuration
rg "Content-Security-Policy\|helmet\|security" -t ts -t tsx -t js

Repository: hpware/log

Length of output: 81


🏁 Script executed:

# Search more broadly for marked-react usage
rg "marked-react" --max-count 20

Repository: hpware/log

Length of output: 571


🏁 Script executed:

# Check the exact Markdown component usage in the page
rg "Markdown" apps/web/src/app/i/\[slug\]/page.tsx -A 3 -B 3

Repository: hpware/log

Length of output: 601


🏁 Script executed:

# Look for any marked configuration or security settings
rg "marked\|Markdown" apps/web/src -l | head -20

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Check if there's a marked configuration file
find . -type f -name "marked.config.*" -o -name ".markedrc*"

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Check the promoBlock component to see how it uses Markdown (to compare usage patterns)
cat apps/web/src/app/dashboard/settings/about/promoBlock.tsx

Repository: hpware/log

Length of output: 1587


🏁 Script executed:

# Search for any URL validation or sanitization functions in the codebase
rg "javascript:|data:|sanitize|validate.*url|safe.*url" --max-count 20

Repository: hpware/log

Length of output: 3000


🏁 Script executed:

# Check if React Link component or next/link has any built-in URL validation
rg "as Route" -B 3 -A 3 | head -30

Repository: hpware/log

Length of output: 2641


🏁 Script executed:

# Check marked-react npm documentation or source for default options
# Search for any HTML-related configuration in the codebase
rg "gfm|breaks|pedantic|mangle|smartypants|html.*true" apps/web

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Verify the exact behavior by checking if marked-react passes any options
rg "Markdown" apps/web/src/components -A 2 -B 2

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Check marked version from lock file
rg "marked.*:" bun.lock | head -5

Repository: hpware/log

Length of output: 513


🏁 Script executed:

# Check marked library behavior by looking for any default options or configuration
# Search for how Markdown component is called throughout the app
rg "Markdown" apps/web/src --max-count 30

Repository: hpware/log

Length of output: 506


🏁 Script executed:

# Check if there's any URL validation happening in the renderer or elsewhere
rg "href.*javascript|javascript.*href|validateUrl|isValidUrl|isSafeUrl" apps/web

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Let me check the CodeRender component to see if there's any security pattern there
cat apps/web/src/components/markdownCodeBlock.tsx

Repository: hpware/log

Length of output: 1543


🏁 Script executed:

# Check the exact behavior of Next.js Link with javascript: URLs and marked-react HTML handling
# Look for any security-related issues or discussions in the codebase
rg "XSS|security|vulnerability|sanitize" apps/web/src -i

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Check if marked has any options being used via marked-react
# Look at how marked-react handles HTML by default
node -e "console.log(require('marked').defaults)"  2>/dev/null || echo "Check npm package for marked defaults"

Repository: hpware/log

Length of output: 91


🏁 Script executed:

# Search for any utility functions that might validate URLs or prevent malicious protocols
rg "protocol|javascript:|data:" apps/web/src -i

Repository: hpware/log

Length of output: 4061


🏁 Script executed:

# Check if there's any Content Security Policy configured
rg "csp|Content-Security-Policy" apps/web

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Verify if Next.js Link component handles javascript: URLs safely
# Check if there's any protection against malicious protocols in the codebase
rg "normalizeUrl|sanitizeUrl|href.*http|startsWith.*http" apps/web/src -i

Repository: hpware/log

Length of output: 484


🏁 Script executed:

# Check Next.js version to understand Link component security
cat apps/web/package.json | grep '"next"'

Repository: hpware/log

Length of output: 77


🏁 Script executed:

# Check if there's a utility function for URL validation that should be reused
rg "startsWith.*http" apps/web/src -B 5 -A 5 | head -40

Repository: hpware/log

Length of output: 1038


🏁 Script executed:

# Verify if Next.js 16 Link component has built-in protections
# Check if there are any security tests or validations related to Link component
rg "javascript:|protocol" apps/web -i

Repository: hpware/log

Length of output: 36


🏁 Script executed:

# Final check: see if the renderer is used with any options or wrappers that add security
grep -A 10 "renderer={renderer}" apps/web/src/app/i/\[slug\]/page.tsx

Repository: hpware/log

Length of output: 471


Add URL validation to the Markdown link handler to prevent javascript: protocol URLs.

User-generated markdown is rendered with a custom renderer, and while React auto-escapes text content and marked-react doesn't parse raw HTML by default, the link() handler in markdownRender.tsx does not validate URLs. Markdown containing malicious links like [click](javascript:alert(1)) will render as clickable links that may execute JavaScript.

The codebase already validates URLs elsewhere (e.g., clientComponents.tsx checks for https:// or http://). Apply similar validation to the markdown renderer's link handler:

link(href: string, text: string) {
  // Only allow http, https, and relative URLs
  const isValidUrl = href.startsWith("http://") || 
                     href.startsWith("https://") || 
                     href.startsWith("/");
  if (!isValidUrl) return <span>{text}</span>;
  
  return (
    <Link
      href={href as Route}
      className="..."
      target="_blank"
      key={crypto.randomUUID()}
    >
      {text}
    </Link>
  );
}
🤖 Prompt for AI Agents
In apps/web/src/app/i/[slug]/page.tsx around lines 69 to 71, the Markdown
renderer's link handler currently does not validate hrefs and can render
javascript: or other dangerous protocols; update the renderer's link(href, text)
to only allow http://, https://, or relative (starting with "/") URLs, returning
a plain span with the link text when validation fails, and otherwise render the
Link component (keep target and other props) so malicious javascript: links are
not clickable.

Comment on lines 32 to 39
const querySystemData = useQuery({
queryFn: async () => {
const req = await fetch("/api/data/system_info");
const res = await req.json();
return res;
},
queryKey: ["system_info"],
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add error handling for the system info query.

The query lacks error handling. If the API request fails, the component will render without showing any error state to the user.

Add error handling:

 const querySystemData = useQuery({
   queryFn: async () => {
     const req = await fetch("/api/data/system_info");
+    if (!req.ok) {
+      throw new Error(`Failed to fetch system info: ${req.status}`);
+    }
     const res = await req.json();
     return res;
   },
   queryKey: ["system_info"],
 });

Consider displaying an error state in the UI:

if (querySystemData.isError) {
  console.error("Failed to load system info:", querySystemData.error);
  // Optionally render error UI or fallback to default behavior
}
🤖 Prompt for AI Agents
In apps/web/src/components/navigation.tsx around lines 32 to 39, the system_info
useQuery has no error handling; update the queryFn to detect failed fetches
(check response.ok and throw an Error with response status/text or include
caught network errors) so react-query receives errors, and in the component add
an isError branch to log the error (console.error("Failed to load system info:",
querySystemData.error)) and render an appropriate fallback UI or default values;
optionally set sensible query options (e.g., retry, staleTime) to control retry
behavior.

"dependencies": {
"dotenv": "^17.2.3",
"geist": "^1.5.1",
"motion": "^12.23.26",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

motion library latest version React animation 2025

💡 Result:

Do you mean the "Motion" package (motion.dev) or "framer-motion"? I can list both — which do you want?


🏁 Script executed:

# Check the root package.json and apps/web/package.json to understand the dependency structure
cat -n package.json | head -50

Repository: hpware/log

Length of output: 1671


🏁 Script executed:

# Look for apps/web/package.json and check if motion is also there
find . -name "package.json" -type f | head -20

Repository: hpware/log

Length of output: 148


🌐 Web query:

npm motion package v12.23.26 React animation library

💡 Result:

Yes — "motion" is a React (and JS/Vue) animation library (motion.dev). The package's current release series is 12.x and the latest published release is v12.23.26. Install with:

npm install motion
import { motion } from "motion/react"

Motion requires React 18.2+ and provides springs, keyframes, layout/shared layout animations, gestures, scroll/SVG support, exit animations, SSR, etc. [1][2][3]

Sources:
[1] Motion docs (install / React requirements).
[2] Package metadata showing latest version 12.23.26.
[3] motion GitHub repository / README.


🏁 Script executed:

# Check apps/web/package.json to see if motion is also declared there
cat -n ./apps/web/package.json

Repository: hpware/log

Length of output: 2258


Remove motion from root dependencies — it's already in apps/web/package.json.

Version 12.23.26 is the latest release for the motion animation library and is correct. However, the dependency is unnecessarily declared in both the root package.json and apps/web/package.json at line 35. Since motion is only used by the web app, remove it from the root and keep it only in apps/web/package.json to avoid duplication and simplify dependency management in the monorepo.

🤖 Prompt for AI Agents
In package.json around line 35, the root package declares "motion": "^12.23.26"
which duplicates the dependency already declared in apps/web/package.json;
remove the "motion" entry from the root dependencies block so the package is
only declared in apps/web/package.json, then run the package manager's
install/lockfile update (e.g., npm/yarn pnpm install) to refresh the lockfile
and ensure no stale references remain.

@hpware hpware merged commit 60a728d into master Dec 16, 2025
3 of 4 checks passed
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