diff --git a/app/layout.tsx b/app/layout.tsx index 3ec4282..ac4865c 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -3,10 +3,11 @@ import { Metadata } from "next" import { siteConfig } from "@/config/site" import { fontDisplay, fontSans } from "@/lib/fonts" -import { cn } from "@/lib/utils" +import { SiteFooter } from "@/components/site-footer" import { SiteHeader } from "@/components/site-header" import { TailwindIndicator } from "@/components/tailwind-indicator" -import { ThemeProvider } from "@/components/theme-provider" + +// import { ThemeProvider } from "@/components/theme-provider" export const metadata: Metadata = { title: { @@ -19,8 +20,8 @@ export const metadata: Metadata = { { media: "(prefers-color-scheme: dark)", color: "black" }, ], icons: { - icon: "/favicon.ico", - shortcut: "/favicon-16x16.png", + icon: "/favicon.svg", + shortcut: "/favicon.svg", apple: "/apple-touch-icon.png", }, } @@ -32,22 +33,19 @@ interface RootLayoutProps { export default function RootLayout({ children }: RootLayoutProps) { return ( <> - + - - -
- -
{children}
-
- -
+ +
+ +
{children}
+ +
+ diff --git a/app/page.tsx b/app/page.tsx index c9a7677..cdf9d6c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,38 +1,187 @@ +import Image from "next/image" import Link from "next/link" +import PSELogo from "@/public/icons/archstar.webp" +import ArrowRightVector from "@/public/icons/arrow-right.svg" +import PSEIcon1 from "@/public/icons/pseicon1.svg" +import PSEIcon2 from "@/public/icons/pseicon2.svg" +import PSEIcon3 from "@/public/icons/pseicon3.svg" import { siteConfig } from "@/config/site" -import { buttonVariants } from "@/components/ui/button" +import WhatWeDo from "@/components/sections/WhatWeDo" +import { ArrowRightUp } from "@/components/svgs/arrows" export default function IndexPage() { return ( -
-
-

- Our new website
- built with Radix UI and Tailwind CSS. -

-

- Accessible and customizable components that you can copy and paste - into your apps. Free. Open Source. And Next.js 13 Ready. -

+
+
+
+
+ Privacy + Scaling Explorations +
+

+ Programmable cryptography for people like you +

+ + +

+ Explore The Project Library +

+ arrowvector + + +
+
+ pselogo +
-
- - Documentation - - - GitHub - + +
+
+
+
+ pseicon1 +

+ Learn and Share +

+
+

+ Diving into Plonk accumulation via aPlonk by Ralph Toledo +

+
+ +

+ Watch +

+ + +
+
+
+
+ pseicon1 +

+ Learn and Share +

+
+

+ Folding Circom Circuit: A ZKML Case Study - Dr. Cathie So +

+
+ +

+ Watch +

+ + +
+
+
+
+ pseicon1 +

+ Event +

+
+

PSE @ETH Global Paris

+
+ +

+ Attend +

+ + +
+
+
+
+ pseicon1 +

+ Blog Post +

+
+

+ zkEVM Community Edition Part 3: Logic and Structure +

+
+ +

+ read +

+ + +
+
+ +
+
+

+ Who we are +

+
+

+ PSE is a research lab building free tools that expand the world of + cryptography. +

+
+
+ + + +
+

+ how to plug in +

+
+

+ PSE is a growing team of developers, researchers, designers, + communicators, artists, and organizers. There are so many ways to + get involved- you can try out our apps, build with our tools, + contribute to projects, or join our team. We’d love to hear from + you! +

+
+ +
+ Say Hi On Discord +
+ + +
+
) diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx new file mode 100644 index 0000000..e1ade5a --- /dev/null +++ b/app/projects/[id]/page.tsx @@ -0,0 +1,136 @@ +"use client" + +import NextImage from "next/image" +import NextLink from "next/link" +import { usePathname } from "next/navigation" +import GithubVector from "@/public/social-medias/github-fill.svg" +import GlobalVector from "@/public/social-medias/global-line.svg" +import TwitterVector from "@/public/social-medias/twitter-fill.svg" + +import { projects } from "@/config/projects" +import Breadcrumbs from "@/components/breadcrumbs" + +export default function ProjectDetailPage() { + const router = usePathname() + + const breadcrumbs = router + .split("/") + .slice(1) + .map((part) => { + const id = Number(part) + + if (!isNaN(id)) { + const project = projects.find((project) => project.id === id) + + return project ? project.name : part + } else { + return part + } + }) + + const findProject = projects.filter( + (project) => String(project.id) === router.split("/").slice(1)[1] + )[0] + + const githubLink = findProject.links.github + const twitterLink = findProject.links.twitter + const websiteLink = findProject.links.website + + return ( +
+
+
+ +

+ {findProject.name} +

+
+ {githubLink !== "none" && ( + +
+ +

Github

+
+
+ )} + {websiteLink !== "none" && ( + +
+ +

Website

+
+
+ )} + {twitterLink !== "none" && ( + +
+ +

Twitter

+
+
+ )} +
+

{findProject.tldr}

+
+
+
+ {findProject.image ? ( +
+ +
+ ) : ( +
+ )} +
+

+ {`RLN is a protocol that allows one user to punish another user who is + abusing the rate limit in an anonymous system. Users can withdraw + the offender's stake or reveal their secrets, helping to maintain + system integrity via deterrence. RLN is built using the Semaphore + protocol.`} +

+

+ {`This project is aimed at developers looking to stop spam while + preserving anonymity within a system. If you're working on + communication systems such as chat apps, client-server + communications, or peer-to-peer communications, RLN can help you + maintain privacy and anonymity while preventing abuse in the form of + spam and denial of service attacks. This ensures a safer and more + enjoyable user experience for your application's users.`} +

+
+
+
+ ) +} diff --git a/app/projects/page.tsx b/app/projects/page.tsx new file mode 100644 index 0000000..d74297f --- /dev/null +++ b/app/projects/page.tsx @@ -0,0 +1,90 @@ +"use client" + +import NextImage from "next/image" +import NextLink from "next/link" +import { useRouter } from "next/navigation" +import GithubVector from "@/public/social-medias/github-fill.svg" +import GlobalVector from "@/public/social-medias/global-line.svg" + +import { projects } from "@/config/projects" + +export default function ProjectsPage() { + const router = useRouter() + + return ( +
+
+
+

+ Explore the project library +

+

+ PSE is home to many projects, from cryptography research to + developer tools, protocols and proof-of-concept applications. +

+
+
+
+

Showing 24 projects

+
+ {projects.map((item, index) => { + return ( +
router.push(`/projects/${item.id}`)} + className="flex h-full w-full cursor-pointer flex-col md:h-[500px]" + > +
+ {item.image.length > 0 ? ( + + ) : ( +
+ )} +
+
+

{item.name}

+

{item.tldr}

+
e.stopPropagation()} + > + + + + + + +
+
+
+ ) + })} +
+
+
+ ) +} diff --git a/components/breadcrumbs.tsx b/components/breadcrumbs.tsx new file mode 100644 index 0000000..1ad4962 --- /dev/null +++ b/components/breadcrumbs.tsx @@ -0,0 +1,30 @@ +import NextLink from "next/link" + +interface Props { + path: string[] +} + +const Breadcrumbs = ({ path }: Props) => { + return ( +
+ {path.map((item, index) => { + const isLastItem = index === path.length - 1 + if (isLastItem) { + return ( +

+ {item} +

+ ) + } + return ( + + {item === "projects" ? "All Projects" : item} + / + + ) + })} +
+ ) +} + +export default Breadcrumbs diff --git a/components/main-nav.tsx b/components/main-nav.tsx index 64e87a2..55ce82f 100644 --- a/components/main-nav.tsx +++ b/components/main-nav.tsx @@ -1,41 +1,43 @@ -import * as React from "react" +"use client" + +import NextImage from "next/image" import Link from "next/link" +import { usePathname } from "next/navigation" +import PSELogo from "@/public/logos/header-logo.svg" import { NavItem } from "@/types/nav" -import { siteConfig } from "@/config/site" -import { cn } from "@/lib/utils" -import { Icons } from "@/components/icons" interface MainNavProps { - items?: NavItem[] + items: NavItem[] } export function MainNav({ items }: MainNavProps) { + const router = usePathname() + return (
- - {siteConfig.name} + - {items?.length ? ( - - ) : null} +
) } diff --git a/components/sections/WhatWeDo.tsx b/components/sections/WhatWeDo.tsx new file mode 100644 index 0000000..4b4e1e8 --- /dev/null +++ b/components/sections/WhatWeDo.tsx @@ -0,0 +1,227 @@ +"use client" + +import { cn } from "@/lib/utils" + +const content = [ + { + title: "Privacy", + description: + "We believe privacy is a social good that should be accessible to everyone. That's why we're creating open source tools that help people choose what, how, when, and where they share.", + className: "privacyDesc", + }, + { + title: "Scaling", + description: + "Our infrastructure helps communities grow by making Ethereum more efficient and accessible. From account abstraction and reducing transaction costs, to rollups and zkEVM, we are building towards an interoperable future.", + className: "scalingDesc", + }, + { + title: "Explorations", + description: + "We are mapping the emerging zero knowledge ecosystem through collective experimentation. We collaborate, share what we learn, and welcome contributions from around the world.", + className: "explorationsDesc", + }, +] + +const WhatWeDo = () => { + // useEffect(() => { + // const mm = gsap.matchMedia() + + // mm.add("(min-width: 1024px)", () => { + // gsap.registerPlugin(ScrollTrigger) + // const tl = gsap.timeline({ + // scrollTrigger: { + // trigger: ".badge-start-trigger", + // start: "top center", + // end: "+=550", + // scrub: 1, + // // markers: true, + // }, + // }) + + // tl.from("#privacy", { fill: "#E1523A" }, "+=0.5") + // .to(".badge-right", { y: 50, ease: "ease-out" }, "+=1") + // .to("#privacy", { fill: "#111827", ease: "ease-out" }, "+=0.5") + // .to(".badge-right", { y: 100, ease: "ease-out" }) + // .to("#scaling", { fill: "#E1523A", ease: "ease-in" }) + // .to(".badge-right", { y: 250, ease: "ease-out" }, "+=1") + // .to(".badge-right", { y: 350, ease: "ease-out" }) + // .to("#scaling", { fill: "#111827", ease: "ease-out" }) + // .to("#explorations", { fill: "#E1523A", ease: "ease-in" }) + // .to(".badge-right", { y: 550, ease: "ease-out" }) + // }) + // }, []) + + return ( +
+

+ What we do +

+
+ {content.map((item, index) => ( +
+

{item.title}

+
+

{item.description}

+
+ ))} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ) +} + +export default WhatWeDo diff --git a/components/site-footer.tsx b/components/site-footer.tsx new file mode 100644 index 0000000..4b37775 --- /dev/null +++ b/components/site-footer.tsx @@ -0,0 +1,85 @@ +import NextImage from "next/image" +import NextLink from "next/link" +import PSELogo from "@/public/logos/footer-logo.svg" + +import { siteConfig } from "@/config/site" +import { + Discord, + Github, + Mirror, + Twitter, +} from "@/components/svgs/social-medias" + +import { ArrowRightUp } from "./svgs/arrows" + +export function SiteFooter() { + return ( +
+
+ +

+ Privacy + Scaling Explorations is a multidisciplinary team supported + by the Ethereum Foundation. +

+
+
+ + HOME + + + PROJECT LIBRARY + + + JOBS + + +
+
+
+ + + + + + + + + + + + + +
+
+

Privacy Policy

+

Terms of use

+
+

Last updated June 8, 2023

+
+
+ ) +} diff --git a/components/site-header-mobile.tsx b/components/site-header-mobile.tsx new file mode 100644 index 0000000..e7bea2a --- /dev/null +++ b/components/site-header-mobile.tsx @@ -0,0 +1,116 @@ +"use client" + +import { useState } from "react" +import NextImage from "next/image" +import NextLink from "next/link" +import ArrowVector from "@/public/icons/arrow-right-up.svg" +import CloseVector from "@/public/icons/close-fill.svg" +import HeaderVector from "@/public/icons/menu-burger.svg" + +import { siteConfig } from "@/config/site" +import { + Discord, + Github, + Mirror, + Twitter, +} from "@/components/svgs/social-medias" + +export function SiteHeaderMobile() { + const [header, setHeader] = useState(false) + + return ( +
+ setHeader(true)} + width={24} + height={24} + /> + {header && ( +
setHeader(false)} + >
+ )} + {header && ( +
+
+ setHeader(false)} + width={24} + height={24} + /> +
+
+ setHeader(false)} + className="border-y-2 border-white p-[16px]" + > + HOME + + setHeader(false)} + href={"/projects"} + className="border-b-2 border-white p-[16px] pt-0" + > + PROJECT LIBRARY + + + JOBS + + +
+
+
+ + {" "} + + + + {" "} + + + {" "} + + + {" "} + +
+
+

Privacy Policy

+

Terms of use

+
+

Last updated June 8, 2023

+
+
+ )} +
+ ) +} diff --git a/components/site-header.tsx b/components/site-header.tsx index c4bcffa..116ecee 100644 --- a/components/site-header.tsx +++ b/components/site-header.tsx @@ -1,49 +1,52 @@ import Link from "next/link" import { siteConfig } from "@/config/site" -import { buttonVariants } from "@/components/ui/button" -import { Icons } from "@/components/icons" import { MainNav } from "@/components/main-nav" -import { ThemeToggle } from "@/components/theme-toggle" +import { + Discord, + Github, + Mirror, + Twitter, +} from "@/components/svgs/social-medias" + +import { SiteHeaderMobile } from "./site-header-mobile" export function SiteHeader() { return ( -
-
+
+
-
-
diff --git a/components/svgs/arrows.tsx b/components/svgs/arrows.tsx new file mode 100644 index 0000000..cc4f155 --- /dev/null +++ b/components/svgs/arrows.tsx @@ -0,0 +1,30 @@ +import React from "react" + +interface MySvgProps { + color: "white" | "black" +} + +export const ArrowRightUp = ({ color }: MySvgProps) => { + return ( + + + + + + + + + + + ) +} diff --git a/components/svgs/social-medias.tsx b/components/svgs/social-medias.tsx new file mode 100644 index 0000000..c5be8a0 --- /dev/null +++ b/components/svgs/social-medias.tsx @@ -0,0 +1,137 @@ +import React from "react" + +interface MySvgProps { + color: string +} + +export const Github = ({ color }: MySvgProps) => { + return ( + + + + + + ) +} + +export const Global = ({ color }: MySvgProps) => { + return ( + + + + + + + + + + + ) +} + +export const Discord = ({ color }: MySvgProps) => { + return ( + + + + + + + + + ) +} + +export const Twitter = ({ color }: MySvgProps) => { + return ( + + + + + + ) +} + +export const Mirror = ({ color }: MySvgProps) => { + return ( + + + + + + + + + + + + + ) +} diff --git a/config/projects.ts b/config/projects.ts new file mode 100644 index 0000000..413267b --- /dev/null +++ b/config/projects.ts @@ -0,0 +1,426 @@ +export const projects = [ + { + id: 1, + image: "rlnlogo.webp", + name: "Rate-Limiting Nullifier", + tldr: "A protocol for deterring spam and maintaining anonymity in communication systems.", + description: + "Rate-Limiting Nullifier (RLN) is a protocol designed to combat spam and denial of service attacks in privacy-preserving environments. It allows users in an anonymous system to penalize those who exceed the rate limit, either by withdrawing the offender's stake or revealing their secrets. This mechanism helps maintain system integrity and deters abuse. RLN is built on the Semaphore protocol and uses zero-knowledge proofs and the Shamir’s Secret Sharing scheme to reveal the spammer's private key. It's particularly useful for developers working on communication systems that require privacy and anonymity, such as chat apps, client-server communications, and peer-to-peer communications. It's already being used in projects like Zerokit and Waku, and is also being developed for use with the KZG polynomial commitment scheme.", + links: { + github: "https://github.com/Rate-Limiting-Nullifier/circom-rln", + website: "https://rate-limiting-nullifier.github.io/rln-docs/", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy"], + types: ["Infrastructure/protocol"], + builtWith: ["Circom", "Solidity", "Semaphore"], + }, + }, + { + id: 2, + image: "zkitterlogo.webp", + name: "Zkitter", + tldr: "A decentralized social network prioritizing privacy and anonymity", + description: + "Zkitter is a decentralized social network that emphasizes privacy by default. It allows users to share thoughts and communicate in various modes: as known identities, as a member of a group, or entirely anonymously. Built with Semaphore and RLN, Zkitter offers familiar social media features such as posting, chatting, following, and liking, but with a strong focus on user privacy and anonymity. It serves as an experiment to explore new ways of engaging in conversations without the fear of damaging one’s personal reputation and is an example of a user-facing application using zero-knowledge primitives such as Semaphore, CryptKeeper, ZK-Chat, and Interep. Users can sign up using an Ethereum address or ENS name, or create an anonymous account, with options for anonymous chat and posting.", + links: { + github: "https://github.com/zkitter", + website: "https://www.zkitter.com/explore/", + twitter: "none", + discord: "https://discord.gg/Em4Z9yE8eW", + }, + + tags: { + themes: ["Anonymity/privacy", "Social", "Identity"], + types: ["Application", "Infrastructure/protocol"], + builtWith: ["Semaphore", "RLN", "Interep", "zkchat"], + }, + }, + { + id: 3, + image: "macilogo.webp", + name: "MACI", + tldr: "A secure e-voting solution minimizing the risk of collusion and bribery", + description: + "Minimal Anti-Collusion Infrastructure (MACI) is a protocol designed to provide a highly secure e-voting solution. It enables organizations to conduct on-chain voting processes with a significantly reduced risk of cheating, such as bribery or collusion. MACI uses zero-knowledge proofs to implement a receipt-free voting scheme, making it impossible for anyone other than the vote coordinator to verify how a specific user voted. This ensures the correct execution of votes and allows anyone to verify the results. It's particularly beneficial for governance and funding events, where its anti-collusion mechanisms help ensure fair and transparent outcomes.", + links: { + github: "https://github.com/privacy-scaling-explorations/maci", + + website: + "https://mirror.xyz/privacy-scaling-explorations.eth/ltCt68hslI5jmMf1AnfkrP2eUwkeZ8_fgkHc_WyD9Nc", + + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Voting/governance"], + types: ["Lego sets/toolkits", "Infrastructure/protocol"], + builtWith: ["P0tion", "JubjubLib"], + }, + }, + { + id: 4, + image: "waxlogo.webp", + name: "WAX: Wallet Account eXperiments", + tldr: "Streamlining web3 product development with smart account components for enhanced wallets, dApps, and SDKs.", + description: + "Wallet Account eXperiments (WAX), formerly known as BLS Wallet, is a suite of production-ready smart account components that provide advanced features for wallets, SDKs, and dApps. It's designed to lower gas costs on EVM rollups through aggregated BLS signatures, simplifying the integration of contract wallets and reducing the cost of layer 2 transactions. This makes WAX particularly beneficial for web3 projects targeting developing economies. WAX components incorporate advanced cryptographic primitives in a secure and intuitive way, using Safe contracts for a familiar and battle-tested foundation. Each additional module can be audited and added or removed at the account holder's discretion. WAX offers features like cheaper L2 transactions, modular smart contract components, ERC 4337 compatibility, zk email verification, passkeys verification, multi-action transactions, gasless transactions, and wallet upgradability. The primary use cases for WAX include scaling, key management, and the creation of prototypes for the web3 ecosystem.", + links: { + github: "https://github.com/getwax", + website: "https://getwax.org/", + twitter: "none", + discord: "https://discord.gg/hGDmAhcRyz", + }, + tags: { + builtWith: [ + "Hardhat", + "Node", + "Solidity BLS library", + "sqlite", + "docker", + "ethers", + "deno", + ], + + themes: ["Scaling", "Key management"], + types: ["Prototype", "Proof of concept", "Lego sets/toolkits"], + }, + }, + + { + id: 5, + image: "", + name: "ZK-Chat", + tldr: "A protocol for integrating decentralized, anonymous, and spam-protected chat into applications.", + description: + "ZK-Chat is a protocol that enables developers to incorporate decentralized, anonymous chat features into their applications, complete with spam protection and anonymous group signaling. It uses Waku decentralized messaging, Semaphore for anonymous signaling, and Rate-Limiting Nullifier (RLN) for spam prevention. This creates a decentralized, client-server model that offers unstoppable, anonymous chat with registry on-chain. It's designed for both developers and users, offering an app and a library for easy integration into various applications.", + links: { + github: "https://github.com/kayleegeorge/zk-chat//", + + website: "https://www.notion.so/6649797a76ed4858933015360fc76650?pvs=21", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Social"], + types: ["Legos/dev tools", "Proof of concept", "Application"], + builtWith: ["RLN", "Semaphore", "Waku"], + }, + }, + { + id: 6, + image: "cryptkeeperlogo.webp", + name: "CryptKeeper", + tldr: "A browser extension for secure, portable anonymous identity management across applications.", + description: + "CryptKeeper is a browser extension that generates Semaphore and RLN proofs for websites, providing a secure and portable solution for managing anonymous identity secrets across different applications. It simplifies the integration of zero-knowledge (ZK) identities and proofs into applications, allowing developers to focus on building the front-end and logic of their applications. By handling complex aspects of cryptography, circuits, caching, and storage, CryptKeeper enables users to interact with decentralized applications (dapps) without revealing their private identity secrets. It is aimed at building secure community standards for the growing ZK ecosystem.", + links: { + github: "https://github.com/CryptKeeperZK", + website: "none", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Social", "Identity"], + types: ["Application", "Infrastructure/protocol", "Lego sets/toolkits"], + + builtWith: ["Semaphore", "RLN"], + }, + }, + { + id: 7, + image: "semaphorelogo.webp", + name: "Semaphore", + tldr: "A zero-knowledge protocol enabling anonymous group membership proof and signaling.", + description: + "Semaphore is a protocol that allows users to prove their membership in a group and transmit anonymous data, such as votes or feedback, without revealing their identities. It is designed for developers aiming to build privacy-preserving applications. Semaphore enables the creation of identities and their corresponding public values, which can be added to Merkle trees. This facilitates the authentication of anonymous user messages through zero-knowledge proofs, where membership is proven using Merkle proofs within the circuit. Key use cases include anonymous voting applications, receiving anonymous feedback from event attendees, and anonymous text messages. It is currently in production and is being used in a wide variety of projects.", + links: { + github: "https://github.com/semaphore-protocol", + website: "https://semaphore.appliedzkp.org/", + twitter: "none", + discord: "https://semaphore.appliedzkp.org/discord", + }, + tags: { + themes: [ + "Anonymity/privacy", + "Social", + "Identity", + "Transaction privacy", + "Voting/governance", + "Reputation", + "Education", + "Scaling", + "Key management", + "Other (group membership)", + ], + + types: [ + "Legos/dev tools", + "Lego sets/toolkits", + "Infrastructure/protocol", + ], + builtWith: ["ZK-kit", "circom", "snarkjs"], + }, + }, + { + id: 8, + image: "", + name: "PSE Security", + tldr: "Proactively securing Ethereum's L2 and ZK ecosystems.", + description: + "PSE Security is a division of the Privacy & Scaling Explorations team at the Ethereum Foundation. Its primary goal is to identify and rectify bugs, thereby enhancing the security of the Ethereum Layer 2 and Zero-Knowledge ecosystems. Recognizing the potential for critical bugs to cause significant setbacks, PSE Security is committed to preemptively addressing these issues. The team offers open-source projects like the ZK Bug Tracker and Bridge Bug Tracker, which track real bugs and exploits in production code, and encourages community contributions. PSE Security also conducts manual audits and plans to help teach the community more about security and ways they can prevent bugs themselves.", + links: { + github: "https://github.com/privacy-scaling-explorations/security", + website: + "https://mirror.xyz/privacy-scaling-explorations.eth/BaqGMfBhEZR1cvTJlA9E3Xu5ZhD7IthLiUK-Q75rQMM", + discord: "none", + twitter: "none", + }, + tags: { + themes: [ + "Anonymity/privacy", + "Education", + "Key management", + "Scaling", + "Security", + ], + types: ["Legos/dev tools"], + builtWith: ["Slither", "Ecne", "Circomspect", "Echidna"], + }, + }, + + { + id: 9, + image: "", + name: "zkEVM Community Edition", + tldr: "A zero-knowledge proof mechanism for Ethereum block verification.", + description: + "zkEVM Community Edition is a project aimed at validating Ethereum blocks using zero-knowledge proofs. It is designed to be fully compatible with Ethereum's EVM and serves two primary goals. First, it enables the creation of a layer 2 network (zkRollup) compatible with the Ethereum ecosystem, which uses zero-knowledge proofs to validate blocks, thus enhancing scalability. Second, it allows the generation of zero-knowledge proofs for blocks from the existing layer 1 Ethereum network, enabling light clients to quickly synchronize many blocks with low resource consumption while ensuring block correctness without needing trust in external parties.", + links: { + github: "https://github.com/privacy-scaling-explorations/zkevm-circuits", + website: + "https://mirror.xyz/privacy-scaling-explorations.eth/I5BzurX-T6slFaPbA4i3hVrO7U2VkBR45eO-N3CSnSg", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Scaling"], + types: ["Infrastructure/protocol", "Lego sets/toolkits"], + builtWith: ["halo2 from zcash", "Rust", "geth"], + }, + }, + + { + id: 10, + image: "bandadalogo.webp", + name: "Bandada", + tldr: "An open-source system for managing privacy-preserving groups of anonymous individuals.", + description: + "Bandada is a project designed to simplify the management of privacy-preserving Semaphore groups. It is aimed at developers who want to build privacy-based applications and integrate anonymity sets, as well as non-developers working in DAOs, governments, international institutions, non-profit organizations, and associations that want to create and manage anonymous groups. Bandada offers a plug-and-play infrastructure, reducing the time and complexity required for managing anonymity sets. It enables anonymous signaling, such as voting, messaging, login, or endorsing, in various use cases like private organizations, GitHub repository contributors, and groups of wallets holding a specific NFT.", + links: { + github: "https://github.com/privacy-scaling-explorations/bandada", + website: "https://bandada.appliedzkp.org/", + twitter: "none", + discord: "none", + }, + tags: { + themes: [ + "Anonymity/privacy", + "Social", + "Identity", + "Transaction privacy", + "Voting/governance", + "Reputation", + "Education", + "Scaling", + "Key management", + ], + type: [ + "Legos/dev tools", + "Lego sets/toolkits", + "Prototype", + "Proof of concept", + "Infrastructure/protocol", + "Plugin", + "Application", + ], + builtWith: ["Semaphore", "ZK-kit"], + }, + }, + + { + id: 11, + image: "", + name: "DSL Working Group", + tldr: "Exploration of languages for writing zk circuits", + description: + "The DSL Working Group is focused on the exploration and improvement of languages used to write zero-knowledge circuits. The group's primary goal is to enhance the state of zk circuit languages, making them easier to write and review by offering the right abstractions. They also aim to make it harder to write unsound circuits by implementing static analysis and enforcing safer patterns. Additionally, they are working to support next-generation (Incrementally Verifiable Computation or IVC) proving systems. The group is currently working on Chiquito, a high-level Domain-Specific Language (DSL) for Halo2 circuits that lowers the entry barrier to write zk circuits with a state-machine abstraction API.", + links: { + github: "https://github.com/privacy-scaling-explorations/chiquito/", + website: "none", + twitter: "none", + discord: "none", + }, + tags: { + type: ["Legos/dev tools", "Proof of concept", "Developer tooling"], + themes: [], + builtWith: [], + }, + }, + + { + id: 12, + image: "", + name: "ZKML (Zero-Knowledge Machine Learning)", + tldr: "ZKML leverages zero-knowledge proofs for privacy-preserving machine learning, enabling model and data privacy with transparent verification.", + description: + "ZKML is a solution that combines the power of zero-knowledge proofs (ZKPs) and machine learning to address the privacy concerns in traditional machine learning. It provides a platform for machine learning developers to convert their TensorFlow Keras models into ZK-compatible versions, ensuring model privacy, data privacy, and transparent verification. ZKML can be used to verify if a specific machine learning model was used to generate a particular piece of content, without revealing the input or the model used. It has potential use cases in on-chain biometric authentication, private data marketplace, proprietary ML model sharing, and AIGC NFTs.", + links: { + github: "https://github.com/socathie", + + website: + "https://mirror.xyz/privacy-scaling-explorations.eth/K88lOS4XegJGzMoav9K5bLuT9Zhn3Hz2KkhB3ITq-m8", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Scaling"], + type: ["Proof of concept", "Infrastructure/protocol"], + builtWith: ["circom", "halo2", "nova"], + }, + }, + + { + id: 13, + image: "", + name: "Trusted Setups", + tldr: "Aiding developers with tools for trusted setups.", + description: + "The Trusted Setups project is dedicated to simplifying the process of trusted setups, which are crucial for privacy or scaling solutions. Trusted setups involve multiple participants contributing to the generation of secrets. As long as one participant forgets their part of the secret, the final solution remains secure. The team recognizes the complexity of developing contribution programs and coordinating the participants' queue in a trusted setup. To address this, they are developing tools, including scripts, WebApps, and APIs, to streamline the contribution and coordination effort. This allows developers to focus on building their circuits and applications, enhancing efficiency and productivity in the development of zero-knowledge applications.", + links: { + github: "https://github.com/zkparty", + + website: "https://docs.google.com/presentation/d/1dTKWaZDPCZFI5W", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Scaling", "Education"], + type: ["Legos/dev tools", "Lego sets/toolkits"], + builtWith: [], + }, + }, + + { + id: 14, + image: "", + name: "zk3", + tldr: "Utilizing ZK proofs in social networks", + description: + "Zk3 is a protocol that leverages Zero Knowledge Proofs (ZKPs) to allow users to prove their membership in a group without revealing their identity. This is particularly useful for social media applications built on Lens or other on-chain platforms. The protocol helps to moderate conversations and reduce bot activity while preserving user privacy. It provides developers with the tools to verify group eligibility, create ZK proofs, and use ZK proofs in Lens. ZK3 consists of a smart contract system for user interactions and network rules, and a GraphQL API for flexible interaction, enabling the development of diverse applications, including web 2.0 integrations.", + links: { + github: "http://github.com/monemetrics/semaphore-zk3", + website: "http://zk3.io/", + twitter: "http://twitter.com/zk3org", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Social", "Identity", "Reputation"], + type: [ + "Legos/dev tools", + "Lego sets/toolkits", + "Infrastructure/protocol", + "Plugin", + ], + builtWith: ["Semaphore", "Lens protocol"], + }, + }, + + { + id: 15, + image: "tlsnlogo.webp", + name: "TLSNotary", + tldr: "A protocol for creating cryptographic proofs of authenticity for any data on the web.", + description: + "TLSNotary is useful for developers of privacy focused projects that need data provenance from secure web servers. It leverages the widely-used Transport Layer Security (TLS) protocol to securely and privately prove a transcript of communications took place with a webserver. The protocol involves splitting TLS session keys between two parties: the User and the Notary. Neither the User nor Notary are in possession of the full TLS session keys, they only hold a share of those keys. This ensures the security assumptions of TLS while enabling the User to prove the authenticity of the communication to the Notary. The Notary remains unaware of which webserver is being queried, and the Notary never has access to the unencrypted communications. All of this is achieved while maintaining full privacy.", + links: { + github: "none", + website: "none", + twitter: "none", + discord: "none", + }, + tags: { + themes: [], + type: [], + builtWith: [], + }, + }, + + { + id: 16, + image: "", + name: "EigenTrust", + tldr: "A distributed reputation system with zero-knowledge features.", + description: + "EigenTrust is a library designed to manage trust within a distributed network, incorporating zero-knowledge features. It serves as a reputation bank for the Ethereum ecosystem, providing an interoperable layer for managing reputation and trust. The protocol creates zero-knowledge proofs of reputation scores based on ratings given by network participants. This allows for the creation of a reputation system for peer-to-peer marketplaces and exchanges, reputation-weighted voting, and community gatekeeping.", + links: { + github: "https://github.com/eigen-trust/protocol", + website: "none", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Reputation", "Identity"], + type: ["Infrastructure/protocol"], + builtWith: ["Ethereum Attestation Service", "Halo2", "ethers.rs"], + }, + }, + + { + id: 17, + image: "", + name: "AnonKlub", + tldr: "A mechanism for anonymous proof of Ethereum address ownership.", + description: + "AnonKlub is a tool designed for Ethereum developers that allows for anonymous proof of Ethereum address ownership. It doesn't directly address the public observability of Ethereum transactions but provides a workaround for privacy. Users can prepare a list of Ethereum addresses, sign a message from an address they own, and use that signature to generate a zero-knowledge proof. This proof enables users to perform actions anonymously that would typically require ownership of an address from the initial list. Use cases include anonymous NFT minting and Discord verification for DAOs without disclosing the public address.", + links: { + github: "https://github.com/privacy-scaling-explorations/e2e-zk-ecdsa", + website: "https://anonklub.fly.dev/", + twitter: "none", + discord: "none", + }, + tags: { + themes: [ + "Transaction privacy", + "Anonymity/privacy", + "Social", + "Identity", + "Voting/governance", + ], + type: ["Infrastructure/protocol", "Prototype", "Proof of concept"], + builtWith: ["Circom", "snarkjs", "halo2"], + }, + }, + + { + id: 18, + image: "", + name: "Summa", + tldr: "Protocol enabling centralized exchanges to prove solvency without compromising private information.", + description: + "Summa allows centralized exchanges to demonstrate that their assets exceed their liabilities without revealing critical business information such as individual user balances, total number of users, and total liabilities or assets. It uses zero-knowledge proofs to ensure that exchanges can demonstrate they have sufficient assets to cover all user balances. The protocol involves building a Merkle Sum Tree of user balances, generating proofs for each user, and allowing users to verify these proofs.", + links: { + github: "https://github.com/summa-dev", + website: "none", + twitter: "none", + discord: "none", + }, + tags: { + themes: ["Anonymity/privacy", "Computational Integrity"], + type: ["Infrastructure/protocol", "Application"], + builtWith: ["Halo2 PSE"], + }, + }, +] diff --git a/config/site.ts b/config/site.ts index b9d54f1..22c6dac 100644 --- a/config/site.ts +++ b/config/site.ts @@ -9,10 +9,17 @@ export const siteConfig = { title: "Home", href: "/", }, + { + title: "Project Library", + href: "/projects", + }, ], links: { twitter: "https://twitter.com/privacyscaling", github: "https://github.com/privacy-scaling-explorations", docs: "https://ui.shadcn.com", + discord: "https://discord.com/invite/sF5CT5rzrR", + articles: "https://mirror.xyz/privacy-scaling-explorations.eth", + jobs: "https://jobs.lever.co/ethereumfoundation/?department=Ethereum%20Foundation&team=Privacy%20and%20Scaling%20Explorations", }, } diff --git a/package.json b/package.json index 0ed2c6f..4ff86b1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "@radix-ui/react-slot": "^1.0.2", "class-variance-authority": "^0.4.0", "clsx": "^1.2.1", + "framer-motion": "^10.12.17", + "gsap": "^3.12.1", "lucide-react": "0.105.0-alpha.4", "next": "^13.4.4", "next-themes": "^0.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3028eb..f6b9570 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,12 @@ dependencies: clsx: specifier: ^1.2.1 version: 1.2.1 + framer-motion: + specifier: ^10.12.17 + version: 10.12.17(react-dom@18.2.0)(react@18.2.0) + gsap: + specifier: ^3.12.1 + version: 3.12.1 lucide-react: specifier: 0.105.0-alpha.4 version: 0.105.0-alpha.4(react@18.2.0) @@ -275,6 +281,19 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 + /@emotion/is-prop-valid@0.8.8: + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + requiresBuild: true + dependencies: + '@emotion/memoize': 0.7.4 + dev: false + optional: true + + /@emotion/memoize@0.7.4: + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + dev: false + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.41.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1531,6 +1550,24 @@ packages: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true + /framer-motion@10.12.17(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IR+aAYntsyu6ofyxqQV4QYotmOqzcuKxhqNpfc3DXJjNWOPpOeSyH0A+In3IEBu49Yx/+PNht+YMeZSdCNaYbw==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.5.2 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + dev: false + /fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: false @@ -1671,6 +1708,10 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /gsap@3.12.1: + resolution: {integrity: sha512-FXtb2YbBE9l8I9Pl5DFLpCMedaiMPztRlr0Ln0CMSnJn+pbTaeKlzgth8cLNPc7PzNwIZe+SEQiBBAWaBKJdVA==} + dev: false + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 718d6fe..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..b18cf63 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/archstar.webp b/public/icons/archstar.webp new file mode 100644 index 0000000..0a3f12a Binary files /dev/null and b/public/icons/archstar.webp differ diff --git a/public/icons/arrow-right-up.svg b/public/icons/arrow-right-up.svg new file mode 100644 index 0000000..a74a94a --- /dev/null +++ b/public/icons/arrow-right-up.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/arrow-right.svg b/public/icons/arrow-right.svg new file mode 100644 index 0000000..031ae18 --- /dev/null +++ b/public/icons/arrow-right.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/close-fill.svg b/public/icons/close-fill.svg new file mode 100644 index 0000000..c16a987 --- /dev/null +++ b/public/icons/close-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/menu-burger.svg b/public/icons/menu-burger.svg new file mode 100644 index 0000000..00dcce0 --- /dev/null +++ b/public/icons/menu-burger.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/pseicon1.svg b/public/icons/pseicon1.svg new file mode 100644 index 0000000..63a739f --- /dev/null +++ b/public/icons/pseicon1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/pseicon2.svg b/public/icons/pseicon2.svg new file mode 100644 index 0000000..8da5a23 --- /dev/null +++ b/public/icons/pseicon2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/pseicon3.svg b/public/icons/pseicon3.svg new file mode 100644 index 0000000..c0ded71 --- /dev/null +++ b/public/icons/pseicon3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/logos/footer-logo.svg b/public/logos/footer-logo.svg new file mode 100644 index 0000000..c6f63a6 --- /dev/null +++ b/public/logos/footer-logo.svg @@ -0,0 +1,9 @@ + + + diff --git a/public/logos/header-logo.svg b/public/logos/header-logo.svg new file mode 100644 index 0000000..65e4631 --- /dev/null +++ b/public/logos/header-logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/projects-logo/bandadalogo.webp b/public/projects-logo/bandadalogo.webp new file mode 100644 index 0000000..c1d8611 Binary files /dev/null and b/public/projects-logo/bandadalogo.webp differ diff --git a/public/projects-logo/clrlogo.webp b/public/projects-logo/clrlogo.webp new file mode 100644 index 0000000..4be4a5a Binary files /dev/null and b/public/projects-logo/clrlogo.webp differ diff --git a/public/projects-logo/cryptkeeperlogo.webp b/public/projects-logo/cryptkeeperlogo.webp new file mode 100644 index 0000000..3811e47 Binary files /dev/null and b/public/projects-logo/cryptkeeperlogo.webp differ diff --git a/public/projects-logo/intereplogo.webp b/public/projects-logo/intereplogo.webp new file mode 100644 index 0000000..100170f Binary files /dev/null and b/public/projects-logo/intereplogo.webp differ diff --git a/public/projects-logo/macilogo.webp b/public/projects-logo/macilogo.webp new file mode 100644 index 0000000..4e24d1d Binary files /dev/null and b/public/projects-logo/macilogo.webp differ diff --git a/public/projects-logo/rlnlogo.webp b/public/projects-logo/rlnlogo.webp new file mode 100644 index 0000000..e5850cd Binary files /dev/null and b/public/projects-logo/rlnlogo.webp differ diff --git a/public/projects-logo/semaphorelogo.webp b/public/projects-logo/semaphorelogo.webp new file mode 100644 index 0000000..050c377 Binary files /dev/null and b/public/projects-logo/semaphorelogo.webp differ diff --git a/public/projects-logo/tlsnlogo.webp b/public/projects-logo/tlsnlogo.webp new file mode 100644 index 0000000..73a7845 Binary files /dev/null and b/public/projects-logo/tlsnlogo.webp differ diff --git a/public/projects-logo/unireplogo.webp b/public/projects-logo/unireplogo.webp new file mode 100644 index 0000000..8c14f32 Binary files /dev/null and b/public/projects-logo/unireplogo.webp differ diff --git a/public/projects-logo/waxlogo.webp b/public/projects-logo/waxlogo.webp new file mode 100644 index 0000000..469c81c Binary files /dev/null and b/public/projects-logo/waxlogo.webp differ diff --git a/public/projects-logo/zkitterlogo.webp b/public/projects-logo/zkitterlogo.webp new file mode 100644 index 0000000..83a6c87 Binary files /dev/null and b/public/projects-logo/zkitterlogo.webp differ diff --git a/public/projects-logo/zkkitlogo.webp b/public/projects-logo/zkkitlogo.webp new file mode 100644 index 0000000..85ba107 Binary files /dev/null and b/public/projects-logo/zkkitlogo.webp differ diff --git a/public/projects-logo/zkoprulogo.webp b/public/projects-logo/zkoprulogo.webp new file mode 100644 index 0000000..1b0caea Binary files /dev/null and b/public/projects-logo/zkoprulogo.webp differ diff --git a/public/social-medias/github-fill.svg b/public/social-medias/github-fill.svg new file mode 100644 index 0000000..691c786 --- /dev/null +++ b/public/social-medias/github-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/social-medias/global-line.svg b/public/social-medias/global-line.svg new file mode 100644 index 0000000..3056f5d --- /dev/null +++ b/public/social-medias/global-line.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/social-medias/twitter-fill.svg b/public/social-medias/twitter-fill.svg new file mode 100644 index 0000000..2d87267 --- /dev/null +++ b/public/social-medias/twitter-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/social-medias/youtube-fill.svg b/public/social-medias/youtube-fill.svg new file mode 100644 index 0000000..013652c --- /dev/null +++ b/public/social-medias/youtube-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/thirteen.svg b/public/thirteen.svg deleted file mode 100644 index 8977c1b..0000000 --- a/public/thirteen.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index d2f8422..0000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/styles/globals.css b/styles/globals.css index 9e31af5..d31ee06 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -74,11 +74,22 @@ * { @apply border-border; } + html{ + @apply font-sans; + } body { - @apply bg-background text-foreground; + @apply bg-background text-foreground font-sans; font-feature-settings: "rlig" 1, "calt" 1; } - h1,h2,h3,h4,h5{ - @apply font-display; + h1, + h2, + h3, + h4, + h5, h6 { + @apply font-display font-bold; + } + + #privacy, #scaling, #explorations{ + @apply fill-gray-900; } } diff --git a/tailwind.config.js b/tailwind.config.js index 8ebc8cd..fd3069a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -13,7 +13,17 @@ module.exports = { }, }, extend: { + backgroundImage: { + "main-gradient": + "radial-gradient(114.29% 42.52% at 103.66% 58.94%, #D0F8F1 0%, #D1F3FF 18.23%, #ECF8FF 51.28%, #E1FFFA 80.21%, #D0F2FF 93.23%)", + "second-gradient": + "radial-gradient(56.07% 115.65% at 93.66% 158.94%, #D0F8F1 0%, #D1F3FF 18.23%, #ECF8FF 51.28%, #E1FFFA 80.21%, #D0F2FF 93.23%)", + }, colors: { + corduroy: "#4A5754", + orange: "#E1523A", + orangeDark: "#E3533A", + anakiwa: "#F2FAFD", border: "hsl(var(--border))", input: "hsl(var(--input))", ring: "hsl(var(--ring))", diff --git a/types/nav.ts b/types/nav.ts index 0961ce8..d5a468b 100644 --- a/types/nav.ts +++ b/types/nav.ts @@ -1,6 +1,6 @@ export interface NavItem { title: string - href?: string + href: string disabled?: boolean external?: boolean }