Shots
Odama - Minimal Agency Temlate

Odama - Minimal Agency Temlate

Odama is a minimal & modern Hero Template perfectly suited for studio, designers, or agencies.

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

now accepting new projects

FOR GOOD DESIGN

Lets make this digital age a little more human.

WORK

Overview

The hero section employs a minimalist design approach, emphasizing simplicity and elegance to immediately captivate the viewer’s attention.

Key Components

Supporting Components

Why using dynamic

I encountered the error ReferenceError: document is not defined during the prerendering phase of my Next.js app deployment on Vercel. This issue occurred because the @lottiefiles/react-lottie-player library directly interacts with the DOM, which is unavailable during server-side rendering (SSR). Since Next.js attempts to prerender all pages on the server by default, any DOM-dependent code will fail unless explicitly marked to only render on the client side.

To solve this, I wrapped the Player component using Next.js’s dynamic function with the ssr: false option. This ensures that the component is only rendered in the browser, avoiding SSR-related errors. If you’re copying this code and do not need server-side rendering (e.g., if you’re building a client-only app), you can remove the dynamic wrapper and directly import the Player component as usual. However, keep in mind that without dynamic, you may encounter issues when deploying to SSR environments.

Switch

Picked up this component from shadcn . To add it, simply run:

npx shadcn@latest add switch

Marquee

Snagged this code from MagicUI—trust me, you need to check out their site, it's absolutely fantastic!

import { cn } from "@/lib/utils";
 
interface MarqueeProps {
  className?: string;
  reverse?: boolean;
  pauseOnHover?: boolean;
  children?: React.ReactNode;
  vertical?: boolean;
  cp;
  repeat?: number;
  [key: string]: any;
}
 
export function Marquee({ className, reverse, pauseOnHover = false, children, vertical = false, repeat = 4, ...props }: MarqueeProps) {
  return (
    <div
      {...props}
      className={cn(
        "group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
        {
          "flex-row": !vertical,
          "flex-col": vertical,
        },
        className
      )}
    >
      {Array(repeat)
        .fill(0)
        .map((_, i) => (
          <div
            key={i}
            className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
              "animate-marquee flex-row": !vertical,
              "animate-marquee-vertical flex-col": vertical,
              "group-hover:[animation-play-state:paused]": pauseOnHover,
              "[animation-direction:reverse]": reverse,
            })}
          >
            {children}
          </div>
        ))}
    </div>
  );
}

use-theme

If you're using react.js, feel free to use or tweak this code as needed

import { useContext } from "react";
import { ThemeProviderContext, ThemeProviderState } from "@/context/ThemeContext";
 
export function useTheme(): ThemeProviderState {
  const context = useContext(ThemeProviderContext);
 
  if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider");
 
  return context;
}
Dont forget the context!!
import { createContext, useEffect, useState } from "react";
 
type ThemeProviderProps = {
  children: React.ReactNode;
  defaultTheme?: string;
  storageKey?: string;
};
 
export type ThemeProviderState = {
  theme: string;
  setTheme: (theme: string) => void;
};
 
const initialState = {
  theme: "system",
  setTheme: () => null,
};
 
export const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
 
export function ThemeProvider({ children, defaultTheme = "system", storageKey = "shadcn-ui-theme", ...props }: ThemeProviderProps) {
  const [theme, setTheme] = useState(() => localStorage.getItem(storageKey) ?? defaultTheme);
 
  useEffect(() => {
    const root = window.document.documentElement;
 
    root.classList.remove("light", "dark");
 
    if (theme === "system") {
      const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
 
      root.classList.add(systemTheme);
      return;
    }
 
    root.classList.add(theme);
  }, [theme]);
 
  return (
    <ThemeProviderContext.Provider
      {...props}
      value={{
        theme,
        setTheme: (theme: string) => {
          localStorage.setItem(storageKey, theme);
          setTheme(theme);
        },
      }}
    >
      {children}
    </ThemeProviderContext.Provider>
  );
}

Now the hero section ready to use
Stay tune for more🚀