1chooo / 1chooo.com

👨🏻‍💻 $ ls -al Hugo -- A Turborepo of my personal website and blog built using React and Next.js, and Nextra (V3), fully responsive across all devices
https://1chooo.com
Creative Commons Attribution 4.0 International
12 stars 2 forks source link

[Refactor] Optimizing Page Layout by Centralizing Shared Components #112

Closed 1chooo closed 3 months ago

1chooo commented 3 months ago

Currently, our pages have repetitive elements. For example, in the portfolio section, we only need to modify the <Projects /> component to display content on other pages. This means that components like NavBar and SideBar are shared across all pages. To avoid duplicating code, we could incorporate these components into the layout.tsx file. This would streamline our layout and eliminate the need for repetitive coding.

1chooo commented 3 months ago

Corrected layout.tsx

import Script from "next/script";
import type { Metadata } from "next";
import "./globals.css";
import SideBar from "@/components/side-bar";
import NavBar from "@/components/nav-bar";
import Hello from "@/components/hello";
import { GoogleAnalytics } from '@next/third-parties/google';

const googleAnalyticId = "G-JGG75799PJ";

export const metadata: Metadata = {
  title: "Hugo ChunHo Lin (1chooo) | Open Source Enthusiast",
  description: "I'm Hugo ChunHo Lin, a graduate with a Bachelor's degree from National Central University (NCU) 🐿️, driven by a sincere passion for Software Engineering 💻.",
  authors: [{ name: "Hugo ChunHo Lin (1chooo)" }],
  keywords: ["Hugo ChunHo Lin", "1chooo", "Software Engineering", "Open Source", "NCU"],
  openGraph: {
    url: "https://1chooo.com/",
    type: "website",
    siteName: "Hugo ChunHo Lin (1chooo) | Open Source Enthusiast",
    title: "Hugo ChunHo Lin (1chooo) | Open Source Enthusiast",
    description: "I'm Hugo ChunHo Lin, a graduate with a Bachelor's degree from National Central University (NCU) 🐿️, driven by a sincere passion for Software Engineering 💻.",
    images: [
      {
        url: "https://raw.githubusercontent.com/1chooo/1chooo.com/main/docs/imgs/cover_transparent_bg.png",
        width: 1200,
        height: 630,
        alt: "Hugo ChunHo Lin (1chooo) Cover Image",
      },
    ],
  },
  twitter: {
    card: "summary_large_image",
    title: "Hugo ChunHo Lin (1chooo) | Open Source Enthusiast",
    description: "I'm Hugo ChunHo Lin, a graduate with a Bachelor's degree from National Central University (NCU) 🐿️, driven by a sincere passion for Software Engineering 💻.",
    images: "https://raw.githubusercontent.com/1chooo/1chooo.com/main/docs/imgs/cover_transparent_bg.png",
  },
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <head>
        {/* Google Analytics */}
        <Script
          src="https://www.googletagmanager.com/gtag/js?id=G-JGG75799PJ"
          strategy="afterInteractive"
        />
        <Script id="google-analytics" strategy="afterInteractive">
          {`
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${googleAnalyticId}');
          `}
        </Script>

        {/* Favicon and Manifest */}
        <link rel="icon" href="/favicon.ico" />
        <link rel="apple-touch-icon" href="/logo192.png" />
        <link rel="manifest" href="/manifest.json" />
      </head>

      <body>
        <main>
          <SideBar />
          <div className="main-content">
            <NavBar />
            {children}
          </div>
        </main>
        <GoogleAnalytics gaId={googleAnalyticId} />
      </body>
    </html>
  );
}

Explanation:

This structure ensures your page is well-organized and semantically appropriate for accessibility and SEO.

Given that the SideBar and NavBar components are now part of the global layout in layout.tsx, the About and Portfolio components only need to focus on their specific content. Here's how you can write the About and Portfolio components:

About Component

'use client';

import PageContent from '@/components/page-content';
import AboutText from '@/components/about/about-text';
import GitHubStats from '@/components/about/github-stats';
import TechStack from '@/components/about/tech-stack';
import LifeStyles from '@/components/about/life-styles';
import { abouts } from '@/config/about';

const About = () => {
  return (
    <PageContent title={abouts.header}>
      <AboutText />
      <GitHubStats />
      <TechStack />
      <LifeStyles />
    </PageContent>
  );
}

export default About;

Portfolio Component

'use client';

import PageContent from '@/components/page-content';
import Projects from '@/components/portfolio/projects';

const Portfolio = () => {
  return (
    <PageContent title="Hugo's Portfolio">
      <Projects />
    </PageContent>
  );
}

export default Portfolio;

Explanation:

  1. PageContent Component: This is a utility component that can wrap your content, managing the page title and any other shared layout needs for individual pages. If you don't have this component yet, you can create it as follows:

    import React from 'react';
    import Header from '@/components/header';
    
    const PageContent: React.FC<{ title: string; children: React.ReactNode }> = ({ title, children }) => {
     return (
       <article data-page={title.toLowerCase().replace(' ', '-')}>
         <Header title={title} />
         {children}
       </article>
     );
    };
    
    export default PageContent;
  2. About Component: It now focuses purely on rendering the content relevant to the About page, without worrying about the layout structure like SideBar or NavBar, which are handled by layout.tsx.

  3. Portfolio Component: Similarly, it focuses on the Projects component specific to the Portfolio page, wrapped inside the PageContent for consistency.

By structuring your components this way, you maintain a clean and modular approach, allowing changes to global layout elements in layout.tsx without affecting the individual page components.