File size: 2,865 Bytes
7a85021
 
85181c4
7a85021
22932a5
7a85021
 
6c9b36e
7a85021
 
 
7fc47b1
 
7a85021
fdb7c58
 
7a85021
7fc47b1
c608763
 
7fc47b1
 
 
 
c608763
ab1abdd
c608763
22932a5
 
 
 
 
 
 
 
 
 
 
 
929d75e
22932a5
 
 
 
 
 
 
 
 
 
 
85181c4
22932a5
 
 
 
 
 
 
929d75e
ab1abdd
22932a5
 
 
 
 
 
ab1abdd
03b5e31
c07926b
7a85021
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7fc47b1
7a85021
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;