mirror of
https://github.com/privacy-scaling-explorations/pse.dev.git
synced 2026-01-09 14:18:02 -05:00
cleanup site meta tags (#476)
This commit is contained in:
@@ -10,6 +10,12 @@ import { Divider } from "@/components/divider"
|
||||
import { Icons } from "@/components/icons"
|
||||
import { LABELS } from "@/app/labels"
|
||||
import { interpolate } from "@/lib/utils"
|
||||
import { Metadata } from "next"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "About",
|
||||
description: "About the Privacy & Scaling Explorations community",
|
||||
}
|
||||
|
||||
export default async function AboutPage() {
|
||||
const principles = LABELS.ABOUT_PAGE.PRINCIPLES
|
||||
|
||||
@@ -12,6 +12,7 @@ import { LABELS } from "../labels"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "404: Page Not Found",
|
||||
description: "The requested page could not be found",
|
||||
}
|
||||
|
||||
export default function NotFound() {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Metadata } from "next"
|
||||
|
||||
import { ProjectInterface } from "@/lib/types"
|
||||
import { ProjectContent } from "../sections/ProjectContent"
|
||||
import { getProjects, Project } from "@/lib/content"
|
||||
|
||||
type PageProps = {
|
||||
params: { id: string }
|
||||
@@ -12,18 +13,22 @@ export interface ProjectProps {
|
||||
project: ProjectInterface
|
||||
}
|
||||
|
||||
/*
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: PageProps): Promise<Metadata> {
|
||||
const response = await fetch("/api/projects")
|
||||
const projects = await response.json()
|
||||
|
||||
const projects = await getProjects()
|
||||
const project = projects.find(
|
||||
(p: ProjectInterface) =>
|
||||
(p: Project) =>
|
||||
String(p.id?.toLowerCase()) === params.id.toString().toLowerCase()
|
||||
)
|
||||
|
||||
|
||||
if (!project) {
|
||||
return {
|
||||
title: "Project Not Found",
|
||||
description: "The requested project could not be found",
|
||||
}
|
||||
}
|
||||
|
||||
const content = project?.content
|
||||
const imageUrl =
|
||||
(project?.image ?? "")?.length > 0
|
||||
@@ -43,7 +48,7 @@ export async function generateMetadata({
|
||||
],
|
||||
},
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
export default async function ProjectDetailPage({ params }: PageProps) {
|
||||
return <ProjectContent id={params?.id?.toLowerCase()} />
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
import Link from "next/link"
|
||||
|
||||
import { cn, interpolate } from "@/lib/utils"
|
||||
import { interpolate } from "@/lib/utils"
|
||||
import { siteConfig } from "@/config/site"
|
||||
import { LABELS } from "@/app/labels"
|
||||
|
||||
@@ -15,6 +12,13 @@ import { Button } from "@/components/ui/button"
|
||||
import { Label } from "@/components/ui/label"
|
||||
|
||||
import ResourcesContent from "@/content/resources.md"
|
||||
import { Metadata } from "next"
|
||||
import { ResourceNav } from "@/components/resources/ResourceNav"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Resources",
|
||||
description: "Resources for the Privacy & Scaling Explorations community",
|
||||
}
|
||||
|
||||
interface ResourceItemProps {
|
||||
label: string
|
||||
@@ -85,87 +89,6 @@ const ResourceCard = ({ id, title, children }: ResourceCardProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
const ResourceNav = () => {
|
||||
const SCROLL_OFFSET = 80
|
||||
const [activeId, setActiveId] = useState("")
|
||||
const [isManualScroll, setIsManualScroll] = useState(false)
|
||||
const ID_LABELS_MAPPING: Record<string, string> = {
|
||||
"get-involved": LABELS.RESOURCES_PAGE.NAV.GET_INVOLVED,
|
||||
learn: LABELS.RESOURCES_PAGE.NAV.LEARN,
|
||||
build: LABELS.RESOURCES_PAGE.NAV.BUILD,
|
||||
design: LABELS.RESOURCES_PAGE.NAV.DESIGN,
|
||||
}
|
||||
const sectionsRef = useRef<NodeListOf<HTMLElement> | null>(null) // sections are constant so useRef might be better here
|
||||
|
||||
useEffect(() => {
|
||||
if (sectionsRef.current === null)
|
||||
sectionsRef.current = document.querySelectorAll("div[data-section]")
|
||||
if (!activeId) setActiveId("get-involved")
|
||||
|
||||
const handleScroll = () => {
|
||||
if (isManualScroll) return
|
||||
|
||||
sectionsRef.current?.forEach((section: any) => {
|
||||
const sectionTop = section.offsetTop - SCROLL_OFFSET
|
||||
if (window.scrollY >= sectionTop && window.scrollY > 0) {
|
||||
setActiveId(section.getAttribute("id"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", handleScroll)
|
||||
return () => window.removeEventListener("scroll", handleScroll)
|
||||
}, [activeId, isManualScroll])
|
||||
|
||||
const scrollToId = useCallback((id: string) => {
|
||||
const element = document.getElementById(id)
|
||||
const top = element?.offsetTop ?? 0
|
||||
|
||||
if (element) {
|
||||
setActiveId(id) // active clicked id
|
||||
setIsManualScroll(true) // tell the window event listener to ignore this scrolling
|
||||
window?.scrollTo({
|
||||
behavior: "smooth",
|
||||
top: (top ?? 0) - SCROLL_OFFSET,
|
||||
})
|
||||
}
|
||||
|
||||
setTimeout(() => setIsManualScroll(false), 800)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 p-8">
|
||||
<div className="flex flex-col gap-4">
|
||||
<h6 className="font-display text-lg font-bold text-secondary dark:text-white">
|
||||
{LABELS.RESOURCES_PAGE.ON_THIS_PAGE}
|
||||
</h6>
|
||||
<ul className="text-normal font-sans text-primary">
|
||||
{Object.entries(ID_LABELS_MAPPING).map(([id, label]) => {
|
||||
const active = id === activeId
|
||||
return (
|
||||
<li
|
||||
key={id}
|
||||
onClick={() => {
|
||||
scrollToId(id)
|
||||
}}
|
||||
data-id={id}
|
||||
className={cn(
|
||||
"flex h-8 cursor-pointer items-center border-l-2 border-l-anakiwa-200 px-3 duration-200",
|
||||
{
|
||||
"border-l-anakiwa-500 text-anakiwa-500 font-medium": active,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function ResourcePage() {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
|
||||
@@ -54,8 +54,9 @@ export const viewport: Viewport = {
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
default: siteConfig.name,
|
||||
template: `%s | ${siteConfig.name}`,
|
||||
template: "%s | PSE",
|
||||
},
|
||||
metadataBase: new URL("https://pse.dev"),
|
||||
description: siteConfig.description,
|
||||
keywords: [
|
||||
"Privacy & Scaling Explorations",
|
||||
|
||||
86
components/resources/ResourceNav.tsx
Normal file
86
components/resources/ResourceNav.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
"use client"
|
||||
|
||||
import { LABELS } from "@/app/labels"
|
||||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export const ResourceNav = () => {
|
||||
const SCROLL_OFFSET = 80
|
||||
const [activeId, setActiveId] = useState("")
|
||||
const [isManualScroll, setIsManualScroll] = useState(false)
|
||||
const ID_LABELS_MAPPING: Record<string, string> = {
|
||||
"get-involved": LABELS.RESOURCES_PAGE.NAV.GET_INVOLVED,
|
||||
learn: LABELS.RESOURCES_PAGE.NAV.LEARN,
|
||||
build: LABELS.RESOURCES_PAGE.NAV.BUILD,
|
||||
design: LABELS.RESOURCES_PAGE.NAV.DESIGN,
|
||||
}
|
||||
const sectionsRef = useRef<NodeListOf<HTMLElement> | null>(null) // sections are constant so useRef might be better here
|
||||
|
||||
useEffect(() => {
|
||||
if (sectionsRef.current === null)
|
||||
sectionsRef.current = document.querySelectorAll("div[data-section]")
|
||||
if (!activeId) setActiveId("get-involved")
|
||||
|
||||
const handleScroll = () => {
|
||||
if (isManualScroll) return
|
||||
|
||||
sectionsRef.current?.forEach((section: any) => {
|
||||
const sectionTop = section.offsetTop - SCROLL_OFFSET
|
||||
if (window.scrollY >= sectionTop && window.scrollY > 0) {
|
||||
setActiveId(section.getAttribute("id"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener("scroll", handleScroll)
|
||||
return () => window.removeEventListener("scroll", handleScroll)
|
||||
}, [activeId, isManualScroll])
|
||||
|
||||
const scrollToId = useCallback((id: string) => {
|
||||
const element = document.getElementById(id)
|
||||
const top = element?.offsetTop ?? 0
|
||||
|
||||
if (element) {
|
||||
setActiveId(id) // active clicked id
|
||||
setIsManualScroll(true) // tell the window event listener to ignore this scrolling
|
||||
window?.scrollTo({
|
||||
behavior: "smooth",
|
||||
top: (top ?? 0) - SCROLL_OFFSET,
|
||||
})
|
||||
}
|
||||
|
||||
setTimeout(() => setIsManualScroll(false), 800)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 p-8">
|
||||
<div className="flex flex-col gap-4">
|
||||
<h6 className="font-display text-lg font-bold text-secondary dark:text-white">
|
||||
{LABELS.RESOURCES_PAGE.ON_THIS_PAGE}
|
||||
</h6>
|
||||
<ul className="text-normal font-sans text-primary">
|
||||
{Object.entries(ID_LABELS_MAPPING).map(([id, label]) => {
|
||||
const active = id === activeId
|
||||
return (
|
||||
<li
|
||||
key={id}
|
||||
onClick={() => {
|
||||
scrollToId(id)
|
||||
}}
|
||||
data-id={id}
|
||||
className={cn(
|
||||
"flex h-8 cursor-pointer items-center border-l-2 border-l-anakiwa-200 px-3 duration-200",
|
||||
{
|
||||
"border-l-anakiwa-500 text-anakiwa-500 font-medium": active,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
export type SiteConfig = typeof siteConfig
|
||||
|
||||
export const siteConfig = {
|
||||
name: "PSE",
|
||||
name: "Privacy & Scaling Explorations",
|
||||
description:
|
||||
"Enhancing Ethereum through cryptographic research and collective experimentation.",
|
||||
url: "https://pse.dev",
|
||||
|
||||
Reference in New Issue
Block a user