diff --git a/app/monitor/page.tsx b/app/(admin)/monitor/page.tsx similarity index 97% rename from app/monitor/page.tsx rename to app/(admin)/monitor/page.tsx index 08edfcc..0082f3d 100644 --- a/app/monitor/page.tsx +++ b/app/(admin)/monitor/page.tsx @@ -1,11 +1,11 @@ -import WebVitalsDashboard from "../components/WebVitalsDashboard"; -import Header from "../components/Header"; -import Footer from "../components/Footer"; +import WebVitalsDashboard from "../../components/WebVitalsDashboard"; +import TopNav from "../../components/navigation/TopNav"; +import Footer from "../../components/navigation/Footer"; export default function MonitorPage() { return (
-
+
diff --git a/app/components-preview/page.tsx b/app/(dev)/components-preview/page.tsx similarity index 99% rename from app/components-preview/page.tsx rename to app/(dev)/components-preview/page.tsx index 315a6f5..f653013 100644 --- a/app/components-preview/page.tsx +++ b/app/(dev)/components-preview/page.tsx @@ -1,11 +1,11 @@ "use client"; import { useState } from "react"; -import RuleCard from "../components/RuleCard"; -import Chip from "../components/Chip"; -import MultiSelect from "../components/MultiSelect"; +import RuleCard from "../components/cards/RuleCard"; +import Chip from "../components/controls/Chip"; +import MultiSelect from "../components/controls/MultiSelect"; import Image from "next/image"; -import { getAssetPath } from "../../lib/assetUtils"; +import { getAssetPath } from "../../../lib/assetUtils"; interface ChipData { id: string; diff --git a/app/blog/[slug]/page.tsx b/app/(marketing)/blog/[slug]/page.tsx similarity index 96% rename from app/blog/[slug]/page.tsx rename to app/(marketing)/blog/[slug]/page.tsx index 82d3263..bdd91e2 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/(marketing)/blog/[slug]/page.tsx @@ -5,16 +5,16 @@ import { getBlogPostBySlug, getAllBlogPosts as getAllPosts, type BlogPost, -} from "../../../lib/content"; -import { logger } from "../../../lib/logger"; -import ContentBanner from "../../components/ContentBanner"; -import AskOrganizer from "../../components/AskOrganizer"; -import { getAssetPath, ASSETS } from "../../../lib/assetUtils"; +} from "../../../../lib/content"; +import { logger } from "../../../../lib/logger"; +import ContentBanner from "../../../components/sections/ContentBanner"; +import AskOrganizer from "../../../components/sections/AskOrganizer"; +import { getAssetPath, ASSETS } from "../../../../lib/assetUtils"; import "../blog.css"; // Code split RelatedArticles - blog-specific, below the fold const RelatedArticles = dynamic( - () => import("../../components/RelatedArticles"), + () => import("../../../components/sections/RelatedArticles"), { loading: () => (
diff --git a/app/blog/blog.css b/app/(marketing)/blog/blog.css similarity index 100% rename from app/blog/blog.css rename to app/(marketing)/blog/blog.css diff --git a/app/blog/page.tsx b/app/(marketing)/blog/page.tsx similarity index 92% rename from app/blog/page.tsx rename to app/(marketing)/blog/page.tsx index 0cc02c4..62c0ad8 100644 --- a/app/blog/page.tsx +++ b/app/(marketing)/blog/page.tsx @@ -1,5 +1,5 @@ -import { getAllBlogPosts } from "../../lib/content"; -import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate"; +import { getAllBlogPosts } from "../../../lib/content"; +import ContentThumbnailTemplate from "../../../components/content/ContentThumbnailTemplate"; import type { Metadata } from "next"; export const metadata: Metadata = { diff --git a/app/learn/page.tsx b/app/(marketing)/learn/page.tsx similarity index 87% rename from app/learn/page.tsx rename to app/(marketing)/learn/page.tsx index 750d8a9..1644679 100644 --- a/app/learn/page.tsx +++ b/app/(marketing)/learn/page.tsx @@ -1,9 +1,9 @@ -import messages from "../../messages/en/index"; -import { getTranslation } from "../../lib/i18n/getTranslation"; -import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate"; -import ContentLockup from "../components/ContentLockup"; -import AskOrganizer from "../components/AskOrganizer"; -import { getAllBlogPosts } from "../../lib/content"; +import messages from "../../../messages/en/index"; +import { getTranslation } from "../../../lib/i18n/getTranslation"; +import ContentThumbnailTemplate from "../../components/content/ContentThumbnailTemplate"; +import ContentLockup from "../../components/type/ContentLockup"; +import AskOrganizer from "../../components/sections/AskOrganizer"; +import { getAllBlogPosts } from "../../../lib/content"; export default function LearnPage() { // Get real blog posts from the content system diff --git a/app/page.tsx b/app/(marketing)/page.tsx similarity index 78% rename from app/page.tsx rename to app/(marketing)/page.tsx index b85e238..525b6ef 100644 --- a/app/page.tsx +++ b/app/(marketing)/page.tsx @@ -1,39 +1,39 @@ import dynamic from "next/dynamic"; -import messages from "../messages/en/index"; -import { getTranslation } from "../lib/i18n/getTranslation"; -import HeroBanner from "./components/HeroBanner"; -import AskOrganizer from "./components/AskOrganizer"; +import messages from "../../messages/en/index"; +import { getTranslation } from "../../lib/i18n/getTranslation"; +import HeroBanner from "../components/sections/HeroBanner"; +import AskOrganizer from "../components/sections/AskOrganizer"; // Code split below-the-fold components to reduce initial bundle size -const LogoWall = dynamic(() => import("./components/LogoWall"), { +const LogoWall = dynamic(() => import("../components/sections/LogoWall"), { loading: () => (
), ssr: true, }); -const NumberedCards = dynamic(() => import("./components/NumberedCards"), { +const NumberedCards = dynamic(() => import("../components/sections/NumberedCards"), { loading: () => (
), ssr: true, }); -const RuleStack = dynamic(() => import("./components/RuleStack"), { +const RuleStack = dynamic(() => import("../components/sections/RuleStack"), { loading: () => (
), ssr: true, }); -const FeatureGrid = dynamic(() => import("./components/FeatureGrid"), { +const FeatureGrid = dynamic(() => import("../components/sections/FeatureGrid"), { loading: () => (
), ssr: true, }); -const QuoteBlock = dynamic(() => import("./components/QuoteBlock"), { +const QuoteBlock = dynamic(() => import("../components/sections/QuoteBlock"), { loading: () => (
), diff --git a/app/components/ConditionalHeader/ConditionalHeader.container.tsx b/app/components/ConditionalHeader/ConditionalHeader.container.tsx deleted file mode 100644 index 5f006f1..0000000 --- a/app/components/ConditionalHeader/ConditionalHeader.container.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import { memo } from "react"; -import { usePathname } from "next/navigation"; -import { ConditionalHeaderView } from "./ConditionalHeader.view"; -import type { ConditionalHeaderProps } from "./ConditionalHeader.types"; - -const ConditionalHeaderContainer = memo(() => { - const pathname = usePathname(); - const isHomePage = pathname === "/"; - - return ; -}); - -ConditionalHeaderContainer.displayName = "ConditionalHeader"; - -export default ConditionalHeaderContainer; diff --git a/app/components/ConditionalHeader/ConditionalHeader.types.ts b/app/components/ConditionalHeader/ConditionalHeader.types.ts deleted file mode 100644 index 61af22a..0000000 --- a/app/components/ConditionalHeader/ConditionalHeader.types.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ConditionalHeaderProps { - // Currently no props, but keeping interface for future extensibility -} - -export interface ConditionalHeaderViewProps { - isHomePage: boolean; -} diff --git a/app/components/ConditionalHeader/ConditionalHeader.view.tsx b/app/components/ConditionalHeader/ConditionalHeader.view.tsx deleted file mode 100644 index ff36612..0000000 --- a/app/components/ConditionalHeader/ConditionalHeader.view.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import HomeHeader from "../HomeHeader"; -import Header from "../Header"; -import type { ConditionalHeaderViewProps } from "./ConditionalHeader.types"; - -export function ConditionalHeaderView({ - isHomePage, -}: ConditionalHeaderViewProps) { - if (isHomePage) { - return ; - } - return
; -} diff --git a/app/components/ConditionalHeader/index.tsx b/app/components/ConditionalHeader/index.tsx deleted file mode 100644 index a05fd67..0000000 --- a/app/components/ConditionalHeader/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ConditionalHeader.container"; -export type { ConditionalHeaderProps } from "./ConditionalHeader.types"; diff --git a/app/components/ContextMenu.tsx b/app/components/ContextMenu/ContextMenu.tsx similarity index 100% rename from app/components/ContextMenu.tsx rename to app/components/ContextMenu/ContextMenu.tsx diff --git a/app/components/ContextMenuDivider.tsx b/app/components/ContextMenu/ContextMenuDivider.tsx similarity index 100% rename from app/components/ContextMenuDivider.tsx rename to app/components/ContextMenu/ContextMenuDivider.tsx diff --git a/app/components/ContextMenuItem/ContextMenuItem.container.tsx b/app/components/ContextMenu/ContextMenuItem/ContextMenuItem.container.tsx similarity index 96% rename from app/components/ContextMenuItem/ContextMenuItem.container.tsx rename to app/components/ContextMenu/ContextMenuItem/ContextMenuItem.container.tsx index 6b524dc..23beff6 100644 --- a/app/components/ContextMenuItem/ContextMenuItem.container.tsx +++ b/app/components/ContextMenu/ContextMenuItem/ContextMenuItem.container.tsx @@ -3,7 +3,7 @@ import { forwardRef, memo, useCallback } from "react"; import { ContextMenuItemView } from "./ContextMenuItem.view"; import type { ContextMenuItemProps } from "./ContextMenuItem.types"; -import { normalizeContextMenuItemSize } from "../../../lib/propNormalization"; +import { normalizeContextMenuItemSize } from "../../../../lib/propNormalization"; const ContextMenuItemContainer = forwardRef< HTMLDivElement, diff --git a/app/components/ContextMenuItem/ContextMenuItem.types.ts b/app/components/ContextMenu/ContextMenuItem/ContextMenuItem.types.ts similarity index 100% rename from app/components/ContextMenuItem/ContextMenuItem.types.ts rename to app/components/ContextMenu/ContextMenuItem/ContextMenuItem.types.ts diff --git a/app/components/ContextMenuItem/ContextMenuItem.view.tsx b/app/components/ContextMenu/ContextMenuItem/ContextMenuItem.view.tsx similarity index 100% rename from app/components/ContextMenuItem/ContextMenuItem.view.tsx rename to app/components/ContextMenu/ContextMenuItem/ContextMenuItem.view.tsx diff --git a/app/components/ContextMenuItem/index.tsx b/app/components/ContextMenu/ContextMenuItem/index.tsx similarity index 100% rename from app/components/ContextMenuItem/index.tsx rename to app/components/ContextMenu/ContextMenuItem/index.tsx diff --git a/app/components/ContextMenuSection.tsx b/app/components/ContextMenu/ContextMenuSection.tsx similarity index 100% rename from app/components/ContextMenuSection.tsx rename to app/components/ContextMenu/ContextMenuSection.tsx diff --git a/app/components/Header/Header.container.tsx b/app/components/Header/Header.container.tsx deleted file mode 100644 index 52f6990..0000000 --- a/app/components/Header/Header.container.tsx +++ /dev/null @@ -1,155 +0,0 @@ -"use client"; - -import { memo } from "react"; -import { usePathname } from "next/navigation"; -import { useTranslation } from "../../contexts/MessagesContext"; -import MenuBarItem from "../MenuBarItem"; -import Button from "../Button"; -import AvatarContainer from "../AvatarContainer"; -import Avatar from "../Avatar"; -import Logo from "../Logo"; -import { getAssetPath, ASSETS } from "../../../lib/assetUtils"; -import { HeaderView } from "./Header.view"; -import type { HeaderProps, NavSize } from "./Header.types"; - -export const avatarImages = [ - { src: getAssetPath(ASSETS.AVATAR_1), alt: "Avatar 1" }, - { src: getAssetPath(ASSETS.AVATAR_2), alt: "Avatar 2" }, - { src: getAssetPath(ASSETS.AVATAR_3), alt: "Avatar 3" }, -]; - -export const logoConfig = [ - { breakpoint: "block sm:hidden", size: "header" as const, showText: false }, - { - breakpoint: "hidden sm:block md:hidden", - size: "header" as const, - showText: true, - }, - { - breakpoint: "hidden md:block lg:hidden", - size: "headerMd" as const, - showText: true, - }, - { - breakpoint: "hidden lg:block xl:hidden", - size: "headerLg" as const, - showText: true, - }, - { breakpoint: "hidden xl:block", size: "headerXl" as const, showText: true }, -]; - -const HeaderContainer = memo(() => { - const pathname = usePathname(); - const t = useTranslation("header"); - - // Schema markup for site navigation - const schemaData = { - "@context": "https://schema.org", - "@type": "WebSite", - name: "CommunityRule", - url: "https://communityrule.com", - potentialAction: { - "@type": "SearchAction", - target: "https://communityrule.com/search?q={search_term_string}", - "query-input": "required name=search_term_string", - }, - }; - - // Navigation items with translations - const navigationItems = [ - { href: "#", text: t("navigation.useCases"), extraPadding: true }, - { href: "/learn", text: t("navigation.learn") }, - { href: "#", text: t("navigation.about") }, - ]; - - const renderNavigationItems = (size: NavSize) => { - return navigationItems.map((item, index) => ( - - {item.text} - - )); - }; - - const renderAvatarGroup = ( - containerSize: "small" | "medium" | "large" | "xlarge", - avatarSize: "small" | "medium" | "large" | "xlarge", - ) => { - return ( - - {avatarImages.map((avatar, index) => ( - - ))} - - ); - }; - - const renderLoginButton = (size: NavSize) => { - return ( - - {t("buttons.logIn")} - - ); - }; - - const renderCreateRuleButton = ( - buttonSize: "xsmall" | "small" | "medium" | "large" | "xlarge", - containerSize: "small" | "medium" | "large" | "xlarge", - avatarSize: "small" | "medium" | "large" | "xlarge", - ) => { - return ( - - ); - }; - - const renderLogo = ( - size: - | "default" - | "homeHeaderXsmall" - | "homeHeaderSm" - | "homeHeaderMd" - | "homeHeaderLg" - | "homeHeaderXl" - | "header" - | "headerMd" - | "headerLg" - | "headerXl" - | "footer" - | "footerLg", - showText: boolean, - ) => { - return ; - }; - - return ( - - ); -}); - -HeaderContainer.displayName = "Header"; - -export default HeaderContainer; diff --git a/app/components/Header/Header.view.tsx b/app/components/Header/Header.view.tsx deleted file mode 100644 index 780c7b2..0000000 --- a/app/components/Header/Header.view.tsx +++ /dev/null @@ -1,124 +0,0 @@ -"use client"; - -import { useTranslation } from "../../contexts/MessagesContext"; -import MenuBar from "../MenuBar"; -import type { HeaderViewProps } from "./Header.types"; - -export function HeaderView({ - schemaData, - logoConfig, - renderNavigationItems, - renderLoginButton, - renderCreateRuleButton, - renderLogo, -}: HeaderViewProps) { - const t = useTranslation("header"); - - return ( - <> -