diff --git a/components/common/NavBar.tsx b/components/common/NavBar.tsx
new file mode 100644
index 0000000..1f6d8cf
--- /dev/null
+++ b/components/common/NavBar.tsx
@@ -0,0 +1,102 @@
+import Link from "next/link";
+import { useState, Fragment } from "react";
+import { NavTemplate } from "../../layouts/NavTemplates";
+import Image from "next/image";
+import { m, Variants } from "framer-motion";
+
+interface NavProps {
+ options: NavTemplate[];
+}
+
+// nav bar animation, fades in and then animates the children
+const containerAnimation: Variants = {
+ initial: {
+ opacity: 1,
+ },
+ animate: {
+ opacity: 1,
+ transition: {
+ duration: 2,
+ delayChildren: 0.5,
+ staggerChildren: 0.25,
+ },
+ },
+};
+
+// default animation for nav bar items
+const itemAnimation: Variants = {
+ initial: {
+ opacity: 0,
+ x: 100,
+ },
+ animate: {
+ opacity: 1,
+ x: 0,
+ },
+};
+
+function NavBar({ options }: NavProps) {
+ const [navList, setNavList] = useState(options);
+ return (
+
+
+
+
+
+
+
+ InvestBot
+
+
+
+
+ {navList.map((nav, index) => (
+ {nav.content}
+ ))}
+
+
+
+ Login blah blah
+
+
+
+
+ );
+}
+
+export default NavBar;
diff --git a/layouts/HomeLayout.tsx b/layouts/HomeLayout.tsx
new file mode 100644
index 0000000..fe56766
--- /dev/null
+++ b/layouts/HomeLayout.tsx
@@ -0,0 +1,37 @@
+// Layout/container used for the main mostly empty landing page, can be used for related pages (credits, about, etc.)
+
+import { AnimatePresence, domAnimation, LazyMotion } from "framer-motion";
+import Head from "next/head";
+import NavBar from "../components/common/NavBar";
+import { NavTemplate } from "./NavTemplates";
+
+interface HomeLayoutProps {
+ navOptions: NavTemplate[];
+ children: React.ReactNode;
+}
+
+function HomeLayout(props: HomeLayoutProps) {
+ // get the nav options
+ const navOptions = props.navOptions;
+ return (
+ <>
+
+ InvestBot
+
+
+
+
+
+
+
+
+
+
+ {props.children}
+
+
+ >
+ );
+}
+
+export default HomeLayout;
diff --git a/layouts/NavTemplates.tsx b/layouts/NavTemplates.tsx
new file mode 100644
index 0000000..4b74c1c
--- /dev/null
+++ b/layouts/NavTemplates.tsx
@@ -0,0 +1,44 @@
+import { m } from "framer-motion";
+import Link from "next/link";
+import { ReactComponentElement, ReactElement } from "react";
+
+const DefaultNavOption = ({
+ label,
+ href,
+}: {
+ label: string;
+ href: string;
+}): ReactElement => {
+ return (
+
+
+
+ {label}
+
+
+
+ );
+};
+
+interface NavTemplate {
+ content: ReactComponentElement | ReactElement;
+}
+
+const homeMain: NavTemplate[] = [];
+
+export { type NavTemplate, homeMain };
diff --git a/next.config.js b/next.config.js
index 3d3bc99..bd38de3 100644
--- a/next.config.js
+++ b/next.config.js
@@ -2,6 +2,9 @@
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
+ images: {
+ domains: ["cdn.discordapp.com", "static-cdn.jtvnw.net", "cdn.7tv.app"],
+ },
};
module.exports = nextConfig;
diff --git a/pages/index.tsx b/pages/index.tsx
index 869ab07..2118f0e 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,17 +1,93 @@
-import Head from "next/head";
+import { m } from "framer-motion";
+import { ReactElement, useEffect, useState } from "react";
+import HomeLayout from "../layouts/HomeLayout";
+import { homeMain } from "../layouts/NavTemplates";
+import type { NextPageWithLayout } from "./_app";
+import Image from "next/image";
+
+const Home: NextPageWithLayout = () => {
+ let api7tvEmotes = `/api/7tv/emotes?c=61ad997effa9aba101bcfddf`;
+ const [emotesUrls, setEmotes] = useState([]);
+ const [currentEmote, setCurrentEmote] = useState(0);
+ useEffect(() => {
+ fetch(api7tvEmotes)
+ .then((res) => res.json())
+ .then((data) => {
+ // get all emote URLs
+ let emoteUrls = data.channel.user.emote_sets[0].emotes.map(
+ (emote: any) => {
+ let base_url = emote.data.host.url;
+ // get the largest emote size, append it to the base url
+ let largest =
+ emote.data.host.files[emote.data.host.files.length - 1];
+ // if width != height, skip it
+ if (largest.width !== largest.height) {
+ return null;
+ }
+ return `https:${base_url}/${largest.name}`;
+ }
+ );
+
+ // remove null values
+
+ emoteUrls = emoteUrls.filter((emote: any) => emote !== null);
+
+ setEmotes(emoteUrls);
+ console.log(emoteUrls);
+ });
+ console.log(currentEmote);
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ // choose a random emote
+ let randomEmote = Math.floor(Math.random() * emotesUrls.length);
+ setCurrentEmote(randomEmote);
+ }, 5000);
+ return () => clearInterval(interval);
+ }, [emotesUrls]);
+
+ // until the emotes are loaded, show the logo as a placeholder
+ let slideShow = (
+
+ );
+ if (emotesUrls) {
+ slideShow = (
+
+ );
+ }
-export default function Home() {
return (
-
-
-
InvestBot
-
-
-
-
-
- Hello :o
-
+
+
+
+ Buy high
+ Sell low
+ ...or something like that
+
+
{slideShow}
+
);
-}
+};
+
+// set the layout for the page, this is used to wrap the page in a layout
+Home.getLayout = function getLayout(page: ReactElement) {
+ return
{page};
+};
+
+export default Home;
diff --git a/public/favicon.ico b/public/favicon.ico
index 718d6fe..3ceb202 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/img/logo.webp b/public/img/logo.webp
new file mode 100644
index 0000000..740f4d7
Binary files /dev/null and b/public/img/logo.webp differ
diff --git a/tailwind.config.js b/tailwind.config.js
index 4842997..e189919 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -3,6 +3,7 @@ module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
+ "./layouts/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},