Notes and flow-

  1. We are using Prismic CMS. and use its starter code to set up our web app. It runs the local dev server and a slice machine server. This is provided by Prismic. It's like a workbench to edit our pages on the go. The slice machine also does the work of type declaration for us. So In Prismic, a slice is a reusable, flexible content block used to build dynamic sections of a webpage. It allows you to create custom components (or sections) that can be reused and rearranged in different pages or documents without hardcoding each section.

    When you create a new slice or update a slice using Slice Machine, it generates the necessary TypeScript types for the slice model.

    These types describe the data structure of your slices, making it easier to integrate them with your React components, ensuring that you get accurate type-checking.

    We can add/remove any slices via this server.

  2. In Tailwind CSS, content scanning refers to the process where Tailwind analyzes your project's source files to identify and extract all the utility classes used in your HTML, JSX, TSX, etc. files. It will then generate CSS for the specific classes and omit any unused ones. This process ensures that only the CSS for the classes that are actually used in your project gets included in the final CSS file, making it smaller and more efficient.

    This can be noted via the content property in tailwind’s config file.

  3. For the “Fizzi” logo, we used an svg to JSX converter. And it has a group class which keeps a watch over the parent component, for a hover action, which triggers a wavy animation in the child component. i.e., The overall logo contains a hover effect triggered by the group-hover class. This animation translates a section of the logo, giving the appearance of a wave or slide motion when the user hovers over the logo.

    Some references for animating svg -

    <g> groups multiple elements for transformations or style applications.

    <mask> is used to define a mask that controls the visibility of parts of the content.

    url() is a reference to another element inside the SVG, usually by id, often used in masking or clipping paths.

  4. Next.js has its way to load fonts in an optimized way. Next.js preloads fonts based on where the font function is called. Here’s how it works:

This automatic optimization ensures that fonts are only preloaded when needed, improving performance and avoiding unnecessary font loading.

For our case, we used localFont from Next.js to define our custom fonts as CSS variables and after adding them to our tailwind config file, we can use them globally as we just applied that variable as className on html tag at root level.

And we passed a property Display: swap - displays fallback fonts immediately, and then swaps to the custom font when it’s ready. This avoids content reflow and layout shifts.

  1. Body property - the overflow-hidden utility to clip any content within an element that overflows the bounds of that element.

  2. We build our first slice (reusable content sections) - Hero slice, in which we create various components using our slice machine server. And we can use those code snippets of components (example - image, link, richText fields) in our main code.

  3. PrismicRichText is a component provided by the Prismic library, which is used to render rich text content from Prismic's CMS.

    The content from Prismic is typically stored as a structured data format (JSON), which contains various elements such as paragraphs, headings, lists, links, etc.

    A className is typically applied to a specific HTML element (like a <div>, <p>, etc.), but in the case of PrismicRichText, it is rendering multiple different types of elements (dynamically generates multiple HTML elements) depending on the content (e.g., paragraphs, headings, lists).

    Applying a className directly to the entire component would not affect the individual rendered elements.

    So To style the output of PrismicRichText, we wrap it with a container or use custom serializers to control how each element is rendered.

    <aside> 💡

    **What is the role of CMS here**

    </aside>

    So what we do is style our prismicRichText components individually with tailwind classes. For the 1st grid of our hero component, i.e. the very beginning view/screen.

  4. We make a component - Bounded. This is like a container with certain CSS properties, in which we will inject different UI elements / components. Now on a side note, I was curious how things go under-the-hood when this JSX is converted to Javascript, and how it is executed.

    So I took a closer look at the Bounded Component.

  5. In the second view of Hero Component. To animate the text, we need each word to be in a separate component (or wrapped). So our TextSplitter Component will wrap each word in a span and further each character in a span as well.

  6. We will move onto animating with GSAP and will use its Timeline function to stack up animations. On the first page we created an intro timeline where elements appear one by one after a certain delay. Our second timeline is triggered on our scroll. For the effects on the second page

    useGSAP() in this context is a custom hook provided by a package related to GSAP for use in React. It serves as a drop-in replacement for React's useLayoutEffect() but integrates with GSAP for animation handling. It also falls back to useEffect() if the window object is not defined, making it compatible with server-side rendering (SSR).

    <aside> 💡

    Now the difference between useEffect and useLayoutEffect is only that the code inside useLayoutEffect runs synchronously (this is super important to know) after all DOM mutations are performed but before the browser has painted the screen. This means that it can block the browser from updating the screen until the effect is finished / or block the component from being rendered until the code inside it has finished execution. In contrast, useEffect runs asynchronously after the browser has painted.

    </aside>

  7. Next we will set up a canvas with Three.js. The (0, 0) for three.js is at the center of the viewport unlike CSS which is at top left.

    So Three.js is a powerful and widely-used JavaScript library that enables developers to create and display 3D graphics in a web browser using WebGL.

    and

    React Three Fiber (R3F) is a popular React renderer for Three.js, which allows developers to create 3D graphics and animations in React applications. By integrating Three.js with React, R3F provides a declarative and component-based approach to building 3D scenes, making it easier to manage and manipulate 3D content within a React ecosystem.

  8. Canvas: This is the container that creates a 3D rendering context. Everything inside it will be rendered in 3D space.

    A mesh combines geometry (shape) and material (appearance). In this case, a simple box geometry is created.

    We added some styles directly to our canvas because we needed it to exist over the whole viewport. (position: fixed)

    After having set our canvas properly with configurations that we need, we render our soda can into it. (which is a 3d model created in blender) it is in GLTF file format of which we can get a React component by this GLTF to React Three Fiber converter and we import that in our canvas.

  9. In our SodaCan component -

    useGLTF.preload() is a utility provided by the @react-three/drei library. When this function is called, it triggers the loading of the specified GLTF asset as soon as the code runs. This happens outside of the React component lifecycle, which means the model is ready to be used by the time the SodaCan component mounts.