# Pages All pages are a separate React component in our repository, under the [pages](../pages) folder. This is a [special directory](https://nextjs.org/docs/tag/v11.0.0/basic-features/pages) used by Next.js which maps a React component exported from this directory to a page on a url. The React components exported by these files are wrapped by the [`App` component](../pages/_app.tsx). This lets us reuse code in between pages which makes it a good place to render the [navbar](../components/Navbar.tsx), [footer](../components/Footer.tsx), [background shapes](../components/ShapesBackground.tsx), and the general CSS layout of a page. ## Title We use a custom [`Title` component](../components/Title.tsx) to set the title on our pages. This is a very simple component and is just a wrapper around the Next.js [`Head` component](https://nextjs.org/docs/tag/v11.0.0/api-reference/next/head). It also automatically prefixes each title with "CSC - University of Waterloo". Look at the [code](../components/Title.tsx) for more details. ### Example 1 ```tsx import { Title } from "@/components/Title" function FooPage() { return ( <> Title in the tab
Content of the page
) } // The page's content will be "Content of the page" // The title of the page (as shown at the top of the browser in the tab) is "CSC - University of Waterloo - Title in the tab" ``` ### Example 2 You can also pass in an array of strings, and the [`Title` component](../components/Title.tsx) will automatically join them with " - ". ```tsx import { Title } from "@/components/Title" function FooPage() { return ( <> {["Foo", "Bar", "Baz"]}
Content of the page
) } // The page's content will be "Content of the page" // The title of the page (as shown at the top of the browser in the tab) is "CSC - University of Waterloo - Foo - Bar - Baz" ``` ## Layout Most pages are wrapped with the [`DefaultLayout`](../components/DefaultLayout.tsx) component which limits the page width and adds the necessary margins and paddings. However, some pages need to override these default styles to accomodate for their specific design. For example: - The [home page](../pages/index.tsx) is wider than all the other pages. - The [about us](../pages/about/index.tsx) needs the entire screen width to properly render the [bubbles](../components/Bubble.tsx).
bubble on about page
The bubble component on the About us page
We have an opt-in model for using a custom layout for pages. This is enabled by the static `Layout` function on a React component for a page. ### Example ```tsx function PageXYZ() { return

I am a page

} // If we want this page to use a custom layout, we can add a static `Layout` function to it. PageXYZ.Layout = function PageXYZLayout(props: { children: React.ReactNode }) { return
{props.children}
; } ``` It is extremely important to return `props.children` as part of the JSX because this contains the entire page. If you fail to return it, the page will **not** show up. Note that this functionality is **not** a part of Next.js. We take advantage of static properties in the [_app.tsx](../pages/_app.tsx#L30) file to implement this. ## Shapes Background Just like the static `Layout` function, we use another static function on React pages called `getShapesConfig`. Most pages use the [default config](../components/ShapesBackground.tsx#L188) which positions shapes randomly on the page. Some pages require a little artistic nudge or even hardcoding the shapes to appear in certain locations. Pages like the [home page](../pages/index.tsx) can use the `getShapesConfig` function to customize what shapes they want the page to render. ### Example 1 ```tsx import { GetShapesConfig } from "@/components/ShapesBackground"; PageXYZ.getShapesConfig = (() => { // I ONLY LIKE DOTS AND WAVES!!!! return { dots: [ { // These map to CSS properties. You don't have to use all of them. Use the ones that you want. top: "calc(0.06 * (580rem / 0.65) / 16)", right: "90vw", width: "calc(168rem / 16)", height: "calc(204rem / 16)", filter: "var(--teal)", opacity: "25%", } ], waves: [ { top: "calc(0.5 * (580rem / 0.65) / 16)", left: "24vw", width: "calc(116rem / 16)", height: "calc(58rem / 16)", filter: "var(--teal)", }, ] } }) as GetShapesConfig ``` Note that background shapes are not rendered into html files during build time because it is impossible to know the window dimensions. This means that you can safely use `window.innerWidth` and `window.innerHeight` as well use the width and height of the shapes container inside the `getShapesConfig` function to change the shapes based on size of the screen. ### Example 2 ```tsx import { GetShapesConfig } from "@/components/ShapesBackground"; PageXYZ.getShapesConfig = ((containerWidth, containerHeight) => { // I like dots on desktops if (window.innerWidth >= 768) { return { dots: [ { // These map to CSS properties. You don't have to use all of them. Use the ones that you want. top: "calc(0.06 * (580rem / 0.65) / 16)", right: "90vw", width: "calc(168rem / 16)", height: "calc(204rem / 16)", filter: "var(--teal)", opacity: "25%", } ], } } // but waves on phones and tables else { return { waves: [ { top: "calc(0.5 * (580rem / 0.65) / 16)", left: "24vw", width: "calc(116rem / 16)", height: "calc(58rem / 16)", filter: "var(--teal)", }, ] } } }) as GetShapesConfig ``` As with the `Layout` function, this is **not** a part of Next.js. We take advantage of static properties in the [_app.tsx](../pages/_app.tsx#L51) file to implement this.