diff --git a/components/dashboard/NavBar.tsx b/components/dashboard/NavBar.tsx
index b940fd6..af25a5f 100644
--- a/components/dashboard/NavBar.tsx
+++ b/components/dashboard/NavBar.tsx
@@ -6,7 +6,7 @@ function NavBar() {
   return (
     <div className="m-3">
       <m.div
-        className="flex min-h-[5rem] w-full flex-row items-center justify-between rounded-2xl bg-zinc-800 p-1 lg:h-full lg:w-24 lg:flex-col"
+        className="flex min-h-[5rem] w-full flex-row items-center justify-between rounded-2xl bg-zinc-800 bg-opacity-70 p-1 lg:h-full lg:w-24 lg:flex-col"
         variants={navContainerVariants}
         initial="initial"
         animate="animate"
diff --git a/layouts/DashLayout.tsx b/layouts/DashLayout.tsx
index d212598..3d6536f 100644
--- a/layouts/DashLayout.tsx
+++ b/layouts/DashLayout.tsx
@@ -18,7 +18,13 @@ function DashLayout(props: DashLayoutProps) {
   // get the current route for animation purposes
   const router = useRouter();
   return (
-    <>
+    <m.div
+      className="bg-gradient-to-t from-zinc-900 to-[#202737b6]"
+      initial="initial"
+      animate="animate"
+      exit="exit"
+      variants={containerVariants}
+    >
       <Head>
         <title>Dashboard - InvestBot</title>
         <meta name="description" content="Dashboard statistics for InvestBot" />
@@ -57,7 +63,7 @@ function DashLayout(props: DashLayoutProps) {
           </AnimatePresence>
         </LazyMotion>
       </div>
-    </>
+    </m.div>
   );
 }
 
diff --git a/layouts/HomeLayout.tsx b/layouts/HomeLayout.tsx
index 8273c0f..da130f1 100644
--- a/layouts/HomeLayout.tsx
+++ b/layouts/HomeLayout.tsx
@@ -23,7 +23,12 @@ function HomeLayout(props: HomeLayoutProps) {
   // get the current route for animation purposes
   const router = useRouter();
   return (
-    <>
+    <m.div
+      initial="initial"
+      animate="animate"
+      exit="exit"
+      variants={containerVariants}
+    >
       <Head>
         <title>InvestBot</title>
         <meta name="description" content="Serving anny's community est. 2022" />
@@ -59,7 +64,7 @@ function HomeLayout(props: HomeLayoutProps) {
           </m.div>
         </AnimatePresence>
       </LazyMotion>
-    </>
+    </m.div>
   );
 }
 
diff --git a/pages/_app.tsx b/pages/_app.tsx
index c6d8054..d9d8111 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -2,6 +2,7 @@ import "../styles/globals.css";
 import type { ReactElement, ReactNode } from "react";
 import type { NextPage } from "next";
 import type { AppProps } from "next/app";
+import { AnimatePresence, domAnimation, LazyMotion } from "framer-motion";
 
 export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
   getLayout?: (page: ReactElement) => ReactNode;
@@ -15,5 +16,11 @@ export default function App({ Component, pageProps }: AppPropsWithLayout) {
   // Use the layout defined at the page level, if available
   const getLayout = Component.getLayout ?? ((page) => page);
 
-  return getLayout(<Component {...pageProps} />);
+  return (
+    <LazyMotion features={domAnimation}>
+      <AnimatePresence mode="wait" initial={false}>
+        {getLayout(<Component {...pageProps} />)}
+      </AnimatePresence>
+    </LazyMotion>
+  );
 }
diff --git a/pages/api/fakeRanking.ts b/pages/api/fakeRanking.ts
index 0b5731d..eb93f4d 100644
--- a/pages/api/fakeRanking.ts
+++ b/pages/api/fakeRanking.ts
@@ -9,6 +9,7 @@ export default async function handler(
   res: NextApiResponse<Data>
 ) {
   const sortBy = req.query.s ? (req.query.s as string) : undefined;
+  const sortAsc = req.query.a ? (req.query.a as string) : undefined;
 
   let data = fakeData;
   if (sortBy) {
@@ -25,6 +26,10 @@ export default async function handler(
     } else if (sortBy === "name") {
       data = data.sort((a, b) => a.name.localeCompare(b.name));
     }
+    if (sortAsc === "true") {
+      // slow but only needed for temporary fake data anyway
+      data = data.reverse();
+    }
   }
 
   res.status(200).json({ data });
@@ -48,7 +53,7 @@ const fakeData: fakeDataEntry[] = [
     points: 70, /// uninvested points
     shares: 20,
     dailyChange: -500,
-    dailyChangePercent: -0.523,
+    dailyChangePercent: -0.0498504486540378863409770687936,
   },
   {
     id: 1,
@@ -57,7 +62,7 @@ const fakeData: fakeDataEntry[] = [
     points: 10020,
     shares: 200,
     dailyChange: 5420,
-    dailyChangePercent: 0.14,
+    dailyChangePercent: 0.0379259673920649359736897347981,
   },
   {
     id: 2,
@@ -70,138 +75,138 @@ const fakeData: fakeDataEntry[] = [
   },
   {
     id: 3,
-    name: "SecondSock",
+    name: "SecondSockSan",
     netWorth: 153495,
     points: 15020,
     shares: 20,
-    dailyChange: 5432,
-    dailyChangePercent: 0.104,
+    dailyChange: -10432,
+    dailyChangePercent: -0.06796312583471774324896576435715,
   },
   {
     id: 0,
-    name: "Ente",
+    name: "e__n__t__e",
     netWorth: 429481824,
     points: 1002022,
     shares: 94214,
-    dailyChange: 3294444224,
-    dailyChangePercent: 0.94,
+    dailyChange: 329444422,
+    dailyChangePercent: 4.2932124926634939999741296760186,
   },
   {
     id: 5,
-    name: "ObnoxiouslyLongNameWICKED",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "luckytohavefoundyou14252",
+    netWorth: 8024,
+    points: 423,
+    shares: 4,
+    dailyChange: 9,
+    dailyChangePercent: 0.00112163509471585244267198404786,
   },
   {
     id: 6,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "ZeroxZerich",
+    netWorth: 842190,
+    points: 88542,
+    shares: 532,
+    dailyChange: -10219,
+    dailyChangePercent: -0.01213384153219582279533121979601,
   },
   {
     id: 7,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "joeeyo",
+    netWorth: 10000000,
+    points: 9999979,
+    shares: 1,
+    dailyChange: 1,
+    dailyChangePercent: 0.0000001,
   },
   {
     id: 8,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "dd_maru",
+    netWorth: 10328421,
+    points: 328421,
+    shares: 252,
+    dailyChange: 85192,
+    dailyChangePercent: 0.00824830823607984221402284047097,
   },
   {
     id: 9,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "Goldeneye128",
+    netWorth: 58292,
+    points: 6521,
+    shares: 63,
+    dailyChange: -1942,
+    dailyChangePercent: -0.03331503465312564331297605160228,
   },
   {
     id: 10,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "lilpastatv",
+    netWorth: 7328919,
+    points: 40,
+    shares: 93,
+    dailyChange: 921821,
+    dailyChangePercent: 0.12577857662228222197571019682439,
   },
   {
     id: 11,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "domiswitch",
+    netWorth: 43290,
+    points: 5002,
+    shares: 15,
+    dailyChange: 2429,
+    dailyChangePercent: 0.05610995610995610995610995610996,
   },
   {
     id: 12,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "minosura",
+    netWorth: 904328,
+    points: 32901,
+    shares: 83,
+    dailyChange: 94821,
+    dailyChangePercent: 0.10485244291894091524314186887943,
   },
   {
     id: 13,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "scienceteam_member",
+    netWorth: 34894,
+    points: 958,
+    shares: 5,
+    dailyChange: -7964,
+    dailyChangePercent: -0.22823408035765461110792686421734,
   },
   {
     id: 14,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "witchdev",
+    netWorth: 94382912,
+    points: 8532,
+    shares: 329,
+    dailyChange: -421,
+    dailyChangePercent: -0.0000044605531984433792422085896,
   },
   {
     id: 15,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "justone123879",
+    netWorth: 8889123,
+    points: 86333,
+    shares: 153,
+    dailyChange: 53289,
+    dailyChangePercent: 0.00599485461051669551653183334284,
   },
   {
     id: 16,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "marcelr_",
+    netWorth: 400329,
+    points: 39291,
+    shares: 52,
+    dailyChange: 1329,
+    dailyChangePercent: 0.00331976948959480827019776234047,
   },
   {
     id: 17,
-    name: "User",
-    netWorth: 0,
-    points: 100,
-    shares: 0,
-    dailyChange: 0,
-    dailyChangePercent: 0,
+    name: "fossabot",
+    netWorth: 20005,
+    points: 0,
+    shares: 1,
+    dailyChange: -31042,
+    dailyChangePercent: -1.5517120719820044988752811797051,
   },
 ];
 
diff --git a/pages/dashboard/index.tsx b/pages/dashboard/index.tsx
index 6595e0a..8ad0a5a 100644
--- a/pages/dashboard/index.tsx
+++ b/pages/dashboard/index.tsx
@@ -17,31 +17,31 @@ function Dashboard() {
         animate="animate"
       >
         <m.div
-          className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
+          className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3"
           variants={gridItemVariants}
         >
           1
         </m.div>
         <m.div
-          className="col-span-1 row-span-3 m-2 rounded-2xl bg-zinc-800 p-3 lg:col-span-3 lg:row-span-1"
+          className="col-span-1 row-span-3 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3 lg:col-span-3 lg:row-span-1"
           variants={gridItemVariants}
         >
           2
         </m.div>
         <m.div
-          className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
+          className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-80 p-3"
           variants={gridItemVariants}
         >
           3
         </m.div>
         <m.div
-          className="col-span-1 row-span-4 m-2 rounded-2xl bg-zinc-800 p-3 lg:col-span-4 lg:row-span-1"
+          className="col-span-1 row-span-4 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3 lg:col-span-4 lg:row-span-1"
           variants={gridItemVariants}
         >
           4
         </m.div>
         <m.div
-          className="col-span-1 m-2 rounded-2xl bg-zinc-800 p-3"
+          className="col-span-1 m-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3"
           variants={gridItemVariants}
         >
           5
diff --git a/pages/dashboard/ranking.tsx b/pages/dashboard/ranking.tsx
index 54ec832..13b8956 100644
--- a/pages/dashboard/ranking.tsx
+++ b/pages/dashboard/ranking.tsx
@@ -6,15 +6,75 @@ import { fakeDataEntry } from "../api/fakeRanking";
 
 function Ranking() {
   const [sortBy, setSortBy] = useState("netWorth");
+  const [sortAsc, setSortAsc] = useState(false);
   const [fakeData, setFakeData] = useState([]);
 
   useEffect(() => {
-    fetch(`/api/fakeRanking?s=${sortBy}`)
+    // fetch data from api on change to sort method
+    fetch(`/api/fakeRanking?s=${sortBy}&a=${sortAsc}`)
       .then((res) => res.json())
       .then((data) => {
         setFakeData(data.data);
       });
-  }, [sortBy]);
+  }, [sortBy, sortAsc]);
+
+  const SortSVG = (props: { sortType: string; children?: ReactElement }) => {
+    // if not current sort, return a line, otherwise return an arrow corresponding to sortAsc
+    if (sortBy != props.sortType) {
+      return (
+        <m.svg
+          className="ml-2"
+          origin="center"
+          width="15"
+          height="15"
+          viewBox="0 0 6 6"
+          x={0}
+          y={0}
+        >
+          <m.line
+            x1="1"
+            y1="3"
+            x2="5"
+            y2="3"
+            stroke="white"
+            stroke-linecap="round"
+          />
+        </m.svg>
+      );
+    }
+    return (
+      <m.svg
+        className="ml-2"
+        origin="center"
+        width="15"
+        height="15"
+        viewBox="0 0 330 330"
+        x={0}
+        y={0}
+        // if asc, rotate 180
+        animate={{ rotate: sortAsc ? 180 : 0 }}
+      >
+        <m.path
+          d="M325.607,79.393c-5.857-5.857-15.355-5.858-21.213,0.001l-139.39,139.393L25.607,79.393  c-5.857-5.857-15.355-5.858-21.213,0.001c-5.858,5.858-5.858,15.355,0,21.213l150.004,150c2.813,2.813,6.628,4.393,10.606,4.393  s7.794-1.581,10.606-4.394l149.996-150C331.465,94.749,331.465,85.251,325.607,79.393z"
+          fill="white"
+          stroke="white"
+          strokeWidth="15"
+          strokeLinecap="round"
+        />
+      </m.svg>
+    );
+  };
+
+  const setSortMethod = (sortType: string) => {
+    // if same sort, toggle asc
+    // a change in sort means asc should be false for intuitive behavior
+    if (sortBy == sortType) {
+      setSortAsc(!sortAsc);
+    } else {
+      setSortAsc(false);
+      setSortBy(sortType);
+    }
+  };
 
   return (
     <>
@@ -37,37 +97,64 @@ function Ranking() {
           </m.h1>
           {/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
           <m.div
-            className="text-md inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 backdrop-blur sm:text-xl"
+            className="text-md inline-grid w-full rounded-t-2xl bg-zinc-800 bg-opacity-70 p-3 pt-4 sm:text-xl"
             variants={rankingCardVariants}
             initial="initial"
             animate="animate"
           >
-            <m.div className="inline-grid w-full grid-flow-col grid-cols-[0.75fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-400 px-5 pb-3 text-right text-gray-300 md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
-              <m.h1 className="text-left md:text-center">#</m.h1>
-              <m.h1
-                className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left"
-                onClick={() => setSortBy("name")}
+            {/* Column names and arrows */}
+            <div className="inline-grid w-full grid-flow-col grid-cols-[0.75fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-400 px-5 pb-3 text-right text-gray-300 md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]">
+              <h1 className="text-left md:text-center">#</h1>
+              <div
+                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-start"
+                onClick={() => setSortMethod("name")}
               >
-                Name
-              </m.h1>
-              <m.h1 onClick={() => setSortBy("netWorth")}>Assets</m.h1>
-              <m.h1
-                className="hidden md:block"
-                onClick={() => setSortBy("points")}
+                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
+                  Name
+                </h1>
+                <SortSVG sortType="name" />
+              </div>
+              <div
+                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
+                onClick={() => setSortMethod("netWorth")}
               >
-                Points
-              </m.h1>
-              <m.h1
-                className="hidden md:block"
-                onClick={() => setSortBy("shares")}
+                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
+                  Assets
+                </h1>
+                <SortSVG sortType="netWorth" />
+              </div>
+              <div
+                className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
+                onClick={() => setSortMethod("points")}
               >
-                Shares
-              </m.h1>
-              <m.h1 onClick={() => setSortBy("dailyChange")}>Daily</m.h1>
-            </m.div>
+                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
+                  Points
+                </h1>
+                <SortSVG sortType="points" />
+              </div>
+              <div
+                className="pointer-events-auto hidden cursor-pointer flex-row items-center justify-end md:flex"
+                onClick={() => setSortMethod("shares")}
+              >
+                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
+                  Shares
+                </h1>
+                <SortSVG sortType="shares" />
+              </div>
+              <div
+                className="pointer-events-auto flex cursor-pointer flex-row items-center justify-end"
+                onClick={() => setSortMethod("dailyChange")}
+              >
+                <h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
+                  Daily
+                </h1>
+                <SortSVG sortType="dailyChange" />
+              </div>
+            </div>
             {
-              // TODO: add arrow to show which column is being sorted by and which direction
+              // generate table rows
               fakeData.map((entry: fakeDataEntry, index) => {
+                // if daily change is negative, make it red
                 let changeClass = " text-lime-500";
                 if (entry.dailyChangePercent < 0) {
                   changeClass = " text-red-500";
@@ -105,6 +192,7 @@ function Ranking() {
   );
 }
 
+// entire container page animation
 const containerVariants: Variants = {
   initial: {
     opacity: 1,
@@ -122,6 +210,7 @@ const containerVariants: Variants = {
   },
 };
 
+// header animation if needed
 const headerVariants: Variants = {
   initial: {
     opacity: 0,
@@ -140,6 +229,7 @@ const headerVariants: Variants = {
   },
 };
 
+// table container animation
 const rankingCardVariants: Variants = {
   initial: {
     opacity: 0,