Skip to content

feat(api): 🚀 add WebSocket support and integrate new SSO adapters#688

Open
aXenDeveloper wants to merge 1 commit intocanaryfrom
feat/websockets
Open

feat(api): 🚀 add WebSocket support and integrate new SSO adapters#688
aXenDeveloper wants to merge 1 commit intocanaryfrom
feat/websockets

Conversation

@aXenDeveloper
Copy link
Owner

  • Removed old Copilot instructions and added new guidelines in AGENTS.md.
  • Introduced WebSocket functionality using @hono/node-ws for real-time communication.
  • Updated SSO adapters to use SSOApiAdapter instead of SSOApiPlugin for better type safety.
  • Enhanced documentation for WebSocket and SSO integration in the API.
  • Updated various components and configurations to support the new WebSocket and SSO structures.

Improving Documentation

Description

What?

Why?

- Removed old Copilot instructions and added new guidelines in `AGENTS.md`.
- Introduced WebSocket functionality using `@hono/node-ws` for real-time communication.
- Updated SSO adapters to use `SSOApiAdapter` instead of `SSOApiPlugin` for better type safety.
- Enhanced documentation for WebSocket and SSO integration in the API.
- Updated various components and configurations to support the new WebSocket and SSO structures.
@vercel
Copy link

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vitnode-docs Error Error Mar 13, 2026 1:49pm

@github-actions github-actions bot added the 💡 Feature A new feature label Mar 13, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the VitNode API by introducing native WebSocket support for real-time interactions and refining the SSO integration mechanism for better developer experience and type safety. It also includes comprehensive updates to the project's documentation, providing clearer guidelines and expanding on core features, ensuring that developers have up-to-date resources for building and extending applications within the framework.

Highlights

  • WebSocket Support: Introduced WebSocket functionality into the API using @hono/node-ws, including a new /ws endpoint with basic connection handling and management. This lays the groundwork for real-time communication capabilities.
  • SSO Adapter Refactor: Refactored the Single Sign-On (SSO) system by renaming SSOApiPlugin to SSOApiAdapter across the codebase and documentation. This change improves type safety and clarity for integrating external SSO providers like Discord, Google, and Facebook.
  • Documentation Enhancements: Updated developer guidelines in AGENTS.md with new rules for React, TypeScript, and API usage. New documentation sections were added for WebSocket integration and different application types supported by VitNode.
  • Core API Integration: Integrated WebSocket management into the global API middleware, allowing WebsocketManager and WebsocketModel to be accessible via the Hono context. The blogApiPlugin was also added to the API configuration.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .github/copilot-instructions.md
    • Removed deprecated Copilot instructions.
  • AGENTS.md
    • Added new AI coding agent guidelines, including rules for React, Next.js, TypeScript, Hono.js, pnpm, Tailwind CSS, API usage, and animations.
  • apps/api/package.json
    • Added @hono/node-ws for WebSocket functionality.
    • Added @vitnode/blog workspace dependency.
  • apps/api/src/index.ts
    • Imported createNodeWebSocket to enable WebSocket support.
    • Implemented a /ws WebSocket endpoint with onOpen, onMessage, and onClose handlers.
    • Configured the Hono server to inject and upgrade WebSocket connections.
  • apps/api/src/vitnode.api.config.ts
    • Imported blogApiPlugin.
    • Registered blogApiPlugin in the API configuration.
  • apps/docs/content/docs/dev/index.mdx
    • Updated import statement for Tab and Tabs components.
    • Added a new section detailing different types of applications (Single App, Monorepo App, Only API).
  • apps/docs/content/docs/dev/meta.json
    • Added 'websocket' to the development documentation navigation.
  • apps/docs/content/docs/dev/sso/custom-adapter.mdx
    • Updated code examples and imports to use SSOApiAdapter instead of SSOApiPlugin.
  • apps/docs/content/docs/dev/sso/discord.mdx
    • Updated code examples and imports to use DiscordSSOApiAdapter instead of DiscordSSOApiPlugin.
  • apps/docs/content/docs/dev/sso/facebook.mdx
    • Updated code examples and imports to use FacebookSSOApiAdapter instead of FacebookSSOApiPlugin.
  • apps/docs/content/docs/dev/sso/google.mdx
    • Updated code examples and imports to use GoogleSSOApiAdapter instead of GoogleSSOApiPlugin.
  • apps/docs/content/docs/dev/websocket/index.mdx
    • Added new documentation file for WebSocket.
  • apps/docs/content/docs/dev/websocket/meta.json
    • Added metadata for the new WebSocket documentation.
  • apps/docs/src/content/docs/guides/sso/discord.mdx
    • Updated code examples and imports to use DiscordSSOApiAdapter instead of DiscordSSOApiPlugin.
  • apps/docs/src/content/docs/guides/sso/facebook.mdx
    • Updated code examples and imports to use FacebookSSOApiAdapter instead of FacebookSSOApiPlugin.
  • apps/docs/src/content/docs/guides/sso/google.mdx
    • Updated code examples and imports to use GoogleSSOApiAdapter instead of GoogleSSOApiPlugin.
  • apps/docs/src/vitnode.api.config.ts
    • Updated imports and usage of SSO providers to use SSOApiAdapter instead of SSOApiPlugin.
  • packages/vitnode/src/api/adapters/sso/discord.ts
    • Renamed SSOApiPlugin type to SSOApiAdapter in imports and function signatures.
  • packages/vitnode/src/api/adapters/sso/facebook.ts
    • Renamed SSOApiPlugin type to SSOApiAdapter in imports and function signatures.
  • packages/vitnode/src/api/adapters/sso/google.ts
    • Renamed SSOApiPlugin type to SSOApiAdapter in imports and function signatures.
  • packages/vitnode/src/api/lib/websocket.ts
    • Added WebsocketAdapter type definition.
    • Included a test function demonstrating WebSocket upgrade logic.
  • packages/vitnode/src/api/middlewares/global.middleware.ts
    • Imported WebsocketModel, WebsocketManager, and WebsocketManagerConfig.
    • Updated SSOApiPlugin type to SSOApiAdapter in EnvVariablesVitNode.
    • Added websocketManager configuration to EnvVariablesVitNode['core'].
    • Added websocket object with a test method to EnvVariablesVitNode.
    • Reordered email model initialization.
    • Initialized WebsocketManager and WebsocketModel within the global middleware.
  • packages/vitnode/src/api/models/sso.ts
    • Renamed the SSOApiPlugin interface to SSOApiAdapter.
  • packages/vitnode/src/api/models/websocket/manager.ts
    • Added WebsocketManagerConfig interface for WebSocket connection management.
    • Implemented WebsocketManager class to handle adding, removing, and retrieving WebSocket connections.
  • packages/vitnode/src/api/models/websocket/model.ts
    • Added WebsocketModel class with a test method for WebSocket operations.
  • packages/vitnode/src/hooks/use-websocket.ts
    • Added WebsocketContext for managing WebSocket connection state in React components.
  • packages/vitnode/src/views/layouts/provider.tsx
    • Imported WebsocketContext.
    • Wrapped Toaster and ProgressProvider with WebsocketContext.Provider.
  • packages/vitnode/src/vitnode.config.ts
    • Imported WebsocketAdapter type.
    • Updated SSOApiPlugin type to SSOApiAdapter in VitNodeApiConfig.
    • Added websocketAdapter optional property to VitNodeApiConfig.
  • pnpm-lock.yaml
    • Updated pnpm lock file to include new dependencies @hono/node-ws and @vitnode/blog.
    • Reflected other dependency updates and resolutions.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces WebSocket support to the VitNode API, including new dependencies (@hono/node-ws, @vitnode/blog), WebSocket server implementation in apps/api/src/index.ts, and corresponding documentation. It also renames SSOApiPlugin to SSOApiAdapter across core files and documentation for consistency. Review feedback highlights several areas for improvement: removing a trailing comma in the AGENTS.md guidelines, replacing console.log with structured logging in WebSocket event handlers for better observability, correcting the instantiation of SSO adapters in documentation examples by removing the new keyword to avoid TypeErrors, completing the WebsocketAdapter type definition to include all expected Hono WebSocket handlers, and removing a debugging test method from WebsocketModel for code cleanliness.


## Main Rules

- Use React 19.2, Next.js 16, TypeScript 5.9, Hono.js 4,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This list item has a trailing comma. For clarity and grammatical correctness in documentation, it should be removed.

Suggested change
- Use React 19.2, Next.js 16, TypeScript 5.9, Hono.js 4,
- Use React 19.2, Next.js 16, TypeScript 5.9, Hono.js 4

Comment on lines +19 to +31
upgradeWebSocket(c => ({
onOpen(event, ws) {
const user = c.get("user");
console.log("Connection opened", event, ws, user);
},
onMessage(event, ws) {
console.log(`Message from client`, event.data);
ws.send("Hello from server!");
},
onClose: () => {
console.log("Connection closed");
},
})),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The WebSocket event handlers use console.log for logging. For better observability and to align with the rest of the application, please use the structured logger available via c.get('log'). This will also prevent logging potentially large or sensitive objects like event and ws directly to the console.

Suggested change
upgradeWebSocket(c => ({
onOpen(event, ws) {
const user = c.get("user");
console.log("Connection opened", event, ws, user);
},
onMessage(event, ws) {
console.log(`Message from client`, event.data);
ws.send("Hello from server!");
},
onClose: () => {
console.log("Connection closed");
},
})),
upgradeWebSocket(c => ({
onOpen(event, ws) {
const user = c.get("user");
c.get("log").info({ userId: user?.id }, "WebSocket connection opened");
},
onMessage(event, ws) {
c.get("log").info({ data: event.data }, "Message from client");
ws.send("Hello from server!");
},
onClose: () => {
c.get("log").info("WebSocket connection closed");
},
}))

ssoAdapters: [
// [!code ++]
new DiscordSSOApiPlugin({
new DiscordSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The DiscordSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      DiscordSSOApiAdapter({

ssoAdapters: [
// [!code ++]
new FacebookSSOApiPlugin({
new FacebookSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The FacebookSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      FacebookSSOApiAdapter({

ssoAdapters: [
// [!code ++]
new GoogleSSOApiPlugin({
new GoogleSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The GoogleSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      GoogleSSOApiAdapter({

ssoAdapters: [
// [!code ++]
new DiscordSSOApiPlugin({
new DiscordSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The DiscordSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      DiscordSSOApiAdapter({

ssoAdapters: [
// [!code ++]
new FacebookSSOApiPlugin({
new FacebookSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The FacebookSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      FacebookSSOApiAdapter({

ssoAdapters: [
// [!code ++]
new GoogleSSOApiPlugin({
new GoogleSSOApiAdapter({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The GoogleSSOApiAdapter is a factory function, not a class constructor. Using the new keyword here is incorrect and will result in a TypeError. Please remove new to correctly call the function.

      GoogleSSOApiAdapter({

Comment on lines +5 to +7
export type WebsocketAdapter = (c: Context) => {
onOpen: () => void;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The WebsocketAdapter type is incomplete. The onOpen handler should accept arguments, and other handlers like onMessage, onClose, and onError are missing. Please update the type to accurately represent the WebSocket handlers provided by Hono, as shown in the example implementation in this file.

export type WebsocketAdapter = (c: Context) => {
  onOpen?: (evt: Event, ws: WSContext) => void;
  onMessage?: (event: MessageEvent, ws: WSContext) => void;
  onClose?: (event: CloseEvent, ws: WSContext) => void;
  onError?: (error: Error, ws: WSContext) => void;
};

Comment on lines +10 to +14
test() {
console.log("WebsocketModel test method called");

const user = this.c.get("user");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test method appears to be for debugging purposes. It contains a console.log statement and an unused user variable. This should be removed before merging to keep the model clean.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5d73304ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

cronSecret: CONFIG.cronJobSecret,
plugins: pluginsMetadata,
cron: cronMetadata,
websocketManager: new WebsocketManager(c),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reuse a single WebsocketManager across requests

globalMiddleware creates new WebsocketManager(c) inside the per-request handler, so each HTTP/WebSocket upgrade gets its own fresh connections map and previously tracked sockets are never visible to later requests. Any feature that relies on getConnection/getAllConnections for cross-client messaging (broadcast, targeted push, cleanup) will silently fail because the registry is request-scoped instead of process-scoped.

Useful? React with 👍 / 👎.

type: "cloudflare_turnstile" | "recaptcha_v3";
};
cronAdapter?: CronAdapter;
websocketAdapter?: WebsocketAdapter;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wire websocketAdapter into API startup

This commit adds websocketAdapter to the public VitNodeApiConfig, but the API bootstrap path does not consume it, so setting this option has no runtime effect. That creates a misleading public contract where users can configure an adapter that is never invoked, and WebSocket behavior remains hardcoded elsewhere.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 Feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant