Skip to content

refactor(frontend): centralize category list for tabs and seeding#67

Merged
ViktorSvertoka merged 3 commits into
developfrom
refactoring
Dec 20, 2025
Merged

refactor(frontend): centralize category list for tabs and seeding#67
ViktorSvertoka merged 3 commits into
developfrom
refactoring

Conversation

@ViktorSvertoka
Copy link
Copy Markdown
Member

@ViktorSvertoka ViktorSvertoka commented Dec 20, 2025

Refactor: Centralize Category List for Tabs and Seeding

Overview

This pull request refactors category handling on the frontend by centralizing the category source used across the application.

Previously, category lists were duplicated in multiple places, which caused inconsistencies when adding or updating categories. This change ensures that tabs rendering and database seeding stay in sync by relying on a single shared category definition.

What Was Changed

  • Centralized the category list into a shared source
  • Removed duplicated category arrays
  • Made the default active tab derive from the shared category list
  • Ensured consistent category usage across UI and seeding logic

Summary by CodeRabbit

  • Style

    • Updated tabs grid layout from 5 to 7 columns for improved spacing and organization.
  • Refactor

    • Replaced hardcoded category data with dynamic category management from a centralized data source.
    • Reorganized internal data structure for better maintainability.

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

@netlify
Copy link
Copy Markdown

netlify Bot commented Dec 20, 2025

Deploy Preview for develop-devlovers ready!

Name Link
🔨 Latest commit ae36ed2
🔍 Latest deploy log https://app.netlify.com/projects/develop-devlovers/deploys/6946bb89747901000851e448
😎 Deploy Preview https://deploy-preview-67--develop-devlovers.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 20, 2025

Walkthrough

This PR refactors the frontend to centralize category definitions into a new data module. It introduces category.ts with a shared array of category names, updates the tabs component to use these names dynamically instead of hardcoded values, adjusts the grid layout, and relocates parse-related script paths.

Changes

Cohort / File(s) Summary
New Category Data Module
frontend/data/category.ts
Adds new module exporting categoryNames constant array with 7 frontend technology categories: HTML, CSS, JavaScript, React, Angular, Vue, Next.
Tab Component Refactoring
frontend/components/shared/TabsSection.tsx
Imports categoryNames and derives DEFAULT_CATEGORY from first entry with fallback. Replaces hardcoded categories with imported data throughout URL parsing, active state logic, and rendering. Updates grid from 5 to 7 columns and removes explicit capitalize class from TabsTrigger elements.
Data Seed & Path Updates
frontend/db/seed-categories.ts, frontend/db/seed.ts, frontend/package.json
Refactors seed-categories to use imported categoryNames instead of hardcoded array and renames main() to categoriesList(). Updates import paths: seed.ts references ../parse/questions.json instead of ../data/questions.json; package.json updates parse script path to parse/parse.ts.
Formatting
frontend/app/layout.tsx
Adds trailing newline after final closing brace.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10–15 minutes

  • Verify that categoryNames is correctly imported and referenced across TabsSection.tsx, seed-categories.ts, and the tabs rendering logic
  • Confirm that DEFAULT_CATEGORY fallback ('HTML') is used consistently in URL parameter handling
  • Validate that parse script path updates (parse/parse.ts and parse/questions.json) are consistent and point to the correct locations
  • Confirm the grid layout change from 5 to 7 columns does not introduce unintended styling breakages
  • Check that removal of the capitalize class does not visually affect tab labels

Suggested reviewers

  • AM1007

Poem

🐰 Seven tabs now dance in harmony,
From hardcoded chains, the data breaks free!
Categories centralized, paths realigned,
A tidier structure, neatly designed!
hops with glee

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: centralizing the category list that was previously duplicated across tabs and seeding components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactoring

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

Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (1)
frontend/data/categories.ts (1)

1-9: Consider making the array readonly for immutability.

The categoryNames array serves as a single source of truth and should be protected from accidental mutations. Consider using as const assertion for better type safety.

🔎 Proposed fix to add const assertion
-export const categoryNames = [
+export const categoryNames = [
   'HTML',
   'CSS',
   'JavaScript',
   'React',
   'Angular',
   'Vue',
   'Next',
-];
+] as const;

This will:

  • Make the array readonly at the type level
  • Narrow the type from string[] to a tuple of literal types
  • Prevent accidental mutations like categoryNames.push('Svelte')
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5244260 and 1e94d6c.

📒 Files selected for processing (5)
  • frontend/app/layout.tsx (1 hunks)
  • frontend/components/shared/TabsSection.tsx (5 hunks)
  • frontend/data/categories.ts (1 hunks)
  • frontend/db/seed-categories.ts (1 hunks)
  • frontend/package.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/db/seed-categories.ts (2)
frontend/data/categories.ts (1)
  • categoryNames (1-9)
frontend/db/index.ts (1)
  • db (17-17)
🔇 Additional comments (8)
frontend/app/layout.tsx (1)

29-29: LGTM - Standard formatting convention.

The trailing newline after the closing brace follows standard file formatting conventions.

frontend/db/seed-categories.ts (2)

5-5: LGTM - Centralized category data source.

Importing categoryNames from the shared data module eliminates hardcoded duplication and ensures consistency across seeding and UI components.


7-15: LGTM - Improved function naming and data source.

The function rename from main to categoriesList is more descriptive, and iterating over the imported categoryNames maintains the same logic while using the centralized category definition.

frontend/components/shared/TabsSection.tsx (4)

29-35: LGTM - Consistent URL handling and state initialization.

The URL parameter extraction and initial state logic correctly use DEFAULT_CATEGORY as the fallback, with proper validation to ensure only valid categories are set as active.


45-63: LGTM - Clean URL strategy by excluding default values.

The updateUrl function correctly excludes the default category from URL parameters, keeping URLs clean and consistent with the pattern of excluding other defaults (page 1, empty search).


161-166: LGTM - Grid layout matches category count.

The grid layout correctly expands from 5 to 7 columns to accommodate the 7 categories defined in categoryNames. Removing the capitalize class is appropriate since category names in the source data are already properly cased.


178-182: LGTM - Appropriate conditional messaging.

The conditional rendering correctly displays different messages based on whether a search query is active, providing clear feedback to users in both scenarios.

frontend/package.json (1)

13-13: No action required. The parse script path parse/parse.ts is correctly updated and the file exists at the specified location.

Comment thread frontend/components/shared/TabsSection.tsx Outdated
Copy link
Copy Markdown
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: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e94d6c and 0517862.

📒 Files selected for processing (3)
  • frontend/components/shared/TabsSection.tsx (5 hunks)
  • frontend/data/categories.ts (1 hunks)
  • frontend/db/seed.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/components/shared/TabsSection.tsx
🔇 Additional comments (1)
frontend/db/seed.ts (1)

9-9: LGTM! The relocated parse output path is correctly updated.

The import path in frontend/db/seed.ts line 9 has been successfully updated to ../parse/questions.json, the new file exists at frontend/parse/questions.json, and no lingering references to the old path remain in the codebase.

Comment thread frontend/data/categories.ts Outdated
Comment on lines +1 to +9
export const categories = [
'HTML',
'CSS',
'JavaScript',
'React',
'Angular',
'Vue',
'Next',
];
Copy link
Copy Markdown
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:

#!/bin/bash
# First, check the structure of the frontend directory
echo "=== Directory structure ==="
git ls-files frontend/ | head -20

echo -e "\n=== Content of frontend/data/categories.ts ==="
cat -n frontend/data/categories.ts

echo -e "\n=== Search for hardcoded category arrays ==="
# Look for array literals containing category names
rg -n --type=ts --type=tsx "(\[.*HTML.*CSS|React.*Vue)" frontend/ -g '!frontend/data/categories.ts' | head -20

echo -e "\n=== Search for imports from categories ==="
rg -n --type=ts --type=tsx "from.*categories|import.*categories" frontend/ | head -20

echo -e "\n=== Search for hardcoded category strings together ==="
rg -n --type=ts --type=tsx "'HTML'.*'CSS'|'React'.*'Vue'|'Angular'" frontend/ -g '!frontend/data/categories.ts' | head -30

Repository: DevLoversTeam/devlovers.net

Length of output: 1260


🏁 Script executed:

#!/bin/bash
# Look for any mentions of the specific category names together
echo "=== Searching for potential duplicate category definitions ==="
rg -n "HTML|CSS|JavaScript|React|Angular|Vue|Next" frontend/ --type ts --type tsx | grep -E "\[|const|export" | head -30

Repository: DevLoversTeam/devlovers.net

Length of output: 178


🏁 Script executed:

#!/bin/bash
# Get the exact content and check for imports
echo "=== categories.ts content ==="
cat frontend/data/categories.ts

echo -e "\n=== Check for other data files in frontend/data ==="
ls -la frontend/data/ 2>/dev/null || echo "Directory not found"

echo -e "\n=== Search for files that import from categories ==="
rg --type=ts --type=tsx "from.*categories|import.*categories" frontend/ 2>/dev/null || echo "No imports found"

echo -e "\n=== Search for hardcoded arrays with category keywords ==="
rg -B2 -A8 "'HTML'" frontend/ --type=ts --type=tsx -g '!categories.ts' 2>/dev/null | head -50

Repository: DevLoversTeam/devlovers.net

Length of output: 567


🏁 Script executed:

#!/bin/bash
# Broader search without type flags for files with category keywords
echo "=== Search for files mentioning category names ==="
rg -n "TabsSection|seed-categories" frontend/ 2>/dev/null || echo "Files not found"

echo -e "\n=== Search for exports/definitions with category-like patterns ==="
rg -n "export.*\[" frontend/ --max-count 20 | head -30

echo -e "\n=== Look for arrays containing HTML ==="
rg -n -B2 -A6 "HTML" frontend/ -g '!categories.ts' 2>/dev/null | head -50

echo -e "\n=== Check all TypeScript/TSX files in frontend ==="
find frontend -name "*.ts" -o -name "*.tsx" | wc -l

echo -e "\n=== Search for category-related code ==="
rg -n "category\|categories" frontend/ -i 2>/dev/null | grep -v categories.ts | head -20

Repository: DevLoversTeam/devlovers.net

Length of output: 6249


🏁 Script executed:

#!/bin/bash
# Check the existing CATEGORIES in catalog.ts
echo "=== Content of frontend/lib/config/catalog.ts (first 60 lines) ==="
head -60 frontend/lib/config/catalog.ts

echo -e "\n=== Look for seed-categories.ts ==="
find . -name "seed-categories.ts" -o -name "*seed*categories*" 2>/dev/null

echo -e "\n=== Check database directory ==="
ls -la db/ 2>/dev/null | head -20

Repository: DevLoversTeam/devlovers.net

Length of output: 1929


🏁 Script executed:

#!/bin/bash
# Check the seed-categories.ts file
echo "=== Content of frontend/db/seed-categories.ts ==="
cat frontend/db/seed-categories.ts

echo -e "\n=== Check TabsSection.tsx ==="
cat frontend/components/shared/TabsSection.tsx

Repository: DevLoversTeam/devlovers.net

Length of output: 6638


🏁 Script executed:

#!/bin/bash
# Double-check the exact exports and imports
echo "=== Exact exports from categories.ts ==="
grep "export" frontend/data/categories.ts

echo -e "\n=== Exact imports in seed-categories.ts ==="
grep "import\|from" frontend/db/seed-categories.ts | head -5

echo -e "\n=== Check if categoryNames is defined elsewhere ==="
rg "categoryNames|export.*categoryNames" frontend/

Repository: DevLoversTeam/devlovers.net

Length of output: 534


Fix import mismatch in seed-categories.ts—currently cannot export a non-existent categoryNames.

The centralization successfully eliminates duplication in TabsSection.tsx, which correctly imports categories from the new module. However, seed-categories.ts attempts to import categoryNames from ../data/categories, which does not exist. The export is named categories, not categoryNames. This will cause the seed script to fail at runtime.

Change the import in seed-categories.ts from:

import { categoryNames } from '../data/categories';

to:

import { categories } from '../data/categories';
🤖 Prompt for AI Agents
In frontend/data/categories.ts lines 1-9: the module exports a named export
called "categories" but seed-categories.ts imports a non-existent
"categoryNames"; update seed-categories.ts to import the correct named export
"categories" from '../data/categories' (replace the import of categoryNames with
categories) so the seed script uses the existing export.

@ViktorSvertoka ViktorSvertoka merged commit b835ee6 into develop Dec 20, 2025
4 of 5 checks passed
@ViktorSvertoka ViktorSvertoka deleted the refactoring branch December 20, 2025 15:09
Copy link
Copy Markdown
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: 0

🧹 Nitpick comments (2)
frontend/data/category.ts (1)

1-9: Consider making the array immutable with as const.

Adding as const assertion would provide better type safety by making the array readonly and narrowing the types to literal values, preventing accidental modifications.

🔎 Proposed refactor
-export const categoryNames = [
+export const categoryNames = [
   'HTML',
   'CSS',
   'JavaScript',
   'React',
   'Angular',
   'Vue',
   'Next',
-];
+] as const;

Then you could derive a type like type CategoryName = typeof categoryNames[number] for type-safe usage elsewhere.

frontend/components/shared/TabsSection.tsx (1)

160-166: Consider making grid columns dynamic.

The grid-cols-7 class is hardcoded to match the current number of categories. If categories are added or removed from categoryNames, this class needs manual synchronization. Consider making it dynamic to improve maintainability.

🔎 Potential approaches

Option 1: Use Tailwind's arbitrary value syntax

-        <TabsList className="grid grid-cols-7 mb-6">
+        <TabsList className={`grid grid-cols-[repeat(${categoryNames.length},minmax(0,1fr))] mb-6`}>

Option 2: Use inline style

-        <TabsList className="grid grid-cols-7 mb-6">
+        <TabsList 
+          className="grid mb-6"
+          style={{ gridTemplateColumns: `repeat(${categoryNames.length}, minmax(0, 1fr))` }}
+        >

Option 3: Define dynamic Tailwind classes (if you have a safelist in tailwind.config)
Create a helper function or ensure Tailwind JIT can handle the dynamic class.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0517862 and ae36ed2.

📒 Files selected for processing (3)
  • frontend/components/shared/TabsSection.tsx (5 hunks)
  • frontend/data/category.ts (1 hunks)
  • frontend/db/seed-categories.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/db/seed-categories.ts
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/components/shared/TabsSection.tsx (1)
frontend/data/category.ts (1)
  • categoryNames (1-9)
🔇 Additional comments (4)
frontend/components/shared/TabsSection.tsx (4)

11-13: LGTM! Centralized category import.

The import and DEFAULT_CATEGORY definition look good. The fallback value correctly matches the first category in the array, addressing the previous review comment.


44-62: Verify the default category change is intentional.

The URL omission logic now treats 'HTML' as the default category instead of 'react'. This means:

  • URLs without a category parameter now default to 'HTML' (previously 'react')
  • The category parameter is omitted for 'HTML' instead of 'react'

This is a breaking change that affects existing bookmarks, shared links, and search engine indexed pages. While this appears aligned with the PR's centralization goals, please confirm:

  1. This behavior change is intentional
  2. Any necessary migration or user communication has been planned
  3. Analytics/monitoring is in place to track impact

161-184: LGTM! Clean dynamic rendering.

The dynamic rendering of tabs using categoryNames.map() is well-implemented. The code correctly:

  • Uses category names as unique keys
  • Displays properly capitalized category names
  • Handles loading, results, and empty states appropriately

28-34: LGTM! Robust URL parameter validation.

The validation logic correctly checks that the category from the URL exists in categoryNames before using it, falling back to DEFAULT_CATEGORY if invalid. This provides good protection against URL manipulation.

liudmylasovetovs pushed a commit that referenced this pull request Jan 9, 2026
refactor(frontend): centralize category list for tabs and seeding
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