Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] added sitemaps, robots, og images, favicons/icons, and other metadata #128

Merged
merged 1 commit into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/(landing)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@heroicons/react/24/solid';

const titlingGothicFB = localFont({
src: './TitlingGothicFB.woff2',
src: '../fonts/TitlingGothicFB.woff2',
display: 'swap',
});

Expand Down
5 changes: 5 additions & 0 deletions app/(main)/compare/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {
import fetcher from '@/utils/fetcher';
import roundToTenth from '@/utils/round-to-tenth';
import { EllipsisVerticalIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Compare',
};

export default async function Page({
searchParams,
Expand Down
5 changes: 5 additions & 0 deletions app/(main)/courses/(page)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Card } from '@/components/atoms';
import { DepartmentsResponse } from '@/types/core/departments';
import { Metadata } from 'next';
import Link from 'next/link';

export const metadata: Metadata = {
title: 'Courses',
};

export default async function Page() {
const data: DepartmentsResponse = await fetch(
process.env.BASE_API_URL + '/core/departments',
Expand Down
11 changes: 11 additions & 0 deletions app/(main)/courses/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { BreadcrumbMenu } from '@/components/atoms';
import { Metadata } from 'next';
import Link from 'next/link';

export async function generateMetadata({
params,
}: {
params: { id: string };
}): Promise<Metadata> {
return {
title: `${params.id}`,
};
}

export default function Layout({
statistics,
schedules,
Expand Down
5 changes: 5 additions & 0 deletions app/(main)/courses/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { FilterGroup, PaginationBar } from '@/components/molecules';
import { CoursesSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { EllipsisVerticalIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { Metadata } from 'next';
import Link from 'next/link';

export const metadata: Metadata = {
title: 'Courses Search',
};

export default async function Page({
searchParams,
}: {
Expand Down
35 changes: 35 additions & 0 deletions app/(main)/courses/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CoursesSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { MetadataRoute } from 'next';

const sitemapLinksLimit = 50000;

export async function generateSitemaps() {
const { total_results } = (await fetcher(
process.env.BASE_API_URL + `/core/courses/search?`,
)) as CoursesSearchResponse;
const numberOfSitemaps = Math.ceil(total_results / sitemapLinksLimit);
return Array.from({ length: numberOfSitemaps }, (_, i) => ({
id: i,
}));
}

export default async function sitemap({
id,
}: {
id: number;
}): Promise<MetadataRoute.Sitemap> {
const requestParams = new URLSearchParams();
requestParams.append('limit', sitemapLinksLimit.toString());
requestParams.append('page', (id + 1).toString());
const { items } = (await fetcher(
process.env.BASE_API_URL +
`/core/courses/search?${requestParams.toString()}`,
)) as CoursesSearchResponse;
return items.map((course) => ({
url: `${process.env.NEXT_PUBLIC_BASE_URL}/courses/${course.department}-${course.course_number}`,
lastModified: new Date().toISOString(),
changeFrequency: 'monthly',
priority: 0.6,
}));
}
5 changes: 5 additions & 0 deletions app/(main)/professors/(page)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { LastNameDisplay } from '@/app/(main)/professors/(page)/lastname';
import SWRConfigProvider from '@/wrappers/swr-config';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Professors',
};

export default function Page() {
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
Expand Down
Binary file added app/(main)/professors/[id]/Inter_24pt-Bold.ttf
Binary file not shown.
Binary file not shown.
Binary file added app/(main)/professors/[id]/Inter_24pt-Italic.ttf
Binary file not shown.
12 changes: 12 additions & 0 deletions app/(main)/professors/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { BreadcrumbMenu } from '@/components/atoms';
import { formatName } from '@/utils/format-name';
import { Metadata } from 'next';
import Link from 'next/link';

export async function generateMetadata({
params,
}: {
params: { id: string };
}): Promise<Metadata> {
return {
title: `${formatName(params.id)}`,
};
}

export default function Layout({
statistics,
schedules,
Expand Down
5 changes: 5 additions & 0 deletions app/(main)/professors/[id]/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
131 changes: 131 additions & 0 deletions app/(main)/professors/[id]/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import {
ProfessorsIDReviewStatsResponse,
ProfessorsIDSummaryResponse,
} from '@/types';
import fetcher from '@/utils/fetcher';
import roundToTenth from '@/utils/round-to-tenth';
import { ImageResponse } from 'next/og';

export const runtime = 'edge';

export const alt = 'Professor Page';
export const size = {
width: 1200,
height: 630,
};

export const contentType = 'image/png';

export default async function Image({ params }: { params: { id: string } }) {
const { name } = (await fetcher(
process.env.BASE_API_URL + `/core/professors/${params.id}/summary`,
)) as ProfessorsIDSummaryResponse;
const { avg_rating, total_reviews } = (await fetcher(
process.env.BASE_API_URL + `/core/professors/${params.id}/reviews-stats`,
)) as ProfessorsIDReviewStatsResponse;
const review = roundToTenth(avg_rating ?? 0);

const interItalic = fetch(
new URL('./Inter_24pt-Italic.ttf', import.meta.url),
).then((res) => res.arrayBuffer());
const interBold = fetch(
new URL('./Inter_24pt-Bold.ttf', import.meta.url),
).then((res) => res.arrayBuffer());
const interExtraBold = fetch(
new URL('./Inter_24pt-ExtraBold.ttf', import.meta.url),
).then((res) => res.arrayBuffer());

return new ImageResponse(
(
<div tw="flex justify-stretch bg-[#1e1e1e] text-[#f0f0f0] w-full h-full gap-[16px] items-start">
<p tw="text-[1.5rem] p-[64px] leading-[1.15em] text-[#1e1e1e]">
{total_reviews} Reviews
</p>
<div tw="flex flex-1 flex-col items-center h-full justify-center py-[16px]">
<svg
width="108"
height="46"
viewBox="0 0 54 23"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{ marginBottom: '8px' }}
>
<path
d="M14.9465 14.023C14.9465 15.6514 14.3291 17.1345 13.3131 18.2417C12.1934 19.4784 10.5882 20.2512 8.80717 20.2512C7.02616 20.2512 5.41677 19.4795 4.29606 18.2417C3.28731 17.1345 2.66992 15.6514 2.66992 14.023C2.66992 10.5888 5.422 7.79688 8.80717 7.79688C12.1923 7.79688 14.9465 10.5888 14.9465 14.023Z"
fill="#F1B947"
/>
<path
d="M42.3308 0C37.4555 0 33.3013 3.11996 31.6992 7.49894C31.3811 7.37792 31.0577 7.27388 30.7396 7.17622C29.4421 6.78875 28.1142 6.59342 26.7726 6.59342C25.4311 6.59342 24.1053 6.78769 22.8078 7.17622C22.5242 7.26433 22.2364 7.35563 21.9518 7.46072C20.3403 3.10297 16.1954 0 11.3359 0C5.07513 0 0 5.14862 0 11.5C0 17.8514 5.07513 23 11.3359 23C12.1563 23 12.9568 22.9119 13.7269 22.742C17.8844 21.8386 21.1952 18.621 22.2866 14.483C22.4541 13.8482 22.5702 13.1911 22.6278 12.517C22.9051 12.0255 23.332 11.6497 23.8427 11.4745C24.7939 11.1486 25.7754 10.9798 26.7726 10.9798C27.7699 10.9798 28.7535 11.1486 29.7047 11.4745C30.321 11.6847 30.8171 12.1921 31.0734 12.8365C31.1153 13.2229 31.1791 13.603 31.2607 13.9777C32.1983 18.3121 35.5458 21.7314 39.8079 22.7134C40.6189 22.9013 41.4633 22.9989 42.3319 22.9989C48.5926 22.9989 53.6677 17.8503 53.6677 11.4989C53.6677 5.14756 48.5905 0 42.3308 0ZM15.8428 15.7187C14.7231 16.9554 13.1179 17.7282 11.3369 17.7282C9.5559 17.7282 7.94651 16.9565 6.82579 15.7187C5.81705 14.6115 5.19966 13.1284 5.19966 11.5C5.19966 8.06582 7.95174 5.27389 11.3369 5.27389C14.7221 5.27389 17.4763 8.06582 17.4763 11.5C17.4763 13.1284 16.8589 14.6115 15.8428 15.7187ZM37.7025 15.7187C36.6875 14.6115 36.069 13.1284 36.069 11.5C36.069 8.06582 38.8263 5.27389 42.2063 5.27389C45.5862 5.27389 48.3456 8.06582 48.3456 11.5C48.3456 13.1284 47.7282 14.6115 46.7174 15.7187C45.5977 16.9554 43.9873 17.7282 42.2063 17.7282C40.4253 17.7282 38.8211 16.9565 37.7014 15.7187H37.7025Z"
fill="#F1B947"
/>
<path
d="M45.8189 14.023C45.8189 15.6514 45.2015 17.1345 44.1907 18.2417C43.071 19.4784 41.4606 20.2512 39.6796 20.2512C37.8986 20.2512 36.2944 19.4795 35.1747 18.2417C34.1597 17.1345 33.5413 15.6514 33.5413 14.023C33.5413 10.5888 36.2986 7.79688 39.6785 7.79688C43.0584 7.79688 45.8179 10.5888 45.8179 14.023H45.8189Z"
fill="#F1B947"
/>
</svg>
<p
style={{ fontFamily: 'Inter-Bold', fontWeight: 700 }}
tw="text-center text-[4rem] leading-[1.15em]"
>
{name}
</p>
{review ? (
<p
style={{ fontFamily: 'Inter-ExtraBold', fontWeight: 800 }}
tw="text-center flex items-center text-[8.5rem]"
>
{review}
<span
style={{
fontFamily: 'Inter-Italic',
fontStyle: 'italic',
fontWeight: 400,
}}
tw="leading-[1.15em] text-[5rem]"
>
/5
</span>
</p>
) : (
<p
style={{
fontFamily: 'Inter-Italic',
fontStyle: 'italic',
fontWeight: 400,
}}
tw="text-center text-[1rem] leading-[1.15em] text-[#8b8b8b] opacity-50"
>
No reviews. Be the first to write one!
</p>
)}
</div>
<p tw="text-[1.5rem] p-[64px] leading-[1.15em] text-[#8b8b8b]">
{total_reviews} Reviews
</p>
</div>
),
{
...size,
fonts: [
{
name: 'Inter-Italic',
data: await interItalic,
style: 'italic',
weight: 400,
},
{
name: 'Inter-Bold',
data: await interBold,
style: 'normal',
weight: 700,
},
{
name: 'Inter-ExtraBold',
data: await interExtraBold,
style: 'normal',
weight: 800,
},
],
},
);
}
12 changes: 12 additions & 0 deletions app/(main)/professors/review/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ import { Btn, Card, Select, Tag, Textarea } from '@/components/atoms';
import { FilterGroup, SearchBar } from '@/components/molecules';
import { CoursesSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { formatName } from '@/utils/format-name';
import { getServerSession } from '@/utils/get-server-session';
import { Metadata } from 'next';
import { redirect } from 'next/navigation';

export async function generateMetadata({
searchParams,
}: {
searchParams: { professor_id: string };
}): Promise<Metadata> {
return {
title: `Review ${formatName(searchParams.professor_id)}`,
};
}

export default async function Page({
searchParams,
}: {
Expand Down
5 changes: 5 additions & 0 deletions app/(main)/professors/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { FilterGroup, PaginationBar } from '@/components/molecules';
import { ProfessorsSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { EllipsisVerticalIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { Metadata } from 'next';
import Link from 'next/link';

export const metadata: Metadata = {
title: 'Professors Search',
};

export default async function Page({
searchParams,
}: {
Expand Down
35 changes: 35 additions & 0 deletions app/(main)/professors/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ProfessorsSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { MetadataRoute } from 'next';

const sitemapLinksLimit = 50000;

export async function generateSitemaps() {
const { total_results } = (await fetcher(
process.env.BASE_API_URL + `/core/professors/search?`,
)) as ProfessorsSearchResponse;
const numberOfSitemaps = Math.ceil(total_results / sitemapLinksLimit);
return Array.from({ length: numberOfSitemaps }, (_, i) => ({
id: i,
}));
}

export default async function sitemap({
id,
}: {
id: number;
}): Promise<MetadataRoute.Sitemap> {
const requestParams = new URLSearchParams();
requestParams.append('limit', sitemapLinksLimit.toString());
requestParams.append('page', (id + 1).toString());
const { items } = (await fetcher(
process.env.BASE_API_URL +
`/core/professors/search?${requestParams.toString()}`,
)) as ProfessorsSearchResponse;
return items.map((professor) => ({
url: `${process.env.NEXT_PUBLIC_BASE_URL}/professors/${professor.id}`,
lastModified: new Date().toISOString(),
changeFrequency: 'monthly',
priority: 0.6,
}));
}
5 changes: 5 additions & 0 deletions app/(main)/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import { ParamSelect } from '@/components/molecules';
import { Review } from '@/components/organisms';
import { UsersProfileResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { Metadata } from 'next';
import { cookies } from 'next/headers';

export const metadata: Metadata = {
title: 'My Profile',
};

export default async function Page({
searchParams,
}: {
Expand Down
5 changes: 5 additions & 0 deletions app/(main)/schedules/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { Schedule } from '@/components/organisms';
import { SchedulesSearchResponse } from '@/types';
import fetcher from '@/utils/fetcher';
import { EllipsisVerticalIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Schedules Search',
};

export default async function Page({
searchParams,
Expand Down
Binary file added app/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/favicon-48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/favicon.ico
Binary file not shown.
7 changes: 7 additions & 0 deletions app/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
Loading
Loading