From 79566aeb8515ae3044dc5a8b84fd0530c2580dfe Mon Sep 17 00:00:00 2001
From: Satchmo <456719+rohenaz@users.noreply.github.com>
Date: Fri, 4 Sep 2026 15:35:21 -0400
Subject: [PATCH] Preserve reader links after inscription
---
apps/web/src/app/d/[origin]/page.tsx | 4 ++--
.../components/hosted-draft-redirect.test.ts | 12 ++++++++++++
.../src/components/hosted-draft-redirect.tsx | 19 +++++++++++++++++++
3 files changed, 33 insertions(+), 2 deletions(-)
create mode 100644 apps/web/src/components/hosted-draft-redirect.test.ts
create mode 100644 apps/web/src/components/hosted-draft-redirect.tsx
diff --git a/apps/web/src/app/d/[origin]/page.tsx b/apps/web/src/app/d/[origin]/page.tsx
index 6e3147f..00f9fba 100644
--- a/apps/web/src/app/d/[origin]/page.tsx
+++ b/apps/web/src/app/d/[origin]/page.tsx
@@ -1,8 +1,8 @@
import type { Metadata } from "next";
-import { permanentRedirect } from "next/navigation";
import { Suspense } from "react";
import { DraftResolving, DraftViewer } from "@/components/draft-viewer";
+import { HostedDraftRedirect } from "@/components/hosted-draft-redirect";
import { draftShareDescription } from "@/lib/format";
import { readHostedRecord } from "@/lib/hosted";
import { isHostedId } from "@/lib/hosted-id";
@@ -68,7 +68,7 @@ export default async function DraftPage({
if (origin && isHostedId(origin)) {
const record = await readHostedRecord(origin);
if (record?.origin) {
- permanentRedirect(`/d/${record.origin}`);
+ return ;
}
}
diff --git a/apps/web/src/components/hosted-draft-redirect.test.ts b/apps/web/src/components/hosted-draft-redirect.test.ts
new file mode 100644
index 0000000..c2b5d9a
--- /dev/null
+++ b/apps/web/src/components/hosted-draft-redirect.test.ts
@@ -0,0 +1,12 @@
+import { describe, expect, test } from "bun:test";
+
+import { transitionedDraftHref } from "./hosted-draft-redirect";
+
+describe("hosted draft transition", () => {
+ test("keeps a reader-link fragment when moving to the chain origin", () => {
+ expect(transitionedDraftHref("chain_0", "#k=reader-secret")).toBe(
+ "/d/chain_0#k=reader-secret"
+ );
+ expect(transitionedDraftHref("chain_0", "")).toBe("/d/chain_0");
+ });
+});
diff --git a/apps/web/src/components/hosted-draft-redirect.tsx b/apps/web/src/components/hosted-draft-redirect.tsx
new file mode 100644
index 0000000..a59a2da
--- /dev/null
+++ b/apps/web/src/components/hosted-draft-redirect.tsx
@@ -0,0 +1,19 @@
+"use client";
+
+import { useEffect } from "react";
+
+import { DraftResolving } from "@/components/draft-viewer";
+
+export function transitionedDraftHref(origin: string, hash: string): string {
+ return `/d/${origin}${hash}`;
+}
+
+export function HostedDraftRedirect({ origin }: { origin: string }) {
+ useEffect(() => {
+ window.location.replace(
+ transitionedDraftHref(origin, window.location.hash)
+ );
+ }, [origin]);
+
+ return ;
+}