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:
- POST
/api/share/:chatId– Creates a new share by parsing an optionalmessageIdfrom the JSON body, invokingshareService.createShare, and returning the generatedshareId. - GET
/api/share/:shareId– Retrieves the shared conversation by callingshareService.getSharedChatand 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.tscentralizes request handling under/api/share/*, delegating tohandleShareRequestwhile conditionally applying authentication based on HTTP method. - GET requests operate without
userPrefixvalidation, enabling anonymous public access to shared conversations using unique share IDs. - POST requests require the
userPrefixextracted from the request context, ensuring only authenticated owners can create new shared copies. - The
ShareServiceinbackend/src/serivce/share.tshandles the cloning logic, preservingorigin_chat_idandorigin_message_idreferences while storing data in a public-only repository. - The type definitions in
shared/types/index.tsdefine theChatstructure 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →