Skip to content
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
16 changes: 16 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ const nextConfig: NextConfig = {
},
],
},
async headers() {
return [
{
source: "/(.*)",
headers: [
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
{ key: "X-Frame-Options", value: "DENY" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

X-Frame-Options: DENY will break the OAuth callback flow.

The OAuth callback page at src/app/oauth/callback/page.tsx (lines 26-32) explicitly checks if it's running inside an iframe (window.parent !== window) and uses postMessage to communicate with the parent window. Setting X-Frame-Options: DENY globally prevents any page from loading in an iframe, which will break this embedded authentication flow.

Consider one of these approaches:

  1. Exclude the OAuth callback route from the DENY header
  2. Use SAMEORIGIN instead of DENY (allows same-origin iframes)
  3. Migrate to Content-Security-Policy: frame-ancestors for more granular control
Proposed fix: Exclude OAuth callback from X-Frame-Options
  async headers() {
    return [
      {
-       source: "/(.*)",
+       source: "/((?!oauth/callback).*)",
        headers: [
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
          { key: "X-Frame-Options", value: "DENY" },
          {
            key: "Permissions-Policy",
            value: "camera=(), microphone=(), geolocation=()",
          },
        ],
      },
+     {
+       source: "/oauth/callback",
+       headers: [
+         { key: "X-Content-Type-Options", value: "nosniff" },
+         { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
+         { key: "X-Frame-Options", value: "SAMEORIGIN" },
+         {
+           key: "Permissions-Policy",
+           value: "camera=(), microphone=(), geolocation=()",
+         },
+       ],
+     },
    ];
  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@next.config.ts` at line 20, The global header setting { key:
"X-Frame-Options", value: "DENY" } will block the OAuth iframe callback used by
src/app/oauth/callback/page.tsx; update next.config.ts to exclude the OAuth
callback route (or change to SAMEORIGIN or use frame-ancestors) so the callback
can load in an iframe: modify the place where security headers are defined (the
headers array or function that returns headers) to conditionally omit or alter
the X-Frame-Options header for the OAuth callback path (refer to the OAuth
callback route in src/app/oauth/callback/page.tsx and the X-Frame-Options header
entry) and ensure other routes keep the stricter header.

{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=()",
},
],
},
];
},
async redirects() {
return [
{
Expand Down
26 changes: 26 additions & 0 deletions public/llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Certified

> Certified is a passwordless identity platform built on AT Protocol, operated by the Hypercerts Foundation. It lets users create a single account that works across partner applications with full data portability and no vendor lock-in.

## Main

- [Home](https://certified.app): Create your Certified identity and use one account across partner apps
- [About](https://certified.app/about): About Certified and the Hypercerts Foundation
- [Terms of Service](https://certified.app/terms): Service terms for Certified and certified.one infrastructure
- [Privacy Policy](https://certified.app/privacy): Data processing practices, GDPR compliance, cookie policy
- [DSA Compliance](https://certified.app/dsa): Digital Services Act compliance information

## About

- [Hypercerts Foundation](https://hypercerts.org): Parent organization building open-source protocols for impact funding
- [GitHub](https://github.com/hypercerts-org): Open source repositories for Certified and related projects

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hyphenate “Open-source” in this description.

Minor copy edit for consistency/readability.

Proposed fix
-- [GitHub](https://github.com/hypercerts-org): Open source repositories for Certified and related projects
+- [GitHub](https://github.com/hypercerts-org): Open-source repositories for Certified and related projects
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [GitHub](https://github.com/hypercerts-org): Open source repositories for Certified and related projects
- [GitHub](https://github.com/hypercerts-org): Open-source repositories for Certified and related projects
🧰 Tools
🪛 LanguageTool

[grammar] ~16-~16: Use a hyphen to join words.
Context: ...https://github.com/hypercerts-org): Open source repositories for Certified and re...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/llms.txt` at line 16, Update the text in public/llms.txt so the
description hyphenates "Open-source" (change "Open source repositories for
Certified and related projects" to "Open-source repositories for Certified and
related projects"); locate the GitHub link line containing the string
"[GitHub](https://github.com/hypercerts-org): Open source repositories for
Certified and related projects" and replace it with the hyphenated version to
keep copy consistent.

- [Twitter](https://x.com/hypercerts): Hypercerts on X/Twitter
- [LinkedIn](https://www.linkedin.com/company/hypercerts): Hypercerts on LinkedIn
- [Bluesky](https://bsky.app/profile/hypercerts.org): Hypercerts on Bluesky

## Partner Apps

- [Ma Earth](https://maearth.com): Collective funding for regenerating Earth
- [GainForest](https://gainforest.earth): AI-powered forest monitoring and conservation rewards
- [Simocracy](https://simocracy.org): Democratic governance with verifiable identity
- [Hyperboards](https://hyperboards.org): Visual leaderboards for impact contributions
235 changes: 235 additions & 0 deletions src/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import type { Metadata } from "next";
import Link from "next/link";

export const metadata: Metadata = {
title: "About",
description:
"Certified is a passwordless identity platform built on AT Protocol, operated by the Hypercerts Foundation. Learn how Certified works, who builds it, and why portable identity matters.",
alternates: { canonical: "https://certified.app/about" },
openGraph: {
title: "About — Certified",
description:
"Certified is a passwordless identity platform built on AT Protocol, operated by the Hypercerts Foundation.",
url: "https://certified.app/about",
},
};

export default function AboutPage() {
return (
<div className="app-page">
<div className="app-page__inner max-w-3xl">
<h1 className="font-mono text-h1 text-navy tracking-tight mb-8">
About Certified
</h1>

<div className="prose prose-navy max-w-none space-y-8">
<section>
<h2 className="font-mono text-xl text-navy mb-4">What is Certified?</h2>
<p>
Certified is a passwordless identity platform built on{" "}
<a
href="https://atproto.com"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
AT Protocol
</a>
, the open standard behind Bluesky and a growing ecosystem of decentralized
applications. It lets you create a single account that works across every partner
app — no passwords, no vendor lock-in, and full control over your data.
</p>
<p className="mt-4">
When you sign up for Certified, you get an AT Protocol identity and a Personal Data
Server (PDS) hosted at <strong>certified.one</strong>. Your profile, preferences,
and activity travel with you to every app that supports AT Protocol — and
if the app supports Certified directly, you can sign in with just your email,
no password needed.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">How does it work?</h2>
<p>
Sign-in is passwordless: you enter your email, receive a one-time code, and
you&apos;re in. Behind the scenes, Certified issues an AT Protocol identity tied to
your account. That identity is cryptographically verifiable and portable — it works
the same whether you&apos;re on certified.app, a partner application, or any future
service that speaks AT Protocol.
</p>
<p className="mt-4">
Your data lives on your Personal Data Server. If you ever want to leave, you can export everything or migrate your
identity to a different PDS provider — no data is locked inside Certified.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">What is AT Protocol?</h2>
<p>
AT Protocol (Authenticated Transfer Protocol) is an open, federated protocol for
building social and identity applications. Unlike centralized platforms where one
company controls your account, AT Protocol separates identity from the application
layer. Your identity is yours — verifiable, portable, and independent of any single
service.
</p>
<p className="mt-4">
Certified builds on AT Protocol to provide a managed, user-friendly entry point: you
get the benefits of decentralized identity without needing to understand the
underlying protocol or run your own infrastructure.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">
Who operates Certified?
</h2>
<p>
Certified is operated by the{" "}
<a
href="https://hypercerts.org"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
Hypercerts Foundation
</a>
, a Delaware nonstock corporation founded in February 2023. The Foundation develops
open infrastructure for the hypercerts ecosystem — tools and protocols that help
track, fund, and reward positive impact.
</p>
<p className="mt-4">
Certified was created because the hypercerts ecosystem needed a portable identity
layer: a way for users to move between applications while keeping their profile,
contributions, and reputation intact. Rather than build a proprietary login system,
the Foundation chose AT Protocol as the foundation — making Certified interoperable
with a growing network of decentralized applications.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">
How is Certified different from &quot;Sign in with Google&quot;?
</h2>
<p>
Both Certified and &quot;Sign in with Google&quot; let you use one account across
multiple apps. The key difference is ownership and portability:
</p>
<ul className="list-disc pl-6 mt-4 space-y-2">
<li>
<strong>With Google:</strong> Google controls your identity. If Google suspends
your account or changes their terms, you lose access to every app you signed into.
Your data stays with each individual app.
</li>
<li>
<strong>With Certified:</strong> Your identity is an AT Protocol identity — it&apos;s
cryptographically yours. You can export your data, migrate to another provider, or
even self-host. No single company can revoke your identity.
</li>
</ul>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">Open source</h2>
<p>
Every component of Certified is open source. The application code, the PDS
infrastructure, and the protocol it builds on are all publicly auditable. You can
review the source on{" "}
<a
href="https://github.com/hypercerts-org"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
GitHub
</a>
.
</p>
<p className="mt-4">
Security through transparency, not obscurity. If you find an issue, you can report
it directly or submit a fix.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">Infrastructure</h2>
<p>
The Personal Data Servers operated by Certified are hosted on cloud infrastructure
located within the European Union. The service is designed to comply with GDPR and
the Digital Services Act.
</p>
<p className="mt-4">
For more details, see our{" "}
<Link href="/privacy" className="text-blue-600 underline hover:text-blue-800">
Privacy Policy
</Link>{" "}
and{" "}
<Link href="/dsa" className="text-blue-600 underline hover:text-blue-800">
DSA Compliance
</Link>{" "}
page.
</p>
</section>

<section>
<h2 className="font-mono text-xl text-navy mb-4">Contact</h2>
<p>
<strong>Hypercerts Foundation</strong>
<br />
1209 Orange St.
<br />
Wilmington, DE 19801
<br />
United States
</p>
<p className="mt-4">
Email:{" "}
<a
href="mailto:support@hypercerts.org"
className="text-blue-600 underline hover:text-blue-800"
>
support@hypercerts.org
</a>
</p>
<p className="mt-4">
<a
href="https://bsky.app/profile/hypercerts.org"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
Bluesky
</a>
{" · "}
<a
href="https://x.com/hypercerts"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
Twitter/X
</a>
{" · "}
<a
href="https://www.linkedin.com/company/hypercerts"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
LinkedIn
</a>
{" · "}
<a
href="https://github.com/hypercerts-org"
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 underline hover:text-blue-800"
>
GitHub
</a>
</p>
</section>
</div>
</div>
</div>
);
}
15 changes: 15 additions & 0 deletions src/app/dsa/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Digital Services Act — Compliance Information",
description:
"DSA compliance information for Certified, operated by the Hypercerts Foundation. Includes notice-and-action procedures and contact information.",
alternates: { canonical: "https://certified.app/dsa" },
openGraph: {
title: "DSA Compliance — Certified",
description:
"Digital Services Act compliance information for Certified, operated by the Hypercerts Foundation.",
url: "https://certified.app/dsa",
},
};

export default function DsaPage() {
return (
<div className="app-page">
Expand Down
79 changes: 78 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,75 @@ const instrumentSerif = Instrument_Serif({
});

export const metadata: Metadata = {
title: "Certified",
title: {
default: "Certified",
template: "%s — Certified",
},
description: "Your identity, everywhere.",
metadataBase: new URL("https://certified.app"),
openGraph: {
siteName: "Certified",
locale: "en_US",
type: "website",
images: [
{
url: "/assets/certified-hero-1200x630.png",
width: 1200,
height: 630,
alt: "Certified — One account, any app",
},
],
},
twitter: {
card: "summary_large_image",
images: ["/assets/certified-hero-1200x630.png"],
},
};

const organizationJsonLd = {
"@context": "https://schema.org",
"@type": "Organization",
name: "Hypercerts Foundation",
legalName: "Hypercerts Foundation",
url: "https://hypercerts.org",
logo: "https://certified.app/assets/certified_brandmark_black.png",
description:
"A Delaware nonstock corporation that develops open infrastructure for the hypercerts ecosystem, operating the Certified identity platform.",
foundingDate: "2023-02-03",
address: {
"@type": "PostalAddress",
streetAddress: "1209 Orange St.",
addressLocality: "Wilmington",
addressRegion: "DE",
postalCode: "19801",
addressCountry: "US",
},
contactPoint: {
"@type": "ContactPoint",
email: "legal@hypercerts.org",
contactType: "legal",
},
sameAs: [
"https://github.com/hypercerts-org",
"https://x.com/hypercerts",
"https://www.linkedin.com/company/hypercerts",
"https://bsky.app/profile/hypercerts.org",
],
};

const websiteJsonLd = {
"@context": "https://schema.org",
"@type": "WebSite",
name: "Certified",
url: "https://certified.app",
description:
"Create your Certified identity and use one account across partner apps. No passwords, no lock-in.",
publisher: {
"@type": "Organization",
name: "Hypercerts Foundation",
url: "https://hypercerts.org",
},
inLanguage: "en",
};

export default function RootLayout({
Expand All @@ -43,6 +110,16 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationJsonLd) }}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(websiteJsonLd) }}
/>
</head>
<body className={`${inter.variable} ${notoSerif.variable} ${instrumentSerif.variable} min-h-screen flex flex-col`}>
<Providers>
<AuthProvider>
Expand Down
Loading