feat: configure NIP-05 verification for grimoire.rocks domain

Updates Grimoire member system to use grimoire.rocks domain and adds
proper NIP-05 verification infrastructure.

Changes:
- Update member NIP-05 identifiers from @grimoire.pro to @grimoire.rocks
- Create public/.well-known/nostr.json with member pubkey mappings
- Configure Vercel to serve nostr.json with proper headers:
  - Content-Type: application/json
  - Access-Control-Allow-Origin: * (required for NIP-05)
  - Cache-Control: public, max-age=3600
- Update rewrites to exclude .well-known paths from SPA routing

This enables NIP-05 verification for:
- _@grimoire.rocks → ce3cd5ba...
- verbiricha@grimoire.rocks → 7fa56f5d...
This commit is contained in:
Claude
2026-01-18 10:42:52 +00:00
parent b45abb85c4
commit 7fe97ad157
5 changed files with 46 additions and 12 deletions

View File

@@ -0,0 +1,6 @@
{
"names": {
"_": "ce3cd5ba3ae52cec4e4b267fb29f1d2a526a5f4b8e8475d8a603a63c8925295f",
"verbiricha": "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194"
}
}

View File

@@ -32,7 +32,7 @@ export function GrimoireUsername({
)}
title={`Grimoire member: ${member.nip05}`}
>
<span>{member.username}@grimoire.pro</span>
<span>{member.username}@grimoire.rocks</span>
{showIcon && (
<BookOpen
className="h-3.5 w-3.5 text-accent"

View File

@@ -59,7 +59,7 @@ describe("Grimoire Members", () => {
expect(member).toBeDefined();
expect(member?.username).toBe("_");
expect(member?.pubkey).toBe(underscorePubkey);
expect(member?.nip05).toBe("_@grimoire.pro");
expect(member?.nip05).toBe("_@grimoire.rocks");
});
it("should return member info for verbiricha username", () => {
@@ -67,7 +67,7 @@ describe("Grimoire Members", () => {
expect(member).toBeDefined();
expect(member?.username).toBe("verbiricha");
expect(member?.pubkey).toBe(verbirichaPubkey);
expect(member?.nip05).toBe("verbiricha@grimoire.pro");
expect(member?.nip05).toBe("verbiricha@grimoire.rocks");
});
it("should return undefined for non-member", () => {
@@ -83,15 +83,15 @@ describe("Grimoire Members", () => {
});
describe("getGrimoireMemberByNip05", () => {
it("should return member info for _@grimoire.pro", () => {
const member = getGrimoireMemberByNip05("_@grimoire.pro");
it("should return member info for _@grimoire.rocks", () => {
const member = getGrimoireMemberByNip05("_@grimoire.rocks");
expect(member).toBeDefined();
expect(member?.username).toBe("_");
expect(member?.pubkey).toBe(underscorePubkey);
});
it("should return member info for verbiricha@grimoire.pro", () => {
const member = getGrimoireMemberByNip05("verbiricha@grimoire.pro");
it("should return member info for verbiricha@grimoire.rocks", () => {
const member = getGrimoireMemberByNip05("verbiricha@grimoire.rocks");
expect(member).toBeDefined();
expect(member?.username).toBe("verbiricha");
expect(member?.pubkey).toBe(verbirichaPubkey);
@@ -122,9 +122,9 @@ describe("Grimoire Members", () => {
describe("getGrimoireNip05", () => {
it("should return NIP-05 for member", () => {
expect(getGrimoireNip05(underscorePubkey)).toBe("_@grimoire.pro");
expect(getGrimoireNip05(underscorePubkey)).toBe("_@grimoire.rocks");
expect(getGrimoireNip05(verbirichaPubkey)).toBe(
"verbiricha@grimoire.pro",
"verbiricha@grimoire.rocks",
);
});

View File

@@ -25,12 +25,12 @@ export const GRIMOIRE_MEMBERS: readonly GrimoireMember[] = [
{
username: "_",
pubkey: "ce3cd5ba3ae52cec4e4b267fb29f1d2a526a5f4b8e8475d8a603a63c8925295f",
nip05: "_@grimoire.pro",
nip05: "_@grimoire.rocks",
},
{
username: "verbiricha",
pubkey: "7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194",
nip05: "verbiricha@grimoire.pro",
nip05: "verbiricha@grimoire.rocks",
},
] as const;

View File

@@ -1,3 +1,31 @@
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
"headers": [
{
"source": "/.well-known/nostr.json",
"headers": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Access-Control-Allow-Origin",
"value": "*"
},
{
"key": "Access-Control-Allow-Methods",
"value": "GET, OPTIONS"
},
{
"key": "Cache-Control",
"value": "public, max-age=3600"
}
]
}
],
"rewrites": [
{
"source": "/((?!.well-known).*)",
"destination": "/"
}
]
}