How the Share Router in y-gui Facilitates Chat Conversation Sharing

The share router in y-gui delegates all /api/share/* requests to a common handler that distinguishes between public GET requests for retrieving shared chats and authenticated POST requests for creating new shares, enabling secure public access to private conversations through unique share IDs.

The y-gui application provides a streamlined mechanism for converting private chat conversations into publicly accessible links through its share router architecture. This system allows authenticated users to generate shareable copies of specific conversations while maintaining strict separation between private original chats and their public derivatives.

Share Router Architecture and Request Delegation

The share router is implemented in backend/src/api/share-router.ts as a lightweight Hono router that captures all traffic under the /api/share/* namespace. Rather than defining separate handlers for each HTTP method, the router delegates every request to a centralized handleShareRequest function with conditional authentication parameters.

Public GET Requests for Anonymous Access

When the HTTP method is GET, the router invokes handleShareRequest without passing a userPrefix, allowing anyone with the correct share ID to retrieve the conversation data:

// backend/src/api/share-router.ts
if (c.req.method === 'GET') {
  return handleShareRequest(request, c.env);   // no userPrefix for public access
}

Authenticated POST Requests for Share Creation

For non-GET methods (primarily POST), the router extracts the userPrefix from the request context and forwards it to the handler. This ensures only authenticated owners can create new shared copies:

// backend/src/api/share-router.ts
return handleShareRequest(request, c.env, c.get('userPrefix'));

ShareService Implementation and Data Flow

The ShareService class in backend/src/serivce/share.ts contains the core business logic for cloning conversations and managing public access.

Creating Shared Conversations

The createShare(chatId, messageId?) method clones the original chat, preserves references to the source via origin_chat_id and origin_message_id, optionally truncates the conversation to a specific message subtree, generates a unique public ID, and persists the copy to a public-only repository:

// backend/src/serivce/share.ts
const sharedChat: Chat = {
  ...chat,
  id: shareId,
  origin_chat_id: chatId,
  origin_message_id: messageId,
};
await this.publicChatRepository.saveChat(sharedChat);

Retrieving Shared Data

The getSharedChat(shareId) method queries the public repository directly, returning the shared conversation data without authentication checks, as the share ID itself acts as the access token.

API Endpoints and Handler Integration

The API handler in backend/src/api/share.ts bridges the router and service layer, exposing two primary endpoints:

  1. POST /api/share/:chatId – Creates a new share by parsing an optional messageId from the JSON body, invoking shareService.createShare, and returning the generated shareId.
  2. GET /api/share/:shareId – Retrieves the shared conversation by calling shareService.getSharedChat and returning the chat JSON.

Practical Example: Creating and Accessing Shared Chats

The following example demonstrates the complete flow from creating an authenticated share to publicly retrieving the conversation:


# Create a share (requires authentication)

curl -X POST "https://your-y-gui.com/api/share/12345" \
     -H "Authorization: Bearer <user-token>" \
     -H "Content-Type: application/json" \
     -d '{"messageId":"m-abcde"}'

# Response: {"shareId":"sh-9f8e7d"}

# Retrieve the shared conversation (public access)

curl "https://your-y-gui.com/api/share/sh-9f8e7d"

# Response: { "id":"sh-9f8e7d", "origin_chat_id":"12345", "messages":[...] }

Summary

  • The share router in backend/src/api/share-router.ts centralizes request handling under /api/share/*, delegating to handleShareRequest while conditionally applying authentication based on HTTP method.
  • GET requests operate without userPrefix validation, enabling anonymous public access to shared conversations using unique share IDs.
  • POST requests require the userPrefix extracted from the request context, ensuring only authenticated owners can create new shared copies.
  • The ShareService in backend/src/serivce/share.ts handles the cloning logic, preserving origin_chat_id and origin_message_id references while storing data in a public-only repository.
  • The type definitions in shared/types/index.ts define the Chat structure that supports these sharing relationships.

Frequently Asked Questions

What is the role of the userPrefix in the y-gui share router?

The userPrefix serves as the authentication identifier extracted from the request context. The share router only includes this parameter when handling non-GET requests (like POST), allowing the ShareService to verify that the requesting user owns the original chat before creating a public copy. GET requests intentionally omit this parameter to enable anonymous access to shared conversations.

How does y-gui distinguish between the original chat and a shared copy?

According to the source code in backend/src/serivce/share.ts and type definitions in shared/types/index.ts, shared chats contain origin_chat_id and origin_message_id fields that reference the original conversation. The shared copy receives a new unique shareId and is stored in a separate public repository, maintaining isolation between private originals and public derivatives.

Can shared conversations be truncated to specific message threads?

Yes. When creating a share via POST /api/share/:chatId, the request body can include an optional messageId parameter. The createShare method in backend/src/serivce/share.ts uses this ID to trim the conversation to a specific subtree, allowing users to share partial conversation histories rather than complete chats.

Is it possible to revoke or delete a shared conversation?

While the current implementation focuses on creation and retrieval, the share router's architecture in backend/src/api/share-router.ts supports extensibility. Because all requests route through handleShareRequest, adding a DELETE method handler would require minimal changes to the routing logic while leveraging the existing authentication pattern for ownership verification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →