diff --git a/CONTEXT.md b/CONTEXT.md
index 49729e0..53c4a74 100644
--- a/CONTEXT.md
+++ b/CONTEXT.md
@@ -524,74 +524,44 @@ Nostr defines a set of bech32-encoded identifiers in NIP-19. Their prefixes and
**Critical**: NIP-19 identifiers should be handled at the **root level** of URLs (e.g., `/note1...`, `/npub1...`, `/naddr1...`), NOT nested under paths like `/note/note1...` or `/profile/npub1...`.
+This project includes a boilerplate `NIP19Page` component that provides the foundation for handling all NIP-19 identifier types at the root level. The component is configured in the routing system and ready for AI agents to populate with specific functionality.
+
+**How it works:**
+
+1. **Root-Level Route**: The route `/:nip19` in `AppRouter.tsx` catches all NIP-19 identifiers
+2. **Automatic Decoding**: The `NIP19Page` component automatically decodes the identifier using `nip19.decode()`
+3. **Type-Specific Sections**: Different sections are rendered based on the identifier type:
+ - `npub1`/`nprofile1`: Profile section with placeholder for profile view
+ - `note1`: Note section with placeholder for kind:1 text note view
+ - `nevent1`: Event section with placeholder for any event type view
+ - `naddr1`: Addressable event section with placeholder for articles, marketplace items, etc.
+4. **Error Handling**: Invalid, vacant, or unsupported identifiers show 404 NotFound page
+5. **Ready for Population**: Each section includes comments indicating where AI agents should implement specific functionality
+
+**Example URLs that work automatically:**
+- `/npub1abc123...` - User profile (needs implementation)
+- `/note1def456...` - Kind:1 text note (needs implementation)
+- `/nevent1ghi789...` - Any event with relay hints (needs implementation)
+- `/naddr1jkl012...` - Addressable event (needs implementation)
+
+**Features included:**
+- Basic NIP-19 identifier decoding and routing
+- Type-specific sections for different identifier types
+- Error handling for invalid identifiers
+- Responsive container structure
+- Comments indicating where to implement specific views
+
+**Error handling:**
+- Invalid NIP-19 format → 404 NotFound
+- Unsupported identifier types (like `nsec1`) → 404 NotFound
+- Empty or missing identifiers → 404 NotFound
+
To implement NIP-19 routing in your Nostr application:
-1. **Create a NIP19Page Component**: This component should handle all NIP-19 identifier types and render appropriate views:
-
-```tsx
-// Example NIP19Page component structure
-function NIP19Page() {
- const { nip19: nip19Param } = useParams<{ nip19: string }>();
-
- // Decode the NIP-19 identifier
- const decoded = useMemo(() => {
- try {
- return nip19.decode(nip19Param);
- } catch (error) {
- return null; // Invalid identifier
- }
- }, [nip19Param]);
-
- // Handle different identifier types
- switch (decoded?.type) {
- case 'npub':
- case 'nprofile':
- return ;
- case 'note':
- return ;
- case 'nevent':
- return ;
- case 'naddr':
- return ;
- default:
- return ; // Handle invalid/unsupported identifiers
- }
-}
-```
-
-2. **Add Root-Level Route**: Configure your router to handle NIP-19 identifiers at the root:
-
-```tsx
-// In your router configuration
-} />
-```
-
-3. **Error Handling**: Always handle NIP-19 decoding errors gracefully:
- - **Invalid identifiers**: Show 404 NotFound page
- - **Vacant identifiers**: Show 404 NotFound page
- - **Unsupported types**: Show 404 NotFound page
- - **Malformed identifiers**: Show 404 NotFound page
-
-4. **Identifier Validation**: Validate identifiers before processing:
-
-```tsx
-// Example validation
-const validateNIP19 = (identifier: string): boolean => {
- if (!identifier) return false;
-
- const validPrefixes = ['npub1', 'nsec1', 'note1', 'nevent1', 'nprofile1', 'naddr1'];
- const hasValidPrefix = validPrefixes.some(prefix => identifier.startsWith(prefix));
-
- if (!hasValidPrefix) return false;
-
- try {
- nip19.decode(identifier);
- return true;
- } catch {
- return false;
- }
-};
-```
+1. **The NIP19Page boilerplate is already created** - populate sections with specific functionality
+2. **The route is already configured** in `AppRouter.tsx`
+3. **Error handling is built-in** - all edge cases show appropriate 404 responses
+4. **Add specific components** for profile views, event displays, etc. as needed
#### Event Type Distinctions
diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx
index b8875c6..2db53ee 100644
--- a/src/AppRouter.tsx
+++ b/src/AppRouter.tsx
@@ -2,6 +2,7 @@ import { BrowserRouter, Route, Routes } from "react-router-dom";
import { ScrollToTop } from "./components/ScrollToTop";
import Index from "./pages/Index";
+import { NIP19Page } from "./pages/NIP19Page";
import NotFound from "./pages/NotFound";
export function AppRouter() {
@@ -10,6 +11,8 @@ export function AppRouter() {
} />
+ {/* NIP-19 route for npub1, note1, naddr1, nevent1, nprofile1 */}
+ } />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
} />
diff --git a/src/pages/NIP19Page.tsx b/src/pages/NIP19Page.tsx
new file mode 100644
index 0000000..5aa4439
--- /dev/null
+++ b/src/pages/NIP19Page.tsx
@@ -0,0 +1,42 @@
+import { nip19 } from 'nostr-tools';
+import { useParams } from 'react-router-dom';
+import NotFound from './NotFound';
+
+export function NIP19Page() {
+ const { nip19: identifier } = useParams<{ nip19: string }>();
+
+ if (!identifier) {
+ return ;
+ }
+
+ let decoded;
+ try {
+ decoded = nip19.decode(identifier);
+ } catch {
+ return ;
+ }
+
+ const { type } = decoded;
+
+ switch (type) {
+ case 'npub':
+ case 'nprofile':
+ // AI agent should implement profile view here
+ return
Profile placeholder
;
+
+ case 'note':
+ // AI agent should implement note view here
+ return Note placeholder
;
+
+ case 'nevent':
+ // AI agent should implement event view here
+ return Event placeholder
;
+
+ case 'naddr':
+ // AI agent should implement addressable event view here
+ return Addressable event placeholder
;
+
+ default:
+ return ;
+ }
+}
\ No newline at end of file