diff --git a/modules/rnotes/components/folk-notes-app.ts b/modules/rnotes/components/folk-notes-app.ts
index cee4a1b..66d5555 100644
--- a/modules/rnotes/components/folk-notes-app.ts
+++ b/modules/rnotes/components/folk-notes-app.ts
@@ -360,17 +360,31 @@ Gear: EUR 400 (10%)
Maya is tracking expenses in rF
}
private demoCreateNotebook() {
- const title = prompt("Notebook name:");
- if (!title?.trim()) return;
const now = Date.now();
+ const nbId = `demo-nb-${now}`;
+ const noteId = `demo-note-${now}`;
+ const newNote: Note = {
+ id: noteId, title: "Untitled Note", content: "", content_plain: "",
+ content_format: 'tiptap-json',
+ type: "NOTE", tags: null, is_pinned: false,
+ created_at: new Date(now).toISOString(), updated_at: new Date(now).toISOString(),
+ };
const nb = {
- id: `demo-nb-${now}`, title, description: "",
- cover_color: "#8b5cf6", note_count: "0",
- updated_at: new Date(now).toISOString(), notes: [] as Note[],
+ id: nbId, title: "Untitled Notebook", description: "",
+ cover_color: "#8b5cf6", note_count: "1",
+ updated_at: new Date(now).toISOString(), notes: [newNote],
} as any;
this.demoNotebooks.push(nb);
this.notebooks = this.demoNotebooks.map(({ notes, ...rest }) => rest as Notebook);
+ this.selectedNotebook = { ...nb };
+ this.view = "notebook";
this.render();
+ // Auto-open the note for editing
+ this.selectedNote = newNote;
+ this.view = "note";
+ this.renderNav();
+ this.renderMeta();
+ this.mountEditor(newNote);
}
private demoCreateNote() {
@@ -726,16 +740,20 @@ Gear: EUR 400 (10%)Maya is tracking expenses in rF
}
private async createNotebook() {
- const title = prompt("Notebook name:");
- if (!title?.trim()) return;
try {
const base = this.getApiBase();
- await fetch(`${base}/api/notebooks`, {
+ const res = await fetch(`${base}/api/notebooks`, {
method: "POST",
headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ title }),
+ body: JSON.stringify({ title: "Untitled Notebook" }),
});
- await this.loadNotebooks();
+ const nb = await res.json();
+ if (nb?.id) {
+ this.view = "notebook";
+ await this.loadNotebook(nb.id);
+ } else {
+ await this.loadNotebooks();
+ }
} catch {
this.error = "Failed to create notebook";
this.render();
diff --git a/modules/rsocials/components/folk-campaign-manager.ts b/modules/rsocials/components/folk-campaign-manager.ts
index c836e98..e321baa 100644
--- a/modules/rsocials/components/folk-campaign-manager.ts
+++ b/modules/rsocials/components/folk-campaign-manager.ts
@@ -131,7 +131,7 @@ export class FolkCampaignManager extends HTMLElement {
${phaseHTML}
diff --git a/modules/rsocials/components/folk-campaign-planner.ts b/modules/rsocials/components/folk-campaign-planner.ts
index d920448..13dd22c 100644
--- a/modules/rsocials/components/folk-campaign-planner.ts
+++ b/modules/rsocials/components/folk-campaign-planner.ts
@@ -820,7 +820,7 @@ class FolkCampaignPlanner extends HTMLElement {
} else if (action === 'open-thread') {
const d = node.data as ThreadNodeData;
if (d.threadId) {
- window.location.href = `/${this.space}/rsocials/thread/${d.threadId}/edit`;
+ window.location.href = `/${this.space}/rsocials/thread-editor/${d.threadId}/edit`;
}
}
});
@@ -1457,7 +1457,7 @@ class FolkCampaignPlanner extends HTMLElement {
if (node?.type === 'thread') {
const d = node.data as ThreadNodeData;
if (d.threadId) {
- window.location.href = `/${this.space}/rsocials/thread/${d.threadId}/edit`;
+ window.location.href = `/${this.space}/rsocials/thread-editor/${d.threadId}/edit`;
}
}
});
diff --git a/modules/rsocials/components/folk-thread-builder.ts b/modules/rsocials/components/folk-thread-builder.ts
index 4a6f28e..441c80e 100644
--- a/modules/rsocials/components/folk-thread-builder.ts
+++ b/modules/rsocials/components/folk-thread-builder.ts
@@ -274,7 +274,7 @@ export class FolkThreadBuilder extends HTMLElement {
${tweetCards}
-
Edit Thread
+
Edit Thread
Copy Thread
Copy Link
@@ -289,7 +289,7 @@ export class FolkThreadBuilder extends HTMLElement {
diff --git a/modules/rsocials/components/folk-thread-gallery.ts b/modules/rsocials/components/folk-thread-gallery.ts
index 5682f32..a074066 100644
--- a/modules/rsocials/components/folk-thread-gallery.ts
+++ b/modules/rsocials/components/folk-thread-gallery.ts
@@ -96,7 +96,7 @@ export class FolkThreadGallery extends HTMLElement {
const cardsHTML = threads.length === 0
? ``
: `
${threads.map(t => {
@@ -164,7 +164,7 @@ export class FolkThreadGallery extends HTMLElement {
${cardsHTML}
diff --git a/modules/rsocials/mod.ts b/modules/rsocials/mod.ts
index 25a30b3..eb994dd 100644
--- a/modules/rsocials/mod.ts
+++ b/modules/rsocials/mod.ts
@@ -467,7 +467,7 @@ routes.get("/thread/:id", async (c) => {
}));
});
-routes.get("/thread/:id/edit", async (c) => {
+routes.get("/thread-editor/:id/edit", async (c) => {
const space = c.req.param("space") || "demo";
const dataSpace = (c.get("effectiveSpace" as any) as string) || space;
const id = c.req.param("id");
@@ -490,11 +490,11 @@ routes.get("/thread/:id/edit", async (c) => {
}));
});
-routes.get("/thread", (c) => {
+routes.get("/thread-editor", (c) => {
const space = c.req.param("space") || "demo";
const dataSpace = (c.get("effectiveSpace" as any) as string) || space;
return c.html(renderShell({
- title: `Thread Builder — rSocials | rSpace`,
+ title: `Thread Editor — rSocials | rSpace`,
moduleId: "rsocials",
spaceSlug: space,
modules: getModuleInfoList(),
@@ -522,8 +522,16 @@ routes.get("/threads", (c) => {
routes.get("/campaigns", (c) => {
const space = c.req.param("space") || "demo";
- const dataSpace = (c.get("effectiveSpace" as any) as string) || space;
- return c.redirect(`/${space}/rsocials/campaign`);
+ return c.html(renderShell({
+ title: `Campaigns — rSocials | rSpace`,
+ moduleId: "rsocials",
+ spaceSlug: space,
+ modules: getModuleInfoList(),
+ theme: "dark",
+ body: `
`,
+ styles: `
`,
+ scripts: ``,
+ }));
});
// ── Demo feed rendering (server-rendered, no web component needed) ──
@@ -615,20 +623,55 @@ routes.get("/landing", (c) => {
}));
});
-// ── Default: campaign planner canvas ──
+// ── Default: rSocials hub with navigation ──
routes.get("/", (c) => {
const space = c.req.param("space") || "demo";
- const dataSpace = (c.get("effectiveSpace" as any) as string) || space;
+ const base = `/${escapeHtml(space)}/rsocials`;
return c.html(renderShell({
- title: `${space} — rSocials | rSpace`,
+ title: `rSocials — ${space} | rSpace`,
moduleId: "rsocials",
spaceSlug: space,
modules: getModuleInfoList(),
- body: `
`,
- scripts: ``,
- styles: `
`,
theme: "dark",
+ styles: ``,
+ body: `
`,
}));
});
@@ -667,19 +710,7 @@ export const socialsModule: RSpaceModule = {
],
subPageInfos: [
{
- path: "thread",
- title: "Thread Builder",
- icon: "🧵",
- tagline: "rSocials Tool",
- description: "Compose, preview, and schedule tweet threads with a live card-by-card preview. Save drafts, generate share images, and publish when ready.",
- features: [
- { icon: "✍️", title: "Live Preview", text: "See your thread as tweet cards in real time as you type, with character counts and thread numbering." },
- { icon: "💾", title: "Save & Edit Drafts", text: "Save thread drafts to your space, revisit and refine them before publishing." },
- { icon: "🖼️", title: "Share Images", text: "Auto-generate a branded share image of your thread for cross-posting." },
- ],
- },
- {
- path: "campaign",
+ path: "campaigns",
title: "Campaign Manager",
icon: "📢",
tagline: "rSocials Tool",
@@ -697,5 +728,17 @@ export const socialsModule: RSpaceModule = {
tagline: "rSocials Tool",
description: "Browse all saved thread drafts in your community. Find inspiration, remix threads, or pick up where you left off.",
},
+ {
+ path: "thread-editor",
+ title: "Thread Editor",
+ icon: "🧵",
+ tagline: "rSocials Tool",
+ description: "Compose, preview, and schedule tweet threads with a live card-by-card preview. Save drafts, generate share images, and publish when ready.",
+ features: [
+ { icon: "✍️", title: "Live Preview", text: "See your thread as tweet cards in real time as you type, with character counts and thread numbering." },
+ { icon: "💾", title: "Save & Edit Drafts", text: "Save thread drafts to your space, revisit and refine them before publishing." },
+ { icon: "🖼️", title: "Share Images", text: "Auto-generate a branded share image of your thread for cross-posting." },
+ ],
+ },
],
};