File size: 2,865 Bytes
6ee3edd
 
6580e54
6ee3edd
a14caa5
6ee3edd
 
b17ac62
6ee3edd
 
 
17388ad
 
6ee3edd
22aa376
 
6ee3edd
17388ad
633e5e5
 
17388ad
 
 
 
633e5e5
55d7c10
633e5e5
a14caa5
 
 
 
 
 
 
 
 
 
 
 
a6d1411
a14caa5
 
 
 
 
 
 
 
 
 
 
6580e54
a14caa5
 
 
 
 
 
 
a6d1411
55d7c10
a14caa5
 
 
 
 
 
55d7c10
428d2d6
5e26aa6
6ee3edd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17388ad
6ee3edd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import React, { useState, useEffect } from "react";
import { ProviderInfo, ModelData, CalendarData } from "../types/heatmap";
import OrganizationButton from "../components/OrganizationButton";
import HeatmapGrid from "../components/HeatmapGrid";
import Navbar from "../components/Navbar";
import { getProviders } from "../utils/ranking";
import { ORGANIZATIONS } from "../constants/organizations";

interface PageProps {
  calendarData: CalendarData;
  providers: ProviderInfo[];
}

function Page({
  calendarData,
  providers,
}: PageProps) {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    if (calendarData && Object.keys(calendarData).length > 0) {
      setIsLoading(false);
    }
  }, [calendarData]);


  return (
    <div className="w-full">
      <Navbar />
      
      <div className="w-full p-4 py-16">
        <div className="text-center mb-16 max-w-4xl mx-auto">
          <h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-6xl font-bold text-foreground mb-6 bg-gradient-to-r from-foreground to-foreground/80 bg-clip-text">
            <span className="inline-flex items-center gap-1 sm:gap-2">
              Hugging Face Heatmap
              <img
                src="/hf-icon.svg"
                alt="Hugging Face icon"
                className="size-6 sm:size-8 md:size-10"
              />
            </span>
          </h1>
          <p className="text-base sm:text-lg lg:text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed px-4">
            Open models, datasets, and apps from popular AI labs in the last year.
          </p>
        </div>

        <div className="mb-16 mx-auto">
          <div className="overflow-x-auto scrollbar-hide">
            <div className="flex gap-6 px-4 py-2 min-w-max justify-center">
              {providers.map((provider, index) => (
                <OrganizationButton
                  key={provider.fullName || provider.authors[0]}
                  provider={provider}
                  calendarData={calendarData}
                  rank={index + 1}
                />
              ))}
            </div>
          </div>
        </div>
             
        <HeatmapGrid 
          sortedProviders={providers}
          calendarData={calendarData}
          isLoading={isLoading}
        />
      </div>
    </div>
  );
}


export async function getStaticProps() {
  try {
    const { calendarData, providers } = await getProviders(ORGANIZATIONS);

    return {
      props: {
        calendarData,
        providers,
      },
      revalidate: 3600, // regenerate every hour
    };
  } catch (error) {
    console.error("Error fetching data:", error);
    return {
      props: {
        calendarData: {},
        providers: ORGANIZATIONS,
      },
      revalidate: 60, // retry after 1 minute if there was an error
    };
  }
}

export default Page;