diff --git a/examples/actor-actions/README.md b/examples/actor-actions/README.md new file mode 100644 index 0000000000..71bb29b124 --- /dev/null +++ b/examples/actor-actions/README.md @@ -0,0 +1,17 @@ +# Actor Actions + +Demonstrates how to define and call actions on Rivet Actors for RPC-style communication between actors and clients. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/actor-actions +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/quickstart-actions/package.json b/examples/actor-actions/package.json similarity index 91% rename from examples/quickstart-actions/package.json rename to examples/actor-actions/package.json index e5b80564fe..37c08cabbc 100644 --- a/examples/quickstart-actions/package.json +++ b/examples/actor-actions/package.json @@ -1,5 +1,5 @@ { - "name": "quickstart-actions", + "name": "actor-actions", "version": "2.0.21", "private": true, "type": "module", @@ -33,6 +33,8 @@ ], "tags": [ "quickstart" - ] - } + ], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/quickstart-actions/src/backend/registry.ts b/examples/actor-actions/src/backend/registry.ts similarity index 100% rename from examples/quickstart-actions/src/backend/registry.ts rename to examples/actor-actions/src/backend/registry.ts diff --git a/examples/counter/src/server.ts b/examples/actor-actions/src/backend/server.ts similarity index 100% rename from examples/counter/src/server.ts rename to examples/actor-actions/src/backend/server.ts diff --git a/examples/quickstart-actions/src/frontend/App.tsx b/examples/actor-actions/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-actions/src/frontend/App.tsx rename to examples/actor-actions/src/frontend/App.tsx diff --git a/examples/quickstart-actions/src/frontend/index.html b/examples/actor-actions/src/frontend/index.html similarity index 100% rename from examples/quickstart-actions/src/frontend/index.html rename to examples/actor-actions/src/frontend/index.html diff --git a/examples/quickstart-actions/src/frontend/main.tsx b/examples/actor-actions/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-actions/src/frontend/main.tsx rename to examples/actor-actions/src/frontend/main.tsx diff --git a/examples/quickstart-actions/tests/actions.test.ts b/examples/actor-actions/tests/actions.test.ts similarity index 100% rename from examples/quickstart-actions/tests/actions.test.ts rename to examples/actor-actions/tests/actions.test.ts diff --git a/examples/quickstart-actions/tsconfig.json b/examples/actor-actions/tsconfig.json similarity index 100% rename from examples/quickstart-actions/tsconfig.json rename to examples/actor-actions/tsconfig.json diff --git a/examples/counter-serverless/turbo.json b/examples/actor-actions/turbo.json similarity index 100% rename from examples/counter-serverless/turbo.json rename to examples/actor-actions/turbo.json diff --git a/examples/quickstart-actions/vite.config.ts b/examples/actor-actions/vite.config.ts similarity index 100% rename from examples/quickstart-actions/vite.config.ts rename to examples/actor-actions/vite.config.ts diff --git a/examples/quickstart-actions/vitest.config.ts b/examples/actor-actions/vitest.config.ts similarity index 100% rename from examples/quickstart-actions/vitest.config.ts rename to examples/actor-actions/vitest.config.ts diff --git a/examples/ai-agent/README.md b/examples/ai-agent/README.md index be203caa8e..b0a3a1452b 100644 --- a/examples/ai-agent/README.md +++ b/examples/ai-agent/README.md @@ -1,40 +1,17 @@ -# AI Agent Chat for RivetKit +# AI Agent Chat -Example project demonstrating AI agent integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating AI agent integration. ## Getting Started -### Prerequisites - -- Node.js 18+ -- OpenAI API key - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/ai-agent +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/ai-agent npm install -``` - -### Development - -1. Set your OpenAI API key: -```sh -export OPENAI_API_KEY=your-api-key-here -``` - -2. Start the development server: -```sh npm run dev ``` -3. Open your browser to `http://localhost:3000` ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/ai-agent/package.json b/examples/ai-agent/package.json index 195432e893..45b446475e 100644 --- a/examples/ai-agent/package.json +++ b/examples/ai-agent/package.json @@ -39,6 +39,8 @@ "tags": [ "ai", "real-time" - ] - } + ], + "priority": 100 + }, + "license": "MIT" } diff --git a/examples/ai-and-user-generated-actors-freestyle/README.md b/examples/ai-and-user-generated-actors-freestyle/README.md index 2ea03a4bb3..1ad81fd61b 100644 --- a/examples/ai-and-user-generated-actors-freestyle/README.md +++ b/examples/ai-and-user-generated-actors-freestyle/README.md @@ -1,8 +1,20 @@ -# User and AI Generated Rivet Actors Freestyle Deployer +# User and AI Generated Actors Freestyle Deployer Shows how to deploy user or AI-generated Rivet Actor code using a sandboxed namespace and Freestyle -[View Full Documentation](https://rivet.dev/docs/actors/ai-and-user-generated-actors) +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/ai-and-user-generated-actors-freestyle +npm install +npm run dev +``` + + +## Documentation + +View documentation on [AI and user generated actors](https://rivet.dev/docs/actors/ai-and-user-generated-actors). ## Features @@ -19,32 +31,6 @@ The logic lives in `src/backend/`: 3. **Deploys actor and frontend to Freestyle**: Builds the project and deploys to Freestyle (see [`src/backend/utils.ts`](src/backend/utils.ts)) 4. **Configures Rivet to connect to Freestyle**: Sets up the Rivet runner to point to the Rivet deployment for running the actors -## Getting Started - -### Prerequisites - -- Node.js 18+ and pnpm -- A [Freestyle](https://freestyle.sh) account and API key -- Either: - - [Rivet Cloud](https://dashboard.rivet.dev/) account with API token, or - - [Self-hosted Rivet instance](https://www.rivet.dev/docs/self-hosting/) with endpoint and token - -### Installation - -```bash -pnpm install -``` - -### Running the Application - -Start both the frontend and backend servers: - -```bash -pnpm dev -``` - -Open http://localhost:5173 in your browser. - ## Usage ### Rivet Cloud diff --git a/examples/ai-and-user-generated-actors-freestyle/package.json b/examples/ai-and-user-generated-actors-freestyle/package.json index 54ae8d2b57..1a895cccf1 100644 --- a/examples/ai-and-user-generated-actors-freestyle/package.json +++ b/examples/ai-and-user-generated-actors-freestyle/package.json @@ -17,7 +17,7 @@ "@hono/node-server": "^1.13.8", "@monaco-editor/react": "^4.7.0", "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@715f221", - "@rivetkit/engine-api-full": "^25.7.2", + "@rivetkit/engine-api-full": "latest", "dotenv": "^17.2.2", "execa": "^9.5.2", "freestyle-sandboxes": "^0.0.95", @@ -35,5 +35,17 @@ "typescript": "^5.5.2", "vite": "^5.0.0", "vitest": "^2.1.8" - } + }, + "template": { + "technologies": [ + "react", + "hono", + "typescript" + ], + "tags": [ + "ai" + ], + "priority": 400 + }, + "license": "MIT" } diff --git a/examples/counter/turbo.json b/examples/ai-and-user-generated-actors-freestyle/turbo.json similarity index 100% rename from examples/counter/turbo.json rename to examples/ai-and-user-generated-actors-freestyle/turbo.json diff --git a/examples/counter-next-js/.gitignore b/examples/chat-room-next-js/.gitignore similarity index 100% rename from examples/counter-next-js/.gitignore rename to examples/chat-room-next-js/.gitignore diff --git a/examples/chat-room-next-js/README.md b/examples/chat-room-next-js/README.md new file mode 100644 index 0000000000..a0e0911ece --- /dev/null +++ b/examples/chat-room-next-js/README.md @@ -0,0 +1,17 @@ +# Chat Room (Next.js) + +Next.js chat room demonstrating real-time messaging with actor state management. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/chat-room-next-js +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/counter-next-js/next.config.ts b/examples/chat-room-next-js/next.config.ts similarity index 100% rename from examples/counter-next-js/next.config.ts rename to examples/chat-room-next-js/next.config.ts diff --git a/examples/counter-next-js/package.json b/examples/chat-room-next-js/package.json similarity index 77% rename from examples/counter-next-js/package.json rename to examples/chat-room-next-js/package.json index 8440973862..eb37739908 100644 --- a/examples/counter-next-js/package.json +++ b/examples/chat-room-next-js/package.json @@ -1,5 +1,5 @@ { - "name": "example-counter-next-js", + "name": "chat-room-next-js", "version": "2.0.21", "private": true, "scripts": { @@ -7,7 +7,7 @@ "build": "next build", "start": "next start", "lint": "next lint", - "connect": "tsx scripts/connect.ts" + "check-types": "tsc --noEmit" }, "dependencies": { "react": "19.1.0", @@ -20,10 +20,8 @@ "typescript": "^5", "@types/node": "^20", "@types/react": "^19", - "@types/react-dom": "^19", - "tsx": "^3.12.7" + "@types/react-dom": "^19" }, - "stableVersion": "0.8.0", "template": { "technologies": [ "next-js", @@ -33,5 +31,6 @@ "tags": [ "real-time" ] - } + }, + "license": "MIT" } diff --git a/examples/counter-next-js/src/app/api/rivet/[...all]/route.ts b/examples/chat-room-next-js/src/app/api/rivet/[...all]/route.ts similarity index 100% rename from examples/counter-next-js/src/app/api/rivet/[...all]/route.ts rename to examples/chat-room-next-js/src/app/api/rivet/[...all]/route.ts diff --git a/examples/next-js/src/app/favicon.ico b/examples/chat-room-next-js/src/app/favicon.ico similarity index 100% rename from examples/next-js/src/app/favicon.ico rename to examples/chat-room-next-js/src/app/favicon.ico diff --git a/examples/chat-room-next-js/src/app/globals.css b/examples/chat-room-next-js/src/app/globals.css new file mode 100644 index 0000000000..24fa51ff25 --- /dev/null +++ b/examples/chat-room-next-js/src/app/globals.css @@ -0,0 +1,463 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Roboto, sans-serif; + background: #000000; + height: 100vh; + overflow: hidden; + margin: 0; + padding: 0; +} + +.app { + display: flex; + height: 100vh; + width: 100vw; + background: #000000; + overflow: hidden; +} + +/* Sidebar */ +.sidebar { + width: 280px; + background: #1c1c1e; + border-right: 1px solid #2c2c2e; + display: flex; + flex-direction: column; +} + +.sidebar-header { + padding: 20px 20px; + border-bottom: 1px solid #2c2c2e; + display: flex; + justify-content: space-between; + align-items: center; + height: 60px; + box-sizing: border-box; +} + +.logo { + display: flex; + align-items: center; + gap: 12px; +} + +.logo h1 { + font-size: 18px; + font-weight: 500; + color: #ffffff; +} + +.close-sidebar { + display: none; + background: none; + border: none; + color: #8e8e93; + cursor: pointer; + padding: 8px; + border-radius: 6px; + transition: all 0.2s ease; +} + +.close-sidebar:hover { + background: #3a3a3c; + color: #ffffff; +} + +.user-settings { + padding: 20px; + flex: 1; +} + +.setting-group { + margin-bottom: 20px; +} + +.setting-group label { + display: block; + font-size: 14px; + font-weight: 600; + color: #8e8e93; + margin-bottom: 8px; +} + +.setting-input { + width: 100%; + padding: 10px 14px; + border: 1px solid #3a3a3c; + border-radius: 8px; + font-size: 14px; + transition: all 0.2s ease; + background: #2c2c2e; + color: #ffffff; +} + +.setting-input:focus { + outline: none; + border-color: #007aff; + box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); +} + +.setting-input::placeholder { + color: #8e8e93; +} + +.connection-status { + padding: 20px; + border-top: 1px solid #2c2c2e; + height: 60px; + box-sizing: border-box; + display: flex; + align-items: center; +} + +.status-indicator { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 500; +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + transition: background-color 0.2s ease; +} + +.status-indicator.connected .status-dot { + background-color: #30d158; +} + +.status-indicator.disconnected .status-dot { + background-color: #ff3b30; +} + +.status-indicator.connected { + color: #30d158; +} + +.status-indicator.disconnected { + color: #ff3b30; +} + +/* Chat Container */ +.chat-container { + flex: 1; + display: flex; + flex-direction: column; + background: #000000; +} + +.chat-header { + padding: 12px 20px; + border-bottom: 1px solid #2c2c2e; + background: #1c1c1e; + display: flex; + align-items: center; + gap: 12px; +} + +.menu-button { + display: none; + background: none; + border: none; + color: #8e8e93; + cursor: pointer; + padding: 8px; + border-radius: 6px; + transition: all 0.2s ease; +} + +.menu-button:hover { + background: #3a3a3c; + color: #ffffff; +} + +.room-info h2 { + font-size: 16px; + font-weight: 600; + color: #ffffff; + margin-bottom: 2px; +} + +.room-info p { + font-size: 12px; + color: #8e8e93; +} + +.messages-container { + flex: 1; + overflow-y: auto; + background: #000000; +} + +.messages { + padding: 16px 20px; + min-height: 100%; +} + +.message-wrapper { + display: flex; + margin-bottom: 12px; + align-items: flex-end; +} + +.message-wrapper.own { + flex-direction: row-reverse; +} + +.message-avatar { + margin-right: 12px; + flex-shrink: 0; +} + +.message-wrapper.own .message-avatar { + margin-right: 0; + margin-left: 12px; +} + +.avatar { + width: 32px; + height: 32px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + font-weight: 600; + color: white; + text-transform: uppercase; +} + +.avatar-spacer { + width: 32px; + margin-right: 12px; +} + +.message-wrapper.own .avatar-spacer { + margin-right: 0; + margin-left: 12px; +} + +.message-content { + max-width: 70%; + display: flex; + flex-direction: column; +} + +.message-wrapper.own .message-content { + align-items: flex-end; +} + +.message-sender { + font-size: 12px; + font-weight: 600; + color: #64748b; + margin-bottom: 4px; + margin-left: 4px; +} + +.message-wrapper.own .message-sender { + margin-left: 0; + margin-right: 4px; +} + +.message-bubble { + padding: 10px 14px; + border-radius: 16px; + position: relative; + word-wrap: break-word; + max-width: 100%; +} + +.message-bubble.other { + background: #2c2c2e; + border: none; + border-bottom-left-radius: 4px; + color: #ffffff; +} + +.message-bubble.own { + background: #007aff; + color: white; + border-bottom-right-radius: 4px; +} + +.message-text { + font-size: 15px; + line-height: 1.3; + margin-bottom: 3px; +} + +.message-time { + font-size: 11px; + opacity: 0.5; +} + +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + text-align: center; + color: #8e8e93; +} + +.empty-icon { + font-size: 48px; + margin-bottom: 16px; +} + +.empty-state h3 { + font-size: 18px; + font-weight: 600; + color: #ffffff; + margin-bottom: 8px; +} + +.empty-state p { + font-size: 14px; +} + +.input-container { + padding: 12px 20px; + border-top: 1px solid #2c2c2e; + background: #1c1c1e; + height: 60px; + box-sizing: border-box; + display: flex; + align-items: center; +} + +.input-wrapper { + display: flex; + align-items: center; + gap: 8px; + background: #2c2c2e; + border: 1px solid #3a3a3c; + border-radius: 20px; + padding: 6px 6px 6px 16px; + transition: all 0.2s ease; + width: 100%; +} + +.input-wrapper:focus-within { + border-color: #007aff; + box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); +} + +.message-input { + flex: 1; + border: none; + background: transparent; + font-size: 15px; + outline: none; + resize: none; + color: #ffffff; +} + +.message-input::placeholder { + color: #8e8e93; +} + +.send-button { + width: 32px; + height: 32px; + border: none; + border-radius: 50%; + background: #007aff; + color: white; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.2s ease; + flex-shrink: 0; +} + +.send-button:hover:not(:disabled) { + background: #0056cc; + transform: scale(1.05); +} + +.send-button:disabled { + background: #3a3a3c; + cursor: not-allowed; + transform: none; +} + +/* Scrollbar Styling */ +.messages-container::-webkit-scrollbar { + width: 6px; +} + +.messages-container::-webkit-scrollbar-track { + background: transparent; +} + +.messages-container::-webkit-scrollbar-thumb { + background: #3a3a3c; + border-radius: 3px; +} + +.messages-container::-webkit-scrollbar-thumb:hover { + background: #48484a; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .app { + height: 100vh; + } + + .sidebar { + width: 100%; + position: absolute; + z-index: 10; + transform: translateX(-100%); + transition: transform 0.3s ease; + } + + .sidebar.open { + transform: translateX(0); + } + + .close-sidebar { + display: block; + } + + .menu-button { + display: block; + } + + .chat-container { + width: 100%; + } + + .message-content { + max-width: 85%; + } +} + +/* Animation for new messages */ +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.message-wrapper { + animation: slideIn 0.3s ease; +} diff --git a/examples/counter-next-js/src/app/layout.tsx b/examples/chat-room-next-js/src/app/layout.tsx similarity index 87% rename from examples/counter-next-js/src/app/layout.tsx rename to examples/chat-room-next-js/src/app/layout.tsx index c4f1400687..9e2c27453e 100644 --- a/examples/counter-next-js/src/app/layout.tsx +++ b/examples/chat-room-next-js/src/app/layout.tsx @@ -13,8 +13,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Rivet Counter", - description: "Real-time counter powered by RivetKit", + title: "Rivet Chat", + description: "Real-time chat powered by RivetKit", }; export default function RootLayout({ diff --git a/examples/next-js/src/app/page.module.css b/examples/chat-room-next-js/src/app/page.module.css similarity index 100% rename from examples/next-js/src/app/page.module.css rename to examples/chat-room-next-js/src/app/page.module.css diff --git a/examples/chat-room-next-js/src/app/page.tsx b/examples/chat-room-next-js/src/app/page.tsx new file mode 100644 index 0000000000..8dd238dd61 --- /dev/null +++ b/examples/chat-room-next-js/src/app/page.tsx @@ -0,0 +1,5 @@ +import { ChatRoom } from "@/components/ChatRoom"; + +export default function Home() { + return ; +} diff --git a/examples/next-js/src/components/ChatRoom.tsx b/examples/chat-room-next-js/src/components/ChatRoom.tsx similarity index 100% rename from examples/next-js/src/components/ChatRoom.tsx rename to examples/chat-room-next-js/src/components/ChatRoom.tsx diff --git a/examples/chat-room-next-js/src/rivet/registry.ts b/examples/chat-room-next-js/src/rivet/registry.ts new file mode 100644 index 0000000000..40ab853108 --- /dev/null +++ b/examples/chat-room-next-js/src/rivet/registry.ts @@ -0,0 +1,32 @@ +import { actor, setup } from "rivetkit"; + +export type Message = { sender: string; text: string; timestamp: number }; + +export const chatRoom = actor({ + options: { + sleepTimeout: 2000, + }, + // Persistent state that survives restarts + state: { + messages: [] as Message[], + }, + + actions: { + // Callable functions from clients + sendMessage: (c, sender: string, text: string) => { + const message = { sender, text, timestamp: Date.now() }; + // State changes are automatically persisted + c.state.messages.push(message); + // Send events to all connected clients + c.broadcast("newMessage", message); + return message; + }, + + getHistory: (c) => c.state.messages, + }, +}); + +// Register actors for use +export const registry = setup({ + use: { chatRoom }, +}); diff --git a/examples/counter-next-js/tsconfig.json b/examples/chat-room-next-js/tsconfig.json similarity index 100% rename from examples/counter-next-js/tsconfig.json rename to examples/chat-room-next-js/tsconfig.json diff --git a/examples/starter/turbo.json b/examples/chat-room-next-js/turbo.json similarity index 100% rename from examples/starter/turbo.json rename to examples/chat-room-next-js/turbo.json diff --git a/examples/chat-room/README.md b/examples/chat-room/README.md index 25ae130960..6132b6ad96 100644 --- a/examples/chat-room/README.md +++ b/examples/chat-room/README.md @@ -1,43 +1,16 @@ -# Chat Room for RivetKit +# Chat Room -Example project demonstrating real-time messaging and actor state management with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating real-time messaging and actor state management. ## Getting Started -### Prerequisites - -- Node.js 18+ - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/chat-room +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/chat-room npm install -``` - -### Development - -#### Web UI -Start the development server with both backend and React frontend: - -```sh npm run dev ``` -Open your browser to `http://localhost:3000` to use the web chat interface. - -#### CLI Interface - -Alternatively, use the CLI interface: - -```sh -npm run dev:cli -``` ## Features @@ -49,4 +22,4 @@ npm run dev:cli ## License -Apache 2.0 +MIT diff --git a/examples/chat-room/package.json b/examples/chat-room/package.json index 801df2734d..70906ee1d0 100644 --- a/examples/chat-room/package.json +++ b/examples/chat-room/package.json @@ -38,6 +38,8 @@ ], "tags": [ "real-time" - ] - } + ], + "priority": 200 + }, + "license": "MIT" } diff --git a/examples/cloudflare-workers-hono/README.md b/examples/cloudflare-workers-hono/README.md index 15068c25bb..b9bab7d621 100644 --- a/examples/cloudflare-workers-hono/README.md +++ b/examples/cloudflare-workers-hono/README.md @@ -1,63 +1,17 @@ -# Cloudflare Workers with Hono for RivetKit +# Cloudflare Workers with Hono -Example project demonstrating Cloudflare Workers deployment with Hono router using [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating Cloudflare Workers deployment with Hono router. ## Getting Started -### Prerequisites - -- Node.js -- Cloudflare account with Actors enabled -- Wrangler CLI installed globally (`npm install -g wrangler`) - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/cloudflare-workers-hono +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cloudflare-workers-hono npm install -``` - -### Development - -```sh npm run dev ``` -This will start the Cloudflare Workers development server locally at http://localhost:8787. - -### Testing the Application - -You can test the Hono router endpoint by making a POST request to increment a counter: - -```sh -curl -X POST http://localhost:8787/increment/my-counter -``` - -Or run the client script to interact with your actors: - -```sh -npm run client -``` - -### Deploy to Cloudflare - -First, authenticate with Cloudflare: - -```sh -wrangler login -``` - -Then deploy: - -```sh -npm run deploy -``` ## License -Apache 2.0 +MIT diff --git a/examples/cloudflare-workers-hono/package.json b/examples/cloudflare-workers-hono/package.json index acba2aaf46..eb3379765d 100644 --- a/examples/cloudflare-workers-hono/package.json +++ b/examples/cloudflare-workers-hono/package.json @@ -28,6 +28,8 @@ "hono", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/cloudflare-workers-inline-client/README.md b/examples/cloudflare-workers-inline-client/README.md index a522c3f103..146d122bcc 100644 --- a/examples/cloudflare-workers-inline-client/README.md +++ b/examples/cloudflare-workers-inline-client/README.md @@ -4,30 +4,14 @@ Simple example demonstrating accessing Rivet Actors via Cloudflare Workers witho ## Getting Started -Install dependencies: - -```sh -pnpm install -``` - -Start the development server: - -```sh -pnpm run dev -``` - -In a separate terminal, test the endpoint: - ```sh -pnpm run client-http +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cloudflare-workers-inline-client +npm install +npm run dev ``` -Or: - -```sh -pnpm run client-rivetkit -``` ## License -Apache 2.0 +MIT diff --git a/examples/cloudflare-workers-inline-client/package.json b/examples/cloudflare-workers-inline-client/package.json index cfff982c60..43b52b24be 100644 --- a/examples/cloudflare-workers-inline-client/package.json +++ b/examples/cloudflare-workers-inline-client/package.json @@ -27,6 +27,8 @@ "cloudflare-workers", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/cloudflare-workers/README.md b/examples/cloudflare-workers/README.md index 118113f8f4..5387ab60f0 100644 --- a/examples/cloudflare-workers/README.md +++ b/examples/cloudflare-workers/README.md @@ -1,57 +1,17 @@ -# Cloudflare Workers for RivetKit +# Cloudflare Workers -Example project demonstrating Cloudflare Workers deployment with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating Cloudflare Workers deployment. ## Getting Started -### Prerequisites - -- Node.js -- Cloudflare account with Actors enabled -- Wrangler CLI installed globally (`npm install -g wrangler`) - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/cloudflare-workers +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cloudflare-workers npm install -``` - -### Development - -```sh npm run dev ``` -This will start the Cloudflare Workers development server locally at http://localhost:8787. - -### Testing the Client - -In a separate terminal, run the client script to interact with your actors: - -```sh -npm run client -``` - -### Deploy to Cloudflare - -First, authenticate with Cloudflare: - -```sh -wrangler login -``` - -Then deploy: - -```sh -npm run deploy -``` ## License -Apache 2.0 +MIT diff --git a/examples/cloudflare-workers/package.json b/examples/cloudflare-workers/package.json index 365fca9878..a6f3749b04 100644 --- a/examples/cloudflare-workers/package.json +++ b/examples/cloudflare-workers/package.json @@ -26,6 +26,8 @@ "cloudflare-workers", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/counter-next-js/README.md b/examples/counter-next-js/README.md deleted file mode 100644 index 4409287b70..0000000000 --- a/examples/counter-next-js/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# Counter for RivetKit (Next.js) - -Example Next.js project demonstrating basic actor state management and real-time updates with [RivetKit](https://rivetkit.org). - -This example combines the counter functionality from the basic counter example with a Next.js application structure. - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) - -## Getting Started - -### Prerequisites - -- Node.js - -### Installation - -```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/counter-next-js -pnpm install -``` - -### Development - -```sh -pnpm dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the counter in action. - -The counter is shared across all clients using the same Counter ID. Try opening the page in multiple tabs or browsers to see real-time synchronization! - -### Testing with the Connect Script - -Run the connect script to interact with the counter from the command line: - -```sh -pnpm connect -``` - -This will connect to the counter and increment it every second. You'll see the updates in both the terminal and the web interface! - -## Features - -- Real-time counter synchronization across multiple clients -- Next.js 15 with App Router -- TypeScript support -- Customizable counter IDs for multiple independent counters - -## License - -Apache 2.0 diff --git a/examples/counter-next-js/src/app/globals.css b/examples/counter-next-js/src/app/globals.css deleted file mode 100644 index 87993fb782..0000000000 --- a/examples/counter-next-js/src/app/globals.css +++ /dev/null @@ -1,220 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Roboto, sans-serif; - background: #000000; - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - color: #ffffff; - padding: 20px; -} - -.counter-app { - width: 100%; - max-width: 500px; - margin: 0 auto; -} - -.counter-container { - background: #1c1c1e; - border-radius: 16px; - border: 1px solid #2c2c2e; - overflow: hidden; -} - -.counter-header { - padding: 24px; - border-bottom: 1px solid #2c2c2e; - display: flex; - justify-content: space-between; - align-items: center; -} - -.counter-header h1 { - font-size: 24px; - font-weight: 600; - color: #ffffff; -} - -.status-indicator { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; - font-weight: 500; -} - -.status-dot { - width: 8px; - height: 8px; - border-radius: 50%; - transition: background-color 0.2s ease; -} - -.status-indicator.connected .status-dot { - background-color: #30d158; -} - -.status-indicator.disconnected .status-dot { - background-color: #ff3b30; -} - -.status-indicator.connected { - color: #30d158; -} - -.status-indicator.disconnected { - color: #ff3b30; -} - -.counter-settings { - padding: 24px; - border-bottom: 1px solid #2c2c2e; -} - -.setting-group { - margin-bottom: 0; -} - -.setting-group label { - display: block; - font-size: 14px; - font-weight: 600; - color: #8e8e93; - margin-bottom: 8px; -} - -.setting-input { - width: 100%; - padding: 10px 14px; - border: 1px solid #3a3a3c; - border-radius: 8px; - font-size: 14px; - transition: all 0.2s ease; - background: #2c2c2e; - color: #ffffff; -} - -.setting-input:focus { - outline: none; - border-color: #007aff; - box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); -} - -.setting-input::placeholder { - color: #8e8e93; -} - -.counter-display { - padding: 48px 24px; - text-align: center; - background: #000000; -} - -.count-value { - font-size: 72px; - font-weight: 700; - color: #007aff; - line-height: 1; - margin-bottom: 12px; - font-variant-numeric: tabular-nums; -} - -.count-label { - font-size: 16px; - color: #8e8e93; - font-weight: 500; -} - -.counter-controls { - padding: 24px; - display: flex; - gap: 12px; - border-bottom: 1px solid #2c2c2e; -} - -.counter-button { - flex: 1; - padding: 16px; - border: none; - border-radius: 12px; - font-size: 18px; - font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; - color: white; -} - -.counter-button.increment-1 { - background: #007aff; -} - -.counter-button.increment-1:hover:not(:disabled) { - background: #0056cc; - transform: translateY(-2px); -} - -.counter-button.increment-5 { - background: #34c759; -} - -.counter-button.increment-5:hover:not(:disabled) { - background: #28a745; - transform: translateY(-2px); -} - -.counter-button.increment-10 { - background: #ff9500; -} - -.counter-button.increment-10:hover:not(:disabled) { - background: #e68600; - transform: translateY(-2px); -} - -.counter-button:disabled { - background: #3a3a3c; - cursor: not-allowed; - color: #8e8e93; - transform: none; -} - -.info-box { - padding: 24px; - background: #2c2c2e; -} - -.info-box p { - font-size: 14px; - color: #8e8e93; - line-height: 1.6; - margin-bottom: 8px; -} - -.info-box p:last-child { - margin-bottom: 0; -} - -@media (max-width: 480px) { - .counter-header h1 { - font-size: 20px; - } - - .count-value { - font-size: 56px; - } - - .counter-controls { - flex-direction: column; - } - - .counter-button { - width: 100%; - } -} diff --git a/examples/counter-next-js/src/app/page.tsx b/examples/counter-next-js/src/app/page.tsx deleted file mode 100644 index 97cba5bdfc..0000000000 --- a/examples/counter-next-js/src/app/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Counter } from "@/components/Counter"; - -export default function Home() { - return ; -} diff --git a/examples/counter-next-js/src/rivet/registry.ts b/examples/counter-next-js/src/rivet/registry.ts deleted file mode 100644 index 1e6cdc4fca..0000000000 --- a/examples/counter-next-js/src/rivet/registry.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const counter = actor({ - state: { - count: 0, - }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - getCount: (c) => { - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); diff --git a/examples/counter-serverless/README.md b/examples/counter-serverless/README.md deleted file mode 100644 index bc11eb08c6..0000000000 --- a/examples/counter-serverless/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Counter (Serverless) for RivetKit - -Example project demonstrating serverless actor deployment with automatic engine configuration using [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) - -## Getting Started - -### Prerequisites - -- Node.js -- RIVET_TOKEN environment variable (for serverless configuration) - -### Installation - -```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/counter-serverless -npm install -``` - -### Development - -Set your Rivet token and run the development server: - -```sh -export RIVET_TOKEN=your-token-here -npm run dev -``` - -Run the connect script to interact with the counter: - -```sh -tsx scripts/connect.ts -``` - -## License - -Apache 2.0 \ No newline at end of file diff --git a/examples/counter-serverless/package.json b/examples/counter-serverless/package.json deleted file mode 100644 index 7e292e296e..0000000000 --- a/examples/counter-serverless/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "example-counter-serverless", - "version": "2.0.21", - "private": true, - "type": "module", - "scripts": { - "dev": "tsx src/server.ts", - "check-types": "tsc --noEmit", - "connect": "tsx scripts/connect.ts", - "test": "vitest run" - }, - "devDependencies": { - "rivetkit": "workspace:*", - "@types/node": "^22.13.9", - "tsx": "^3.12.7", - "typescript": "^5.7.3", - "vitest": "^3.1.1" - }, - "stableVersion": "0.8.0", - "template": { - "technologies": [ - "typescript" - ], - "tags": [] - } -} diff --git a/examples/counter/.gitignore b/examples/counter/.gitignore deleted file mode 100644 index 79b7a1192f..0000000000 --- a/examples/counter/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.actorcore -node_modules \ No newline at end of file diff --git a/examples/counter/README.md b/examples/counter/README.md deleted file mode 100644 index 213d0f5d7e..0000000000 --- a/examples/counter/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Counter for RivetKit - -Example project demonstrating basic actor state management and RPC calls with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) - -## Getting Started - -### Prerequisites - -- Node.js - -### Installation - -```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/counter -npm install -``` - -### Development - -```sh -npm run dev -``` - -Run the connect script to interact with the counter: - -```sh -tsx scripts/connect.ts -``` - -## License - -Apache 2.0 \ No newline at end of file diff --git a/examples/counter/scripts/connect.ts b/examples/counter/scripts/connect.ts deleted file mode 100644 index 42208adced..0000000000 --- a/examples/counter/scripts/connect.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createClient } from "rivetkit/client"; -import type { Registry } from "../src/registry"; - -async function main() { - const client = createClient("http://localhost:6420"); - - const counter = client.counter.getOrCreate().connect(); - - counter.on("newCount", (count: number) => console.log("Event:", count)); - - while (true) { - const out = await counter.increment(1); - console.log("RPC:", out); - - await new Promise((resolve) => setTimeout(resolve, 1000)); - } -} - -main(); diff --git a/examples/counter/src/registry.ts b/examples/counter/src/registry.ts deleted file mode 100644 index 44707e2fef..0000000000 --- a/examples/counter/src/registry.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const counter = actor({ - state: { - count: 0, - }, - actions: { - increment: (c, x: number) => { - c.state.count += x; - c.broadcast("newCount", c.state.count); - return c.state.count; - }, - getCount: (c) => { - return c.state.count; - }, - }, -}); - -export const registry = setup({ - use: { counter }, -}); - -export type Registry = typeof registry; diff --git a/examples/counter/tests/counter.test.ts b/examples/counter/tests/counter.test.ts deleted file mode 100644 index 89ba4667e0..0000000000 --- a/examples/counter/tests/counter.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { expect, test } from "vitest"; -import { registry } from "../src/registry"; - -test("it should count", async (test) => { - const { client } = await setupTest(test, registry); - const counter = client.counter.getOrCreate().connect(); - - // Test initial count - expect(await counter.getCount()).toBe(0); - - // Test event emission - let eventCount = -1; - counter.on("newCount", (count: number) => { - eventCount = count; - }); - - // Test increment - const incrementAmount = 5; - const result = await counter.increment(incrementAmount); - expect(result).toBe(incrementAmount); - - // Verify event was emitted with correct count - expect(eventCount).toBe(incrementAmount); - - // Test multiple increments - for (let i = 1; i <= 3; i++) { - const newCount = await counter.increment(incrementAmount); - expect(newCount).toBe(incrementAmount * (i + 1)); - expect(eventCount).toBe(incrementAmount * (i + 1)); - } - - // Verify final count - expect(await counter.getCount()).toBe(incrementAmount * 4); -}); diff --git a/examples/counter/tsconfig.json b/examples/counter/tsconfig.json deleted file mode 100644 index fa0f0ab2ad..0000000000 --- a/examples/counter/tsconfig.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "target": "esnext", - /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - "lib": ["esnext"], - /* Specify what JSX code is generated. */ - "jsx": "react-jsx", - - /* Specify what module code is generated. */ - "module": "esnext", - /* Specify how TypeScript looks up a file from a given module specifier. */ - "moduleResolution": "bundler", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["node"], - /* Enable importing .json files */ - "resolveJsonModule": true, - - /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ - "allowJs": true, - /* Enable error reporting in type-checked JavaScript files. */ - "checkJs": false, - - /* Disable emitting files from a compilation. */ - "noEmit": true, - - /* Ensure that each file can be safely transpiled without relying on other imports. */ - "isolatedModules": true, - /* Allow 'import x from y' when a module doesn't have a default export. */ - "allowSyntheticDefaultImports": true, - /* Ensure that casing is correct in imports. */ - "forceConsistentCasingInFileNames": true, - - /* Enable all strict type-checking options. */ - "strict": true, - - /* Skip type checking all .d.ts files. */ - "skipLibCheck": true - }, - "include": ["src/**/*.ts", "scripts/**/*.ts", "tests/**/*.ts"] -} diff --git a/examples/cross-actor-actions/README.md b/examples/cross-actor-actions/README.md new file mode 100644 index 0000000000..715dc9cfd5 --- /dev/null +++ b/examples/cross-actor-actions/README.md @@ -0,0 +1,17 @@ +# Cross-Actor Actions + +Demonstrates how actors can call actions on other actors for inter-actor communication and coordination. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cross-actor-actions +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/cross-actor-actions/package.json b/examples/cross-actor-actions/package.json new file mode 100644 index 0000000000..26c20d2051 --- /dev/null +++ b/examples/cross-actor-actions/package.json @@ -0,0 +1,40 @@ +{ + "name": "cross-actor-actions", + "version": "2.0.21", + "private": true, + "type": "module", + "scripts": { + "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"", + "dev:backend": "tsx --watch src/backend/server.ts", + "dev:frontend": "vite", + "check-types": "tsc --noEmit", + "test": "vitest run" + }, + "devDependencies": { + "@types/node": "^22.13.9", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@vitejs/plugin-react": "^4.2.0", + "concurrently": "^8.2.2", + "tsx": "^3.12.7", + "typescript": "^5.5.2", + "vite": "^5.0.0", + "vitest": "^3.1.1", + "@rivetkit/react": "workspace:*", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "dependencies": { + "rivetkit": "workspace:*" + }, + "template": { + "technologies": [ + "typescript" + ], + "tags": [ + "quickstart" + ], + "priority": 1000 + }, + "license": "MIT" +} diff --git a/examples/quickstart-cross-actor-actions/src/backend/registry.ts b/examples/cross-actor-actions/src/backend/registry.ts similarity index 100% rename from examples/quickstart-cross-actor-actions/src/backend/registry.ts rename to examples/cross-actor-actions/src/backend/registry.ts diff --git a/examples/quickstart-actions/src/backend/server.ts b/examples/cross-actor-actions/src/backend/server.ts similarity index 100% rename from examples/quickstart-actions/src/backend/server.ts rename to examples/cross-actor-actions/src/backend/server.ts diff --git a/examples/quickstart-cross-actor-actions/src/frontend/App.tsx b/examples/cross-actor-actions/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-cross-actor-actions/src/frontend/App.tsx rename to examples/cross-actor-actions/src/frontend/App.tsx diff --git a/examples/quickstart-cross-actor-actions/src/frontend/index.html b/examples/cross-actor-actions/src/frontend/index.html similarity index 100% rename from examples/quickstart-cross-actor-actions/src/frontend/index.html rename to examples/cross-actor-actions/src/frontend/index.html diff --git a/examples/quickstart-cross-actor-actions/src/frontend/main.tsx b/examples/cross-actor-actions/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-cross-actor-actions/src/frontend/main.tsx rename to examples/cross-actor-actions/src/frontend/main.tsx diff --git a/examples/quickstart-cross-actor-actions/tests/cross-actor.test.ts b/examples/cross-actor-actions/tests/cross-actor.test.ts similarity index 100% rename from examples/quickstart-cross-actor-actions/tests/cross-actor.test.ts rename to examples/cross-actor-actions/tests/cross-actor.test.ts diff --git a/examples/quickstart-cross-actor-actions/tsconfig.json b/examples/cross-actor-actions/tsconfig.json similarity index 100% rename from examples/quickstart-cross-actor-actions/tsconfig.json rename to examples/cross-actor-actions/tsconfig.json diff --git a/examples/cross-actor-actions/turbo.json b/examples/cross-actor-actions/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/cross-actor-actions/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-cross-actor-actions/vite.config.ts b/examples/cross-actor-actions/vite.config.ts similarity index 100% rename from examples/quickstart-cross-actor-actions/vite.config.ts rename to examples/cross-actor-actions/vite.config.ts diff --git a/examples/quickstart-cross-actor-actions/vitest.config.ts b/examples/cross-actor-actions/vitest.config.ts similarity index 100% rename from examples/quickstart-cross-actor-actions/vitest.config.ts rename to examples/cross-actor-actions/vitest.config.ts diff --git a/examples/cursors-raw-websocket/README.md b/examples/cursors-raw-websocket/README.md index b7b2646a0b..da00906c32 100644 --- a/examples/cursors-raw-websocket/README.md +++ b/examples/cursors-raw-websocket/README.md @@ -1,32 +1,16 @@ -# Real-time Collaborative Cursors for RivetKit +# Real-time Collaborative Cursors (Raw WebSocket) -Example project demonstrating real-time cursor tracking and collaborative canvas with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Demonstrates real-time cursor tracking and collaborative canvas using raw WebSocket handlers instead of RivetKit's higher-level WebSocket abstraction. ## Getting Started -### Prerequisites - -- Node.js 18+ - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/cursors +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cursors-raw-websocket npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to `http://localhost:5173`. Open multiple tabs or windows to see real-time cursor tracking and text placement across different users. ## Features @@ -35,9 +19,9 @@ Open your browser to `http://localhost:5173`. Open multiple tabs or windows to s - Click-to-place text on canvas - Multiple room support for different collaborative spaces - Persistent text labels across sessions -- Event-driven architecture with RivetKit actors +- Raw WebSocket handlers using `onWebsocket` for lower-level control - TypeScript support throughout ## License -Apache 2.0 +MIT diff --git a/examples/cursors-raw-websocket/package.json b/examples/cursors-raw-websocket/package.json index d13a8fb38d..798c2cfddb 100644 --- a/examples/cursors-raw-websocket/package.json +++ b/examples/cursors-raw-websocket/package.json @@ -38,5 +38,6 @@ "tags": [ "real-time" ] - } + }, + "license": "MIT" } diff --git a/examples/cursors/README.md b/examples/cursors/README.md index b7b2646a0b..3cfe220ad4 100644 --- a/examples/cursors/README.md +++ b/examples/cursors/README.md @@ -1,32 +1,16 @@ -# Real-time Collaborative Cursors for RivetKit +# Real-time Collaborative Cursors -Example project demonstrating real-time cursor tracking and collaborative canvas with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating real-time cursor tracking and collaborative canvas. ## Getting Started -### Prerequisites - -- Node.js 18+ - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/cursors +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/cursors npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to `http://localhost:5173`. Open multiple tabs or windows to see real-time cursor tracking and text placement across different users. ## Features @@ -40,4 +24,4 @@ Open your browser to `http://localhost:5173`. Open multiple tabs or windows to s ## License -Apache 2.0 +MIT diff --git a/examples/cursors/package.json b/examples/cursors/package.json index 3bc505bfac..a63f5956b0 100644 --- a/examples/cursors/package.json +++ b/examples/cursors/package.json @@ -37,6 +37,8 @@ ], "tags": [ "real-time" - ] - } + ], + "priority": 300 + }, + "license": "MIT" } diff --git a/examples/custom-serverless/README.md b/examples/custom-serverless/README.md new file mode 100644 index 0000000000..0a1c2536bc --- /dev/null +++ b/examples/custom-serverless/README.md @@ -0,0 +1,17 @@ +# Custom Serverless + +Example demonstrating custom serverless actor deployment with automatic engine configuration. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/custom-serverless +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/counter/package.json b/examples/custom-serverless/package.json similarity index 83% rename from examples/counter/package.json rename to examples/custom-serverless/package.json index ce610f8127..b6d96e0b27 100644 --- a/examples/counter/package.json +++ b/examples/custom-serverless/package.json @@ -1,5 +1,5 @@ { - "name": "example-counter", + "name": "custom-serverless", "version": "2.0.21", "private": true, "type": "module", @@ -22,7 +22,9 @@ "typescript" ], "tags": [ - "quickstart" - ] - } + "starter" + ], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/counter-serverless/scripts/connect.ts b/examples/custom-serverless/scripts/connect.ts similarity index 100% rename from examples/counter-serverless/scripts/connect.ts rename to examples/custom-serverless/scripts/connect.ts diff --git a/examples/counter-serverless/src/registry.ts b/examples/custom-serverless/src/registry.ts similarity index 100% rename from examples/counter-serverless/src/registry.ts rename to examples/custom-serverless/src/registry.ts diff --git a/examples/counter-serverless/src/server.ts b/examples/custom-serverless/src/server.ts similarity index 100% rename from examples/counter-serverless/src/server.ts rename to examples/custom-serverless/src/server.ts diff --git a/examples/counter-serverless/tests/counter.test.ts b/examples/custom-serverless/tests/counter.test.ts similarity index 100% rename from examples/counter-serverless/tests/counter.test.ts rename to examples/custom-serverless/tests/counter.test.ts diff --git a/examples/counter-serverless/tsconfig.json b/examples/custom-serverless/tsconfig.json similarity index 100% rename from examples/counter-serverless/tsconfig.json rename to examples/custom-serverless/tsconfig.json diff --git a/examples/custom-serverless/turbo.json b/examples/custom-serverless/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/custom-serverless/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/deno/README.md b/examples/deno/README.md index aa297f8860..0d4dd2b823 100644 --- a/examples/deno/README.md +++ b/examples/deno/README.md @@ -1,39 +1,17 @@ -# Deno Example for RivetKit +# Deno Example -Example project demonstrating basic actor state management and RPC calls with [RivetKit](https://rivetkit.org) using Deno runtime. - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating basic actor state management and RPC calls using Deno runtime. ## Getting Started -### Prerequisites - -- Deno - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/deno -pnpm install +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/deno +npm install +npm run dev ``` -**Notice:** We use `pnpm install` here as Deno offers compatability with package.json via npm/pnpm. Some packages used in rivetkit are simpler to install with npm/pnpm. - -### Development - -```sh -deno task dev -``` - -Run the connect script to interact with the counter: - -```sh -deno task connect -``` ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/deno/package.json b/examples/deno/package.json index f53c2238d6..d324e9c6d0 100644 --- a/examples/deno/package.json +++ b/examples/deno/package.json @@ -23,6 +23,8 @@ "deno", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/deno/turbo.json b/examples/deno/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/deno/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/drizzle/README.md b/examples/drizzle/README.md index 84a3afe9a6..168e73e75e 100644 --- a/examples/drizzle/README.md +++ b/examples/drizzle/README.md @@ -1,33 +1,17 @@ -# Hono Integration for RivetKit +# Drizzle Integration -Example project demonstrating Hono web framework integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Demonstrates Drizzle ORM integration with Rivet Actors for type-safe database operations. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/hono +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/drizzle npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to http://localhost:3000 to see the Hono server with RivetKit integration. ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/drizzle/package.json b/examples/drizzle/package.json index a7bbc87e4d..15baec4417 100644 --- a/examples/drizzle/package.json +++ b/examples/drizzle/package.json @@ -26,6 +26,8 @@ ], "tags": [ "database" - ] - } + ], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/elysia/README.md b/examples/elysia/README.md index ed5623dd4c..72bf58b861 100644 --- a/examples/elysia/README.md +++ b/examples/elysia/README.md @@ -1,33 +1,17 @@ -# Elysia Integration for RivetKit +# Elysia Integration -Example project demonstrating Elysia web framework integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating Elysia web framework integration. ## Getting Started -### Prerequisites - -- Bun - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/elysia +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/elysia npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to http://localhost:3000 to see the Elysia server with RivetKit integration. ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/elysia/package.json b/examples/elysia/package.json index d0e9c6fc15..71158c3aa2 100644 --- a/examples/elysia/package.json +++ b/examples/elysia/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@rivetkit/react": "workspace:*", + "@sinclair/typebox": "^0.34.15", "elysia": "^1.3.5", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -25,6 +26,8 @@ "bun", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/express/README.md b/examples/express/README.md index a15e7e6cb2..8c2b32b150 100644 --- a/examples/express/README.md +++ b/examples/express/README.md @@ -1,33 +1,17 @@ -# Express Integration for RivetKit +# Express Integration -Example project demonstrating Express web framework integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating Express web framework integration. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/express +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/express npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to http://localhost:3000 to see the Express server with RivetKit integration. ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/express/package.json b/examples/express/package.json index 118f30827e..e99a61756a 100644 --- a/examples/express/package.json +++ b/examples/express/package.json @@ -27,6 +27,8 @@ "express", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/hono-bun/README.md b/examples/hono-bun/README.md index 9638b7bde1..8dca40193b 100644 --- a/examples/hono-bun/README.md +++ b/examples/hono-bun/README.md @@ -1,41 +1,17 @@ -# Hono + Bun Integration for RivetKit +# Hono + Bun -Example project demonstrating Hono web framework with Bun runtime and React frontend integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example demonstrating Hono web framework with Bun runtime and React frontend integration. ## Getting Started -### Prerequisites - -- Bun - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/hono-bun +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/hono-bun npm install -``` - -### Development - -```sh npm run dev ``` -This will start both the backend server (on port 8080) and the frontend dev server (on port 5173). - -Open your browser to [http://localhost:5173](http://localhost:5173) to see the counter application. - -You can also test the server directly by running: - -```sh -curl -X POST http://localhost:8080/increment/test -``` ## License -Apache 2.0 +MIT diff --git a/examples/hono-bun/package.json b/examples/hono-bun/package.json index b86e5bc858..9ade9d1eb7 100644 --- a/examples/hono-bun/package.json +++ b/examples/hono-bun/package.json @@ -1,5 +1,5 @@ { - "name": "example-hono-bun", + "name": "hono-bun", "version": "2.0.21", "private": true, "type": "module", @@ -43,6 +43,10 @@ "bun", "typescript" ], - "tags": [] - } + "tags": [ + "starter" + ], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/hono-react/README.md b/examples/hono-react/README.md index e8a7232a12..9aa42e930b 100644 --- a/examples/hono-react/README.md +++ b/examples/hono-react/README.md @@ -1,33 +1,17 @@ -# Hono React Integration for RivetKit +# Hono + React -Example project demonstrating full-stack Hono backend with React frontend integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example demonstrating full-stack Hono backend with React frontend integration. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/hono-react +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/hono-react npm install -``` - -### Development - -```sh npm run dev ``` -This will start both the Hono backend server and Vite React frontend. Open your browser to http://localhost:5173 to see the React app connected to Rivet Actors. ## License -Apache 2.0 +MIT diff --git a/examples/hono-react/package.json b/examples/hono-react/package.json index 651f1b79d0..e7576a9094 100644 --- a/examples/hono-react/package.json +++ b/examples/hono-react/package.json @@ -1,5 +1,5 @@ { - "name": "example-hono-react", + "name": "hono-react", "version": "2.0.21", "private": true, "type": "module", @@ -38,7 +38,8 @@ "typescript" ], "tags": [ - "real-time" + "starter" ] - } + }, + "license": "MIT" } diff --git a/examples/hono/README.md b/examples/hono/README.md index 84a3afe9a6..c76aa48d94 100644 --- a/examples/hono/README.md +++ b/examples/hono/README.md @@ -1,33 +1,17 @@ -# Hono Integration for RivetKit +# Hono Integration -Example project demonstrating Hono web framework integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating Hono web framework integration. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/hono +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/hono npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to http://localhost:3000 to see the Hono server with RivetKit integration. ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/hono/package.json b/examples/hono/package.json index b75c915fdc..33208085c4 100644 --- a/examples/hono/package.json +++ b/examples/hono/package.json @@ -25,6 +25,8 @@ "hono", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/kitchen-sink/README.md b/examples/kitchen-sink/README.md index 66221e34c9..4a026463ba 100644 --- a/examples/kitchen-sink/README.md +++ b/examples/kitchen-sink/README.md @@ -1,36 +1,17 @@ -# Kitchen Sink Example for RivetKit +# Kitchen Sink Example -Example project demonstrating all RivetKit features with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating all RivetKit features. ## Getting Started -### Prerequisites - -- Node.js 18+ or Bun -- RivetKit development environment - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/kitchen-sink +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/kitchen-sink npm install -``` - -### Development - -```sh npm run dev ``` -This will start both the backend server (port 8080) and frontend development server (port 5173). - -Open [http://localhost:5173](http://localhost:5173) in your browser. ## License -Apache 2.0 +MIT diff --git a/examples/kitchen-sink/package.json b/examples/kitchen-sink/package.json index 63da99068a..2c621a4946 100644 --- a/examples/kitchen-sink/package.json +++ b/examples/kitchen-sink/package.json @@ -31,5 +31,6 @@ "typescript" ], "tags": [] - } + }, + "license": "MIT" } diff --git a/examples/multi-region/README.md b/examples/multi-region/README.md new file mode 100644 index 0000000000..e756924ae9 --- /dev/null +++ b/examples/multi-region/README.md @@ -0,0 +1,17 @@ +# Multi-Region + +Demonstrates deploying Rivet Actors across multiple geographic regions for low-latency global access. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/multi-region +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/quickstart-scheduling/package.json b/examples/multi-region/package.json similarity index 91% rename from examples/quickstart-scheduling/package.json rename to examples/multi-region/package.json index e78c3b466d..685e7cb418 100644 --- a/examples/quickstart-scheduling/package.json +++ b/examples/multi-region/package.json @@ -1,5 +1,5 @@ { - "name": "quickstart-scheduling", + "name": "multi-region", "version": "2.0.21", "private": true, "type": "module", @@ -33,6 +33,8 @@ ], "tags": [ "quickstart" - ] - } + ], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/quickstart-multi-region/src/backend/registry.ts b/examples/multi-region/src/backend/registry.ts similarity index 100% rename from examples/quickstart-multi-region/src/backend/registry.ts rename to examples/multi-region/src/backend/registry.ts diff --git a/examples/quickstart-cross-actor-actions/src/backend/server.ts b/examples/multi-region/src/backend/server.ts similarity index 100% rename from examples/quickstart-cross-actor-actions/src/backend/server.ts rename to examples/multi-region/src/backend/server.ts diff --git a/examples/quickstart-multi-region/src/backend/types.ts b/examples/multi-region/src/backend/types.ts similarity index 100% rename from examples/quickstart-multi-region/src/backend/types.ts rename to examples/multi-region/src/backend/types.ts diff --git a/examples/quickstart-multi-region/src/frontend/App.tsx b/examples/multi-region/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-multi-region/src/frontend/App.tsx rename to examples/multi-region/src/frontend/App.tsx diff --git a/examples/quickstart-multi-region/src/frontend/index.html b/examples/multi-region/src/frontend/index.html similarity index 100% rename from examples/quickstart-multi-region/src/frontend/index.html rename to examples/multi-region/src/frontend/index.html diff --git a/examples/quickstart-multi-region/src/frontend/main.tsx b/examples/multi-region/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-multi-region/src/frontend/main.tsx rename to examples/multi-region/src/frontend/main.tsx diff --git a/examples/quickstart-multi-region/tests/regions.test.ts b/examples/multi-region/tests/regions.test.ts similarity index 100% rename from examples/quickstart-multi-region/tests/regions.test.ts rename to examples/multi-region/tests/regions.test.ts diff --git a/examples/quickstart-multi-region/tsconfig.json b/examples/multi-region/tsconfig.json similarity index 100% rename from examples/quickstart-multi-region/tsconfig.json rename to examples/multi-region/tsconfig.json diff --git a/examples/multi-region/turbo.json b/examples/multi-region/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/multi-region/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-multi-region/vite.config.ts b/examples/multi-region/vite.config.ts similarity index 100% rename from examples/quickstart-multi-region/vite.config.ts rename to examples/multi-region/vite.config.ts diff --git a/examples/quickstart-multi-region/vitest.config.ts b/examples/multi-region/vitest.config.ts similarity index 100% rename from examples/quickstart-multi-region/vitest.config.ts rename to examples/multi-region/vitest.config.ts diff --git a/examples/native-websockets/README.md b/examples/native-websockets/README.md new file mode 100644 index 0000000000..e2a98149ee --- /dev/null +++ b/examples/native-websockets/README.md @@ -0,0 +1,17 @@ +# Native WebSockets + +Demonstrates native WebSocket integration with Rivet Actors for real-time bidirectional communication. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/native-websockets +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/quickstart-native-websockets/package.json b/examples/native-websockets/package.json similarity index 94% rename from examples/quickstart-native-websockets/package.json rename to examples/native-websockets/package.json index 72e11aea77..d3feb6c5f9 100644 --- a/examples/quickstart-native-websockets/package.json +++ b/examples/native-websockets/package.json @@ -1,5 +1,5 @@ { - "name": "quickstart-raw-websockets", + "name": "native-websockets", "version": "2.0.21", "private": true, "type": "module", @@ -38,5 +38,6 @@ "quickstart", "real-time" ] - } + }, + "license": "MIT" } diff --git a/examples/quickstart-native-websockets/src/backend/registry.ts b/examples/native-websockets/src/backend/registry.ts similarity index 100% rename from examples/quickstart-native-websockets/src/backend/registry.ts rename to examples/native-websockets/src/backend/registry.ts diff --git a/examples/quickstart-multi-region/src/backend/server.ts b/examples/native-websockets/src/backend/server.ts similarity index 100% rename from examples/quickstart-multi-region/src/backend/server.ts rename to examples/native-websockets/src/backend/server.ts diff --git a/examples/quickstart-native-websockets/src/frontend/App.tsx b/examples/native-websockets/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-native-websockets/src/frontend/App.tsx rename to examples/native-websockets/src/frontend/App.tsx diff --git a/examples/quickstart-native-websockets/src/frontend/index.html b/examples/native-websockets/src/frontend/index.html similarity index 100% rename from examples/quickstart-native-websockets/src/frontend/index.html rename to examples/native-websockets/src/frontend/index.html diff --git a/examples/quickstart-native-websockets/src/frontend/main.tsx b/examples/native-websockets/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-native-websockets/src/frontend/main.tsx rename to examples/native-websockets/src/frontend/main.tsx diff --git a/examples/quickstart-native-websockets/tests/websocket.test.ts b/examples/native-websockets/tests/websocket.test.ts similarity index 100% rename from examples/quickstart-native-websockets/tests/websocket.test.ts rename to examples/native-websockets/tests/websocket.test.ts diff --git a/examples/quickstart-native-websockets/tsconfig.json b/examples/native-websockets/tsconfig.json similarity index 100% rename from examples/quickstart-native-websockets/tsconfig.json rename to examples/native-websockets/tsconfig.json diff --git a/examples/native-websockets/turbo.json b/examples/native-websockets/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/native-websockets/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-native-websockets/vite.config.ts b/examples/native-websockets/vite.config.ts similarity index 100% rename from examples/quickstart-native-websockets/vite.config.ts rename to examples/native-websockets/vite.config.ts diff --git a/examples/quickstart-native-websockets/vitest.config.ts b/examples/native-websockets/vitest.config.ts similarity index 100% rename from examples/quickstart-native-websockets/vitest.config.ts rename to examples/native-websockets/vitest.config.ts diff --git a/examples/next-js/README.md b/examples/next-js/README.md index e215bc4ccf..76eb615a7d 100644 --- a/examples/next-js/README.md +++ b/examples/next-js/README.md @@ -1,36 +1,24 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Next.js -## Getting Started +Minimal Next.js example demonstrating basic actor state management and real-time updates. -First, run the development server: +## Getting Started -```bash +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/next-js +npm install npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +## Features -## Deploy on Vercel +- Real-time counter synchronization across multiple clients +- Next.js 15 with App Router +- TypeScript support +- Customizable counter IDs for multiple independent counters -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## License -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +MIT diff --git a/examples/next-js/package.json b/examples/next-js/package.json index 7dbb006e79..876ba501f7 100644 --- a/examples/next-js/package.json +++ b/examples/next-js/package.json @@ -1,12 +1,14 @@ { - "name": "example-next-js", + "name": "next-js", "version": "2.0.21", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "connect": "tsx scripts/connect.ts", + "check-types": "tsc --noEmit" }, "dependencies": { "react": "19.1.0", @@ -19,14 +21,19 @@ "typescript": "^5", "@types/node": "^20", "@types/react": "^19", - "@types/react-dom": "^19" + "@types/react-dom": "^19", + "tsx": "^3.12.7" }, + "stableVersion": "0.8.0", "template": { "technologies": [ "next-js", "react", "typescript" ], - "tags": [] - } + "tags": [ + "starter" + ] + }, + "license": "MIT" } diff --git a/examples/counter-next-js/scripts/connect.ts b/examples/next-js/scripts/connect.ts similarity index 100% rename from examples/counter-next-js/scripts/connect.ts rename to examples/next-js/scripts/connect.ts diff --git a/examples/next-js/src/app/globals.css b/examples/next-js/src/app/globals.css index 24fa51ff25..87993fb782 100644 --- a/examples/next-js/src/app/globals.css +++ b/examples/next-js/src/app/globals.css @@ -7,114 +7,41 @@ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Roboto, sans-serif; background: #000000; - height: 100vh; - overflow: hidden; - margin: 0; - padding: 0; + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + color: #ffffff; + padding: 20px; } -.app { - display: flex; - height: 100vh; - width: 100vw; - background: #000000; - overflow: hidden; +.counter-app { + width: 100%; + max-width: 500px; + margin: 0 auto; } -/* Sidebar */ -.sidebar { - width: 280px; +.counter-container { background: #1c1c1e; - border-right: 1px solid #2c2c2e; - display: flex; - flex-direction: column; + border-radius: 16px; + border: 1px solid #2c2c2e; + overflow: hidden; } -.sidebar-header { - padding: 20px 20px; +.counter-header { + padding: 24px; border-bottom: 1px solid #2c2c2e; display: flex; justify-content: space-between; align-items: center; - height: 60px; - box-sizing: border-box; -} - -.logo { - display: flex; - align-items: center; - gap: 12px; -} - -.logo h1 { - font-size: 18px; - font-weight: 500; - color: #ffffff; -} - -.close-sidebar { - display: none; - background: none; - border: none; - color: #8e8e93; - cursor: pointer; - padding: 8px; - border-radius: 6px; - transition: all 0.2s ease; -} - -.close-sidebar:hover { - background: #3a3a3c; - color: #ffffff; } -.user-settings { - padding: 20px; - flex: 1; -} - -.setting-group { - margin-bottom: 20px; -} - -.setting-group label { - display: block; - font-size: 14px; +.counter-header h1 { + font-size: 24px; font-weight: 600; - color: #8e8e93; - margin-bottom: 8px; -} - -.setting-input { - width: 100%; - padding: 10px 14px; - border: 1px solid #3a3a3c; - border-radius: 8px; - font-size: 14px; - transition: all 0.2s ease; - background: #2c2c2e; color: #ffffff; } -.setting-input:focus { - outline: none; - border-color: #007aff; - box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); -} - -.setting-input::placeholder { - color: #8e8e93; -} - -.connection-status { - padding: 20px; - border-top: 1px solid #2c2c2e; - height: 60px; - box-sizing: border-box; - display: flex; - align-items: center; -} - .status-indicator { display: flex; align-items: center; @@ -146,318 +73,148 @@ body { color: #ff3b30; } -/* Chat Container */ -.chat-container { - flex: 1; - display: flex; - flex-direction: column; - background: #000000; +.counter-settings { + padding: 24px; + border-bottom: 1px solid #2c2c2e; } -.chat-header { - padding: 12px 20px; - border-bottom: 1px solid #2c2c2e; - background: #1c1c1e; - display: flex; - align-items: center; - gap: 12px; +.setting-group { + margin-bottom: 0; } -.menu-button { - display: none; - background: none; - border: none; +.setting-group label { + display: block; + font-size: 14px; + font-weight: 600; color: #8e8e93; - cursor: pointer; - padding: 8px; - border-radius: 6px; - transition: all 0.2s ease; + margin-bottom: 8px; } -.menu-button:hover { - background: #3a3a3c; +.setting-input { + width: 100%; + padding: 10px 14px; + border: 1px solid #3a3a3c; + border-radius: 8px; + font-size: 14px; + transition: all 0.2s ease; + background: #2c2c2e; color: #ffffff; } -.room-info h2 { - font-size: 16px; - font-weight: 600; - color: #ffffff; - margin-bottom: 2px; +.setting-input:focus { + outline: none; + border-color: #007aff; + box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); } -.room-info p { - font-size: 12px; +.setting-input::placeholder { color: #8e8e93; } -.messages-container { - flex: 1; - overflow-y: auto; +.counter-display { + padding: 48px 24px; + text-align: center; background: #000000; } -.messages { - padding: 16px 20px; - min-height: 100%; -} - -.message-wrapper { - display: flex; +.count-value { + font-size: 72px; + font-weight: 700; + color: #007aff; + line-height: 1; margin-bottom: 12px; - align-items: flex-end; + font-variant-numeric: tabular-nums; } -.message-wrapper.own { - flex-direction: row-reverse; -} - -.message-avatar { - margin-right: 12px; - flex-shrink: 0; -} - -.message-wrapper.own .message-avatar { - margin-right: 0; - margin-left: 12px; -} - -.avatar { - width: 32px; - height: 32px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - font-weight: 600; - color: white; - text-transform: uppercase; -} - -.avatar-spacer { - width: 32px; - margin-right: 12px; -} - -.message-wrapper.own .avatar-spacer { - margin-right: 0; - margin-left: 12px; +.count-label { + font-size: 16px; + color: #8e8e93; + font-weight: 500; } -.message-content { - max-width: 70%; +.counter-controls { + padding: 24px; display: flex; - flex-direction: column; -} - -.message-wrapper.own .message-content { - align-items: flex-end; -} - -.message-sender { - font-size: 12px; - font-weight: 600; - color: #64748b; - margin-bottom: 4px; - margin-left: 4px; -} - -.message-wrapper.own .message-sender { - margin-left: 0; - margin-right: 4px; -} - -.message-bubble { - padding: 10px 14px; - border-radius: 16px; - position: relative; - word-wrap: break-word; - max-width: 100%; + gap: 12px; + border-bottom: 1px solid #2c2c2e; } -.message-bubble.other { - background: #2c2c2e; +.counter-button { + flex: 1; + padding: 16px; border: none; - border-bottom-left-radius: 4px; - color: #ffffff; -} - -.message-bubble.own { - background: #007aff; - color: white; - border-bottom-right-radius: 4px; -} - -.message-text { - font-size: 15px; - line-height: 1.3; - margin-bottom: 3px; -} - -.message-time { - font-size: 11px; - opacity: 0.5; -} - -.empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - text-align: center; - color: #8e8e93; -} - -.empty-icon { - font-size: 48px; - margin-bottom: 16px; -} - -.empty-state h3 { + border-radius: 12px; font-size: 18px; font-weight: 600; - color: #ffffff; - margin-bottom: 8px; -} - -.empty-state p { - font-size: 14px; + cursor: pointer; + transition: all 0.2s ease; + color: white; } -.input-container { - padding: 12px 20px; - border-top: 1px solid #2c2c2e; - background: #1c1c1e; - height: 60px; - box-sizing: border-box; - display: flex; - align-items: center; +.counter-button.increment-1 { + background: #007aff; } -.input-wrapper { - display: flex; - align-items: center; - gap: 8px; - background: #2c2c2e; - border: 1px solid #3a3a3c; - border-radius: 20px; - padding: 6px 6px 6px 16px; - transition: all 0.2s ease; - width: 100%; +.counter-button.increment-1:hover:not(:disabled) { + background: #0056cc; + transform: translateY(-2px); } -.input-wrapper:focus-within { - border-color: #007aff; - box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1); +.counter-button.increment-5 { + background: #34c759; } -.message-input { - flex: 1; - border: none; - background: transparent; - font-size: 15px; - outline: none; - resize: none; - color: #ffffff; +.counter-button.increment-5:hover:not(:disabled) { + background: #28a745; + transform: translateY(-2px); } -.message-input::placeholder { - color: #8e8e93; +.counter-button.increment-10 { + background: #ff9500; } -.send-button { - width: 32px; - height: 32px; - border: none; - border-radius: 50%; - background: #007aff; - color: white; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.2s ease; - flex-shrink: 0; -} - -.send-button:hover:not(:disabled) { - background: #0056cc; - transform: scale(1.05); +.counter-button.increment-10:hover:not(:disabled) { + background: #e68600; + transform: translateY(-2px); } -.send-button:disabled { +.counter-button:disabled { background: #3a3a3c; cursor: not-allowed; + color: #8e8e93; transform: none; } -/* Scrollbar Styling */ -.messages-container::-webkit-scrollbar { - width: 6px; -} - -.messages-container::-webkit-scrollbar-track { - background: transparent; +.info-box { + padding: 24px; + background: #2c2c2e; } -.messages-container::-webkit-scrollbar-thumb { - background: #3a3a3c; - border-radius: 3px; +.info-box p { + font-size: 14px; + color: #8e8e93; + line-height: 1.6; + margin-bottom: 8px; } -.messages-container::-webkit-scrollbar-thumb:hover { - background: #48484a; +.info-box p:last-child { + margin-bottom: 0; } -/* Responsive Design */ -@media (max-width: 768px) { - .app { - height: 100vh; - } - - .sidebar { - width: 100%; - position: absolute; - z-index: 10; - transform: translateX(-100%); - transition: transform 0.3s ease; +@media (max-width: 480px) { + .counter-header h1 { + font-size: 20px; } - .sidebar.open { - transform: translateX(0); + .count-value { + font-size: 56px; } - .close-sidebar { - display: block; + .counter-controls { + flex-direction: column; } - .menu-button { - display: block; - } - - .chat-container { + .counter-button { width: 100%; } - - .message-content { - max-width: 85%; - } -} - -/* Animation for new messages */ -@keyframes slideIn { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.message-wrapper { - animation: slideIn 0.3s ease; } diff --git a/examples/next-js/src/app/layout.tsx b/examples/next-js/src/app/layout.tsx index 9e2c27453e..c4f1400687 100644 --- a/examples/next-js/src/app/layout.tsx +++ b/examples/next-js/src/app/layout.tsx @@ -13,8 +13,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Rivet Chat", - description: "Real-time chat powered by RivetKit", + title: "Rivet Counter", + description: "Real-time counter powered by RivetKit", }; export default function RootLayout({ diff --git a/examples/next-js/src/app/page.tsx b/examples/next-js/src/app/page.tsx index 8dd238dd61..97cba5bdfc 100644 --- a/examples/next-js/src/app/page.tsx +++ b/examples/next-js/src/app/page.tsx @@ -1,5 +1,5 @@ -import { ChatRoom } from "@/components/ChatRoom"; +import { Counter } from "@/components/Counter"; export default function Home() { - return ; + return ; } diff --git a/examples/counter-next-js/src/components/Counter.tsx b/examples/next-js/src/components/Counter.tsx similarity index 100% rename from examples/counter-next-js/src/components/Counter.tsx rename to examples/next-js/src/components/Counter.tsx diff --git a/examples/next-js/src/rivet/registry.ts b/examples/next-js/src/rivet/registry.ts index 40ab853108..1e6cdc4fca 100644 --- a/examples/next-js/src/rivet/registry.ts +++ b/examples/next-js/src/rivet/registry.ts @@ -1,32 +1,21 @@ import { actor, setup } from "rivetkit"; -export type Message = { sender: string; text: string; timestamp: number }; - -export const chatRoom = actor({ - options: { - sleepTimeout: 2000, - }, - // Persistent state that survives restarts +const counter = actor({ state: { - messages: [] as Message[], + count: 0, }, - actions: { - // Callable functions from clients - sendMessage: (c, sender: string, text: string) => { - const message = { sender, text, timestamp: Date.now() }; - // State changes are automatically persisted - c.state.messages.push(message); - // Send events to all connected clients - c.broadcast("newMessage", message); - return message; + increment: (c, x: number) => { + c.state.count += x; + c.broadcast("newCount", c.state.count); + return c.state.count; + }, + getCount: (c) => { + return c.state.count; }, - - getHistory: (c) => c.state.messages, }, }); -// Register actors for use export const registry = setup({ - use: { chatRoom }, + use: { counter }, }); diff --git a/examples/next-js/turbo.json b/examples/next-js/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/next-js/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/node/README.md b/examples/node/README.md new file mode 100644 index 0000000000..b509a0096c --- /dev/null +++ b/examples/node/README.md @@ -0,0 +1,17 @@ +# Node.js + +Minimal Node.js example demonstrating basic actor state management. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/node +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/starter/package.json b/examples/node/package.json similarity index 84% rename from examples/starter/package.json rename to examples/node/package.json index ec6d1f24e0..d6a25edff6 100644 --- a/examples/starter/package.json +++ b/examples/node/package.json @@ -1,5 +1,5 @@ { - "name": "starter", + "name": "node", "version": "2.0.21", "private": true, "scripts": { @@ -22,7 +22,9 @@ "typescript" ], "tags": [ - "quickstart" - ] - } + "starter" + ], + "noFrontend": true + }, + "license": "MIT" } diff --git a/examples/starter/scripts/client.ts b/examples/node/scripts/client.ts similarity index 100% rename from examples/starter/scripts/client.ts rename to examples/node/scripts/client.ts diff --git a/examples/starter/src/registry.ts b/examples/node/src/registry.ts similarity index 100% rename from examples/starter/src/registry.ts rename to examples/node/src/registry.ts diff --git a/examples/quickstart-native-websockets/src/backend/server.ts b/examples/node/src/server.ts similarity index 100% rename from examples/quickstart-native-websockets/src/backend/server.ts rename to examples/node/src/server.ts diff --git a/examples/starter/tsconfig.json b/examples/node/tsconfig.json similarity index 100% rename from examples/starter/tsconfig.json rename to examples/node/tsconfig.json diff --git a/examples/node/turbo.json b/examples/node/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/node/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-realtime/package.json b/examples/quickstart-realtime/package.json deleted file mode 100644 index 7cf9585882..0000000000 --- a/examples/quickstart-realtime/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "quickstart-realtime", - "version": "2.0.21", - "private": true, - "type": "module", - "scripts": { - "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"", - "dev:backend": "tsx --watch src/backend/server.ts", - "dev:frontend": "vite", - "check-types": "tsc --noEmit", - "test": "vitest run" - }, - "devDependencies": { - "@types/node": "^22.13.9", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "@vitejs/plugin-react": "^4.2.0", - "concurrently": "^8.2.2", - "tsx": "^3.12.7", - "typescript": "^5.5.2", - "vite": "^5.0.0", - "vitest": "^3.1.1", - "@rivetkit/react": "workspace:*", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "dependencies": { - "rivetkit": "workspace:*" - }, - "template": { - "technologies": [ - "typescript" - ], - "tags": [ - "quickstart", - "real-time" - ] - } -} diff --git a/examples/quickstart-realtime/src/backend/registry.ts b/examples/quickstart-realtime/src/backend/registry.ts deleted file mode 100644 index b963267add..0000000000 --- a/examples/quickstart-realtime/src/backend/registry.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { actor, setup } from "rivetkit"; - -export interface CursorPosition { - userId: string; - x: number; - y: number; -} - -export const cursorRoom = actor({ - // No persistent state needed for this simple example - state: {}, - - // Connection state stores each user's cursor position - connState: { - cursor: null as CursorPosition | null, - }, - - actions: { - // Update cursor position and broadcast to all connected clients - updateCursor: (c, userId: string, x: number, y: number) => { - const cursor: CursorPosition = { - userId, - x, - y, - }; - // Store cursor in connection state - c.conn.state.cursor = cursor; - // Broadcast cursor update to all clients - c.broadcast("cursorMoved", cursor); - return cursor; - }, - - // Get all active cursors from all connections - getCursors: (c) => { - const cursors: CursorPosition[] = []; - // Iterate through all connections and collect cursor data - for (const conn of c.conns.values()) { - if (conn.state.cursor) { - cursors.push(conn.state.cursor); - } - } - return cursors; - }, - }, -}); - -// Register actors for use: https://rivet.dev/docs/setup -export const registry = setup({ - use: { cursorRoom }, -}); diff --git a/examples/quickstart-realtime/src/frontend/App.tsx b/examples/quickstart-realtime/src/frontend/App.tsx deleted file mode 100644 index 521bf8c21f..0000000000 --- a/examples/quickstart-realtime/src/frontend/App.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { createRivetKit } from "@rivetkit/react"; -import { useState } from "react"; -import type { CursorPosition } from "../backend/registry"; - -const { useActor } = createRivetKit("http://localhost:6420"); - -// Generate a simple color from userId for visualization -function getUserColor(userId: string): string { - let hash = 0; - for (let i = 0; i < userId.length; i++) { - hash = userId.charCodeAt(i) + ((hash << 5) - hash); - } - const hue = hash % 360; - return `hsl(${hue}, 70%, 50%)`; -} - -export function App() { - const [userId] = useState(() => `user-${Math.random().toString(36).substr(2, 9)}`); - const [cursors, setCursors] = useState([]); - - // Connect to the cursor room - const cursorRoom = useActor({ - name: "cursorRoom", - key: ["main"], - }); - - // Listen for cursor moved events from other users - cursorRoom.useEvent("cursorMoved", (cursor: CursorPosition) => { - setCursors((prev) => { - // Update or add the cursor - const filtered = prev.filter((c) => c.userId !== cursor.userId); - return [...filtered, cursor]; - }); - }); - - // Handle mouse movement - const handleMouseMove = (e: React.MouseEvent) => { - if (cursorRoom.connection) { - const rect = e.currentTarget.getBoundingClientRect(); - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - cursorRoom.connection.updateCursor(userId, x, y); - } - }; - - return ( -
-
-

Quickstart: Realtime

-
- {cursorRoom.connection ? ( - Connected - ) : ( - Connecting... - )} -
-
- Your ID: {userId} -
-
-
- {cursors.map((cursor) => ( -
-
{cursor.userId}
-
- ))} -
-
- ); -} diff --git a/examples/quickstart-realtime/src/frontend/index.html b/examples/quickstart-realtime/src/frontend/index.html deleted file mode 100644 index a436cf5392..0000000000 --- a/examples/quickstart-realtime/src/frontend/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - Quickstart: Realtime - - - -
- - - diff --git a/examples/quickstart-realtime/tests/cursors.test.ts b/examples/quickstart-realtime/tests/cursors.test.ts deleted file mode 100644 index 35070c7b77..0000000000 --- a/examples/quickstart-realtime/tests/cursors.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { setupTest } from "rivetkit/test"; -import { describe, expect, test } from "vitest"; -import { registry } from "../src/backend/registry"; - -describe("cursor room", () => { - test("broadcasts cursor updates", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room1 = client.cursorRoom.getOrCreate(["room1"]); - - // Update cursor from client1 - const cursor = await room1.updateCursor("user1", 100, 200); - - // Verify cursor structure - expect(cursor).toMatchObject({ - userId: "user1", - x: 100, - y: 200, - }); - - // Verify getCursors returns the correct cursor - const cursors = await room1.getCursors(); - expect(cursors).toHaveLength(1); - expect(cursors[0]).toMatchObject({ - userId: "user1", - x: 100, - y: 200, - }); - }); - - test("handles multiple cursors", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room1 = client.cursorRoom.getOrCreate(["room2"]); - const room2 = client.cursorRoom.getOrCreate(["room2"]); - const room3 = client.cursorRoom.getOrCreate(["room2"]); - - // Each client updates their cursor - await room1.updateCursor("alice", 10, 20); - await room2.updateCursor("bob", 30, 40); - await room3.updateCursor("charlie", 50, 60); - - // Wait for all updates to propagate - await new Promise((resolve) => setTimeout(resolve, 100)); - - // Verify all clients see all three cursors - const cursors1 = await room1.getCursors(); - const cursors2 = await room2.getCursors(); - const cursors3 = await room3.getCursors(); - - expect(cursors1).toHaveLength(3); - expect(cursors2).toHaveLength(3); - expect(cursors3).toHaveLength(3); - - // Verify cursor positions are correct - const aliceCursor = cursors1.find((c) => c.userId === "alice"); - const bobCursor = cursors1.find((c) => c.userId === "bob"); - const charlieCursor = cursors1.find((c) => c.userId === "charlie"); - - expect(aliceCursor).toMatchObject({ userId: "alice", x: 10, y: 20 }); - expect(bobCursor).toMatchObject({ userId: "bob", x: 30, y: 40 }); - expect(charlieCursor).toMatchObject({ - userId: "charlie", - x: 50, - y: 60, - }); - }); - - test("multiple cursors in same room", async (ctx) => { - const { client } = await setupTest(ctx, registry); - const room1 = client.cursorRoom.getOrCreate(["room3"]); - const room2 = client.cursorRoom.getOrCreate(["room3"]); - - // Both clients update their cursors - await room1.updateCursor("user1", 100, 100); - await room2.updateCursor("user2", 200, 200); - - // Verify both cursors are present - const cursors = await room1.getCursors(); - expect(cursors).toHaveLength(2); - - // Verify cursor data - const user1Cursor = cursors.find((c) => c.userId === "user1"); - const user2Cursor = cursors.find((c) => c.userId === "user2"); - - expect(user1Cursor).toMatchObject({ userId: "user1", x: 100, y: 100 }); - expect(user2Cursor).toMatchObject({ userId: "user2", x: 200, y: 200 }); - }); -}); diff --git a/examples/quickstart-realtime/tsconfig.json b/examples/quickstart-realtime/tsconfig.json deleted file mode 100644 index d4efe57114..0000000000 --- a/examples/quickstart-realtime/tsconfig.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "target": "esnext", - /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - "lib": ["esnext", "dom"], - /* Specify what JSX code is generated. */ - "jsx": "react-jsx", - - /* Specify what module code is generated. */ - "module": "esnext", - /* Specify how TypeScript looks up a file from a given module specifier. */ - "moduleResolution": "bundler", - /* Specify type package names to be included without being referenced in a source file. */ - "types": ["node", "vite/client"], - /* Enable importing .json files */ - "resolveJsonModule": true, - - /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ - "allowJs": true, - /* Enable error reporting in type-checked JavaScript files. */ - "checkJs": false, - - /* Disable emitting files from a compilation. */ - "noEmit": true, - - /* Ensure that each file can be safely transpiled without relying on other imports. */ - "isolatedModules": true, - /* Allow 'import x from y' when a module doesn't have a default export. */ - "allowSyntheticDefaultImports": true, - /* Ensure that casing is correct in imports. */ - "forceConsistentCasingInFileNames": true, - - /* Enable all strict type-checking options. */ - "strict": true, - - /* Skip type checking all .d.ts files. */ - "skipLibCheck": true - }, - "include": ["src/**/*", "actors/**/*", "tests/**/*"] -} diff --git a/examples/quickstart-scheduling/vitest.config.ts b/examples/quickstart-scheduling/vitest.config.ts deleted file mode 100644 index 5bdee00206..0000000000 --- a/examples/quickstart-scheduling/vitest.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - include: ["tests/**/*.test.ts"], - }, -}); diff --git a/examples/quickstart-state/package.json b/examples/quickstart-state/package.json deleted file mode 100644 index 7f3c14e651..0000000000 --- a/examples/quickstart-state/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "quickstart-state", - "version": "2.0.21", - "private": true, - "type": "module", - "scripts": { - "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"", - "dev:backend": "tsx --watch src/backend/server.ts", - "dev:frontend": "vite", - "check-types": "tsc --noEmit", - "test": "vitest run" - }, - "devDependencies": { - "@types/node": "^22.13.9", - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "@vitejs/plugin-react": "^4.2.0", - "concurrently": "^8.2.2", - "tsx": "^3.12.7", - "typescript": "^5.5.2", - "vite": "^5.0.0", - "vitest": "^3.1.1", - "@rivetkit/react": "workspace:*", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "dependencies": { - "rivetkit": "workspace:*" - }, - "template": { - "technologies": [ - "typescript" - ], - "tags": [ - "quickstart" - ] - } -} diff --git a/examples/quickstart-state/src/backend/server.ts b/examples/quickstart-state/src/backend/server.ts deleted file mode 100644 index aa0ee6ed61..0000000000 --- a/examples/quickstart-state/src/backend/server.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { registry } from "./registry"; - -registry.start(); diff --git a/examples/quickstart-state/src/frontend/main.tsx b/examples/quickstart-state/src/frontend/main.tsx deleted file mode 100644 index bd39f29eec..0000000000 --- a/examples/quickstart-state/src/frontend/main.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import { App } from "./App"; - -const root = document.getElementById("root"); -if (!root) throw new Error("Root element not found"); - -createRoot(root).render( - - - -); diff --git a/examples/quickstart-state/vite.config.ts b/examples/quickstart-state/vite.config.ts deleted file mode 100644 index a291f28846..0000000000 --- a/examples/quickstart-state/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import react from "@vitejs/plugin-react"; -import { defineConfig } from "vite"; - -export default defineConfig({ - plugins: [react()], - root: "src/frontend", - server: { - port: 5173, - }, -}); diff --git a/examples/raw-fetch-handler/README.md b/examples/raw-fetch-handler/README.md index 76c4de3623..7656f8236b 100644 --- a/examples/raw-fetch-handler/README.md +++ b/examples/raw-fetch-handler/README.md @@ -1,10 +1,16 @@ -# Raw Fetch Handler Example for RivetKit +# Raw Fetch Handler Example -Example project demonstrating raw HTTP fetch handling with Hono integration in [RivetKit](https://rivetkit.org). +Example project demonstrating raw HTTP fetch handling with Hono integration. -[Learn More →](https://github.com/rivet-dev/rivetkit) +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/raw-fetch-handler +npm install +npm run dev +``` -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) ## Overview @@ -26,44 +32,6 @@ raw-fetch-handler/ └── tests/ # Vitest test suite ``` -## Getting Started - -### Prerequisites - -- Node.js - -### Installation - -```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/raw-fetch-handler -pnpm install -``` - -### Development - -Start both backend and frontend: - -```sh -pnpm dev -``` - -Or run them separately: - -```sh -# Terminal 1 - Backend -pnpm dev:backend - -# Terminal 2 - Frontend -pnpm dev:frontend -``` - -Run tests: - -```sh -pnpm test -``` - ## Features ### Backend @@ -94,4 +62,4 @@ A React app demonstrating: ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/raw-fetch-handler/package.json b/examples/raw-fetch-handler/package.json index c5044b2977..caf7b6e8ea 100644 --- a/examples/raw-fetch-handler/package.json +++ b/examples/raw-fetch-handler/package.json @@ -35,6 +35,8 @@ "technologies": [ "typescript" ], - "tags": [] - } + "tags": [], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/raw-websocket-handler-proxy/README.md b/examples/raw-websocket-handler-proxy/README.md index a3f266f2a2..8547e15397 100644 --- a/examples/raw-websocket-handler-proxy/README.md +++ b/examples/raw-websocket-handler-proxy/README.md @@ -1,41 +1,16 @@ -# Raw WebSocket Handler Proxy for RivetKit +# Raw WebSocket Handler Proxy -Example project demonstrating raw WebSocket handling with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Demonstrates raw WebSocket handling using a proxy endpoint pattern for routing connections to actors. ## Getting Started -### Prerequisites - -- Node.js 18 or later -- pnpm (for monorepo management) - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/raw-websocket-handler-proxy +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/raw-websocket-handler-proxy npm install -``` - -### Development - -```sh npm run dev ``` -This starts both the backend server (on port 9000) and the frontend development server (on port 5173). - -Open http://localhost:5173 in your browser to see the chat application demo. - -### Testing - -```sh -npm test -``` ## Features @@ -52,4 +27,4 @@ This example demonstrates: ## License -Apache 2.0 +MIT diff --git a/examples/raw-websocket-handler-proxy/package.json b/examples/raw-websocket-handler-proxy/package.json index c7ec45214f..712173a1bc 100644 --- a/examples/raw-websocket-handler-proxy/package.json +++ b/examples/raw-websocket-handler-proxy/package.json @@ -44,5 +44,6 @@ "typescript" ], "tags": [] - } + }, + "license": "MIT" } diff --git a/examples/raw-websocket-handler/README.md b/examples/raw-websocket-handler/README.md index a3f266f2a2..7e7dbd7e33 100644 --- a/examples/raw-websocket-handler/README.md +++ b/examples/raw-websocket-handler/README.md @@ -1,41 +1,16 @@ -# Raw WebSocket Handler Proxy for RivetKit +# Raw WebSocket Handler -Example project demonstrating raw WebSocket handling with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Demonstrates raw WebSocket handling with direct actor connections and real-time chat functionality. ## Getting Started -### Prerequisites - -- Node.js 18 or later -- pnpm (for monorepo management) - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/raw-websocket-handler-proxy +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/raw-websocket-handler npm install -``` - -### Development - -```sh npm run dev ``` -This starts both the backend server (on port 9000) and the frontend development server (on port 5173). - -Open http://localhost:5173 in your browser to see the chat application demo. - -### Testing - -```sh -npm test -``` ## Features @@ -52,4 +27,4 @@ This example demonstrates: ## License -Apache 2.0 +MIT diff --git a/examples/raw-websocket-handler/package.json b/examples/raw-websocket-handler/package.json index bf3483a094..f7c9f9e25d 100644 --- a/examples/raw-websocket-handler/package.json +++ b/examples/raw-websocket-handler/package.json @@ -43,6 +43,8 @@ ], "tags": [ "real-time" - ] - } + ], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/react/README.md b/examples/react/README.md index e8a7232a12..5aa70efcd2 100644 --- a/examples/react/README.md +++ b/examples/react/README.md @@ -1,33 +1,17 @@ -# Hono React Integration for RivetKit +# React Integration -Example project demonstrating full-stack Hono backend with React frontend integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Demonstrates React frontend integration with Rivet Actors. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/hono-react +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/react npm install -``` - -### Development - -```sh npm run dev ``` -This will start both the Hono backend server and Vite React frontend. Open your browser to http://localhost:5173 to see the React app connected to Rivet Actors. ## License -Apache 2.0 +MIT diff --git a/examples/react/package.json b/examples/react/package.json index 3acc528a0c..d0dab2736b 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -35,5 +35,6 @@ "typescript" ], "tags": [] - } + }, + "license": "MIT" } diff --git a/examples/scheduling/README.md b/examples/scheduling/README.md new file mode 100644 index 0000000000..291791a6c2 --- /dev/null +++ b/examples/scheduling/README.md @@ -0,0 +1,17 @@ +# Scheduling + +Demonstrates how to schedule tasks and execute code at specific times or intervals using Rivet Actors. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/scheduling +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/quickstart-cross-actor-actions/package.json b/examples/scheduling/package.json similarity index 91% rename from examples/quickstart-cross-actor-actions/package.json rename to examples/scheduling/package.json index 9ac8e3a8e1..a07258b275 100644 --- a/examples/quickstart-cross-actor-actions/package.json +++ b/examples/scheduling/package.json @@ -1,5 +1,5 @@ { - "name": "quickstart-cross-actor-actions", + "name": "scheduling", "version": "2.0.21", "private": true, "type": "module", @@ -33,6 +33,8 @@ ], "tags": [ "quickstart" - ] - } + ], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/quickstart-scheduling/src/backend/registry.ts b/examples/scheduling/src/backend/registry.ts similarity index 100% rename from examples/quickstart-scheduling/src/backend/registry.ts rename to examples/scheduling/src/backend/registry.ts diff --git a/examples/quickstart-realtime/src/backend/server.ts b/examples/scheduling/src/backend/server.ts similarity index 100% rename from examples/quickstart-realtime/src/backend/server.ts rename to examples/scheduling/src/backend/server.ts diff --git a/examples/quickstart-scheduling/src/frontend/App.tsx b/examples/scheduling/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-scheduling/src/frontend/App.tsx rename to examples/scheduling/src/frontend/App.tsx diff --git a/examples/quickstart-scheduling/src/frontend/index.html b/examples/scheduling/src/frontend/index.html similarity index 100% rename from examples/quickstart-scheduling/src/frontend/index.html rename to examples/scheduling/src/frontend/index.html diff --git a/examples/quickstart-realtime/src/frontend/main.tsx b/examples/scheduling/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-realtime/src/frontend/main.tsx rename to examples/scheduling/src/frontend/main.tsx diff --git a/examples/quickstart-scheduling/tests/scheduling.test.ts b/examples/scheduling/tests/scheduling.test.ts similarity index 100% rename from examples/quickstart-scheduling/tests/scheduling.test.ts rename to examples/scheduling/tests/scheduling.test.ts diff --git a/examples/quickstart-scheduling/tsconfig.json b/examples/scheduling/tsconfig.json similarity index 100% rename from examples/quickstart-scheduling/tsconfig.json rename to examples/scheduling/tsconfig.json diff --git a/examples/scheduling/turbo.json b/examples/scheduling/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/scheduling/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-realtime/vite.config.ts b/examples/scheduling/vite.config.ts similarity index 100% rename from examples/quickstart-realtime/vite.config.ts rename to examples/scheduling/vite.config.ts diff --git a/examples/quickstart-realtime/vitest.config.ts b/examples/scheduling/vitest.config.ts similarity index 100% rename from examples/quickstart-realtime/vitest.config.ts rename to examples/scheduling/vitest.config.ts diff --git a/examples/starter/README.md b/examples/starter/README.md deleted file mode 100644 index 2bd2133c3c..0000000000 --- a/examples/starter/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# Rivet Platform for RivetKit - -Example project demonstrating Rivet cloud platform deployment with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) - -## Getting Started - -### Prerequisites - -- Node.js -- Rivet CLI (`npm install -g @rivet-dev/cli`) -- Rivet Cloud account - -### Installation - -```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/rivet -npm install -``` - -### Configuration - -Set up your environment variables: - -```sh -export RIVET_ENDPOINT=https://api.rivet.dev -export RIVET_SERVICE_TOKEN=your_service_token -export RIVET_PROJECT=your_project_id -export RIVET_ENVIRONMENT=your_environment -``` - -### Development - -```sh -npm run dev -``` - -This will start the RivetKit server locally at http://localhost:8080. - -### Testing the Client - -In a separate terminal, run the client script to interact with your actors: - -```sh -npm run client -``` - -### Deployment - -Deploy to Rivet Cloud: - -```sh -rivet deploy -``` - -Your Rivet Actors will be deployed as Rivet actors with automatic scaling and management. - -## License - -Apache 2.0 diff --git a/examples/starter/src/server.ts b/examples/starter/src/server.ts deleted file mode 100644 index aa0ee6ed61..0000000000 --- a/examples/starter/src/server.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { registry } from "./registry"; - -registry.start(); diff --git a/examples/state/README.md b/examples/state/README.md new file mode 100644 index 0000000000..54fa5b854c --- /dev/null +++ b/examples/state/README.md @@ -0,0 +1,17 @@ +# State Management + +Demonstrates persistent state management in Rivet Actors with automatic state saving and restoration. + +## Getting Started + +```sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/state +npm install +npm run dev +``` + + +## License + +MIT diff --git a/examples/quickstart-multi-region/package.json b/examples/state/package.json similarity index 92% rename from examples/quickstart-multi-region/package.json rename to examples/state/package.json index 1d21fa8138..5c1d305b18 100644 --- a/examples/quickstart-multi-region/package.json +++ b/examples/state/package.json @@ -1,5 +1,5 @@ { - "name": "quickstart-multi-region", + "name": "state", "version": "2.0.21", "private": true, "type": "module", @@ -33,6 +33,8 @@ ], "tags": [ "quickstart" - ] - } + ], + "priority": 1000 + }, + "license": "MIT" } diff --git a/examples/quickstart-state/src/backend/registry.ts b/examples/state/src/backend/registry.ts similarity index 100% rename from examples/quickstart-state/src/backend/registry.ts rename to examples/state/src/backend/registry.ts diff --git a/examples/quickstart-scheduling/src/backend/server.ts b/examples/state/src/backend/server.ts similarity index 100% rename from examples/quickstart-scheduling/src/backend/server.ts rename to examples/state/src/backend/server.ts diff --git a/examples/quickstart-state/src/frontend/App.tsx b/examples/state/src/frontend/App.tsx similarity index 100% rename from examples/quickstart-state/src/frontend/App.tsx rename to examples/state/src/frontend/App.tsx diff --git a/examples/quickstart-state/src/frontend/index.html b/examples/state/src/frontend/index.html similarity index 100% rename from examples/quickstart-state/src/frontend/index.html rename to examples/state/src/frontend/index.html diff --git a/examples/quickstart-scheduling/src/frontend/main.tsx b/examples/state/src/frontend/main.tsx similarity index 100% rename from examples/quickstart-scheduling/src/frontend/main.tsx rename to examples/state/src/frontend/main.tsx diff --git a/examples/quickstart-state/tests/chat.test.ts b/examples/state/tests/chat.test.ts similarity index 100% rename from examples/quickstart-state/tests/chat.test.ts rename to examples/state/tests/chat.test.ts diff --git a/examples/quickstart-state/tsconfig.json b/examples/state/tsconfig.json similarity index 100% rename from examples/quickstart-state/tsconfig.json rename to examples/state/tsconfig.json diff --git a/examples/state/turbo.json b/examples/state/turbo.json new file mode 100644 index 0000000000..29d4cb2625 --- /dev/null +++ b/examples/state/turbo.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"] +} diff --git a/examples/quickstart-scheduling/vite.config.ts b/examples/state/vite.config.ts similarity index 100% rename from examples/quickstart-scheduling/vite.config.ts rename to examples/state/vite.config.ts diff --git a/examples/quickstart-state/vitest.config.ts b/examples/state/vitest.config.ts similarity index 100% rename from examples/quickstart-state/vitest.config.ts rename to examples/state/vitest.config.ts diff --git a/examples/stream/README.md b/examples/stream/README.md index 906d7dbd9d..5e503d43fc 100644 --- a/examples/stream/README.md +++ b/examples/stream/README.md @@ -1,32 +1,16 @@ -# Stream Processor for RivetKit +# Stream Processor -Example project demonstrating real-time top-K stream processing with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating real-time top-K stream processing. ## Getting Started -### Prerequisites - -- Node.js 18+ - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/stream +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/stream npm install -``` - -### Development - -```sh npm run dev ``` -Open your browser to `http://localhost:3000` ## Features @@ -123,4 +107,4 @@ The example includes basic structural tests. For production use, consider adding ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/stream/package.json b/examples/stream/package.json index f647d71afb..19b0bf8615 100644 --- a/examples/stream/package.json +++ b/examples/stream/package.json @@ -33,5 +33,6 @@ "tags": [ "real-time" ] - } + }, + "license": "MIT" } diff --git a/examples/trpc/README.md b/examples/trpc/README.md index 228963c1b6..7d7278a805 100644 --- a/examples/trpc/README.md +++ b/examples/trpc/README.md @@ -1,37 +1,17 @@ -# tRPC Integration for RivetKit +# tRPC Integration -Example project demonstrating tRPC integration with [RivetKit](https://rivetkit.org). - -[Learn More →](https://github.com/rivet-dev/rivetkit) - -[Discord](https://rivet.dev/discord) — [Documentation](https://rivetkit.org) — [Issues](https://github.com/rivet-dev/rivetkit/issues) +Example project demonstrating tRPC integration. ## Getting Started -### Prerequisites - -- Node.js - -### Installation - ```sh -git clone https://github.com/rivet-dev/rivetkit -cd rivetkit/examples/trpc +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/trpc npm install -``` - -### Development - -```sh npm run dev ``` -Run the client script to interact with the tRPC server: - -```sh -npm run client -``` ## License -Apache 2.0 \ No newline at end of file +MIT diff --git a/examples/trpc/package.json b/examples/trpc/package.json index 559784d504..321fcefbe5 100644 --- a/examples/trpc/package.json +++ b/examples/trpc/package.json @@ -25,6 +25,8 @@ "trpc", "typescript" ], - "tags": [] - } + "tags": [], + "noFrontend": true + }, + "license": "MIT" } diff --git a/frontend/packages/example-registry/package.json b/frontend/packages/example-registry/package.json index e369e2c99c..6ae9283b49 100644 --- a/frontend/packages/example-registry/package.json +++ b/frontend/packages/example-registry/package.json @@ -1,5 +1,5 @@ { - "name": "@rivet-gg/example-registry", + "name": "@rivetkit/example-registry", "private": true, "version": "2.0.21", "type": "module", @@ -16,10 +16,11 @@ }, "types": "./dist/index.d.ts", "scripts": { - "build": "tsx scripts/build.ts" + "build": "tsx scripts/build/index.ts" }, "devDependencies": { "@types/node": "^22.13.9", + "puppeteer": "^23.11.1", "tsx": "^4.20.6", "typescript": "^5.9.3" } diff --git a/frontend/packages/example-registry/scripts/build.ts b/frontend/packages/example-registry/scripts/build.ts deleted file mode 100644 index baa29f93da..0000000000 --- a/frontend/packages/example-registry/scripts/build.ts +++ /dev/null @@ -1,121 +0,0 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -interface TemplateMetadata { - technologies: string[]; - tags: string[]; -} - -interface PackageJson { - name: string; - template?: TemplateMetadata; -} - -interface Template { - name: string; - displayName: string; - description: string; - technologies: string[]; - tags: string[]; -} - -async function main() { - // Path to examples directory (from example-registry package) - const examplesDir = path.join(__dirname, "../../../../examples"); - const outputFile = path.join(__dirname, "../src/_gen.ts"); - - // Read all example directories - const entries = await fs.readdir(examplesDir, { withFileTypes: true }); - const exampleDirs = entries.filter((entry) => entry.isDirectory()); - - const templates: Template[] = []; - - for (const dir of exampleDirs) { - const packageJsonPath = path.join(examplesDir, dir.name, "package.json"); - const readmePath = path.join(examplesDir, dir.name, "README.md"); - - try { - // Read package.json - const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8"); - const packageJson: PackageJson = JSON.parse(packageJsonContent); - - // Error if no template metadata - if (!packageJson.template) { - throw new Error( - `Missing template metadata in ${dir.name}/package.json. Please add a "template" property with technologies and tags.`, - ); - } - - // Read README.md to extract description - let description = ""; - let displayName = dir.name; - - try { - const readmeContent = await fs.readFile(readmePath, "utf-8"); - // Extract first paragraph after the title as description - const lines = readmeContent.split("\n"); - let foundTitle = false; - for (const line of lines) { - // Extract display name from title (e.g., "# Counter Example" -> "Counter Example") - if (line.startsWith("# ")) { - displayName = line.slice(2).trim(); - foundTitle = true; - continue; - } - // Get first non-empty line after title as description - if (foundTitle && line.trim() !== "") { - description = line.trim(); - break; - } - } - } catch (error) { - console.warn(`Could not read README.md for ${dir.name}:`, error); - } - - // Always add "rivet" as the first technology if not present - const technologies = packageJson.template.technologies.includes("rivet") - ? packageJson.template.technologies - : ["rivet", ...packageJson.template.technologies]; - - templates.push({ - name: dir.name, - displayName, - description: description || `Example project for ${displayName}`, - technologies, - tags: packageJson.template.tags, - }); - } catch (error) { - console.warn(`Error processing ${dir.name}:`, error); - } - } - - // Sort templates by name - templates.sort((a, b) => a.name.localeCompare(b.name)); - - // Generate TypeScript file - const output = `// This file is auto-generated by scripts/build.ts -// Do not edit manually - -export interface Template { - name: string; - displayName: string; - description: string; - technologies: string[]; - tags: string[]; -} - -export const templates: Template[] = ${JSON.stringify(templates, null, 2)}; -`; - - await fs.writeFile(outputFile, output, "utf-8"); - console.log(`✅ Generated ${templates.length} templates to ${outputFile}`); -} - -main().catch((error) => { - console.error("Failed to generate templates:", error); - process.exit(1); -}); diff --git a/frontend/packages/example-registry/scripts/build/index.ts b/frontend/packages/example-registry/scripts/build/index.ts new file mode 100644 index 0000000000..e6bf9af8bf --- /dev/null +++ b/frontend/packages/example-registry/scripts/build/index.ts @@ -0,0 +1,298 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { generateScreenshots } from "./screenshots.js"; +import { validateReadmeFormat, validateRivetKitVersions, validatePackageJson, validateTurboJson } from "./validate.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +interface TemplateMetadata { + technologies: string[]; + tags: string[]; + noFrontend?: boolean; + priority?: number; +} + +interface PackageJson { + name: string; + license?: string; + template?: TemplateMetadata; + scripts?: Record; + dependencies?: Record; + devDependencies?: Record; +} + +interface Template { + name: string; + displayName: string; + description: string; + technologies: string[]; + tags: string[]; + noFrontend: boolean; + priority?: number; +} + +function generateGettingStartedSection(exampleName: string): string { + return `## Getting Started + +\`\`\`sh +git clone https://github.com/rivet-dev/rivet.git +cd rivet/examples/${exampleName} +npm install +npm run dev +\`\`\` +`; +} + +function generateLicenseSection(): string { + return `## License + +MIT +`; +} + +function processReadme(content: string, exampleName: string): string { + const lines = content.split('\n'); + let titleLine = ''; + let descriptionLine = ''; + let contentLines: string[] = []; + let foundTitle = false; + let foundDescription = false; + let inGettingStarted = false; + let inLicense = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + // Extract title + if (!foundTitle && line.startsWith('# ')) { + titleLine = line; + foundTitle = true; + continue; + } + + // Extract description (first non-empty line after title) + if (foundTitle && !foundDescription && line.trim() !== '') { + descriptionLine = line; + foundDescription = true; + continue; + } + + // Skip empty lines between title and description + if (foundTitle && !foundDescription && line.trim() === '') { + continue; + } + + // Skip Getting Started section + if (line.match(/^##\s+Getting Started/i)) { + inGettingStarted = true; + continue; + } + + // Skip License section + if (line.match(/^##\s+License/i)) { + inLicense = true; + continue; + } + + // Check if we're exiting a section + if ((inGettingStarted || inLicense) && line.startsWith('## ')) { + inGettingStarted = false; + inLicense = false; + // Don't skip this line, it's a new section + } + + // Skip content within Getting Started or License sections + if (inGettingStarted || inLicense) { + continue; + } + + // Add to content if we've found description + if (foundDescription) { + contentLines.push(line); + } + } + + // Reconstruct README + const parts = [ + titleLine, + '', + descriptionLine, + '', + generateGettingStartedSection(exampleName), + ...contentLines, + ]; + + // Add license at the end (trim trailing whitespace first) + while (parts.length > 0 && parts[parts.length - 1].trim() === '') { + parts.pop(); + } + parts.push(''); + parts.push(generateLicenseSection().trim()); + + return parts.join('\n') + '\n'; +} + +async function main() { + // Path to examples directory (from example-registry package) + const examplesDir = path.join(__dirname, "../../../../../examples"); + const outputFile = path.join(__dirname, "../../src/_gen.ts"); + const websitePublicDir = path.join( + __dirname, + "../../../../../website/public/examples", + ); + + // Read all example directories + const entries = await fs.readdir(examplesDir, { withFileTypes: true }); + const exampleDirs = entries.filter((entry) => entry.isDirectory()); + + const templates: Template[] = []; + const errors: Array<{ example: string; error: Error }> = []; + + for (const dir of exampleDirs) { + const packageJsonPath = path.join(examplesDir, dir.name, "package.json"); + const readmePath = path.join(examplesDir, dir.name, "README.md"); + + // Skip directories without package.json + try { + await fs.access(packageJsonPath); + } catch { + console.warn(`Skipping ${dir.name}: no package.json found`); + continue; + } + + try { + // Read package.json + const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8"); + const packageJson: PackageJson = JSON.parse(packageJsonContent); + + // Error if no template metadata + if (!packageJson.template) { + throw new Error( + `Missing template metadata in ${dir.name}/package.json. Please add a "template" property with technologies and tags.`, + ); + } + + // Validate package.json requirements + validatePackageJson(packageJson, dir.name); + + // Validate rivetkit package versions + validateRivetKitVersions(packageJson, dir.name); + + // Validate turbo.json exists + await validateTurboJson(path.join(examplesDir, dir.name), dir.name); + + // Read README.md to extract description and validate format + let description = ""; + let displayName = dir.name; + + try { + const readmeContent = await fs.readFile(readmePath, "utf-8"); + const validated = validateReadmeFormat(readmeContent, dir.name); + displayName = validated.displayName; + description = validated.description; + + // Process and update README with standardized getting started and license + const processedReadme = processReadme(readmeContent, dir.name); + await fs.writeFile(readmePath, processedReadme, "utf-8"); + console.log(`✅ Processed README for ${dir.name}`); + } catch (error) { + if ( + error instanceof Error && + error.message.includes("README format validation failed") + ) { + throw error; + } + throw new Error(`Could not read README.md for ${dir.name}: ${error}`); + } + + // Always add "rivet" as the first technology if not present + const technologies = packageJson.template.technologies.includes("rivet") + ? packageJson.template.technologies + : ["rivet", ...packageJson.template.technologies]; + + templates.push({ + name: dir.name, + displayName, + description: description || `Example project for ${displayName}`, + technologies, + tags: packageJson.template.tags, + noFrontend: packageJson.template.noFrontend ?? false, + priority: packageJson.template.priority, + }); + } catch (error) { + errors.push({ + example: dir.name, + error: error instanceof Error ? error : new Error(String(error)), + }); + } + } + + // If there were any errors, print them all and exit + if (errors.length > 0) { + console.error("\n❌ Validation failed for the following examples:\n"); + for (const { example, error } of errors) { + console.error(`\n${example}:`); + console.error(` ${error.message}`); + } + console.error(`\n\nTotal errors: ${errors.length}`); + process.exit(1); + } + + // Sort templates by priority (ascending), then by name alphabetically + templates.sort((a, b) => { + // Templates with priority come first + if (a.priority !== undefined && b.priority === undefined) return -1; + if (a.priority === undefined && b.priority !== undefined) return 1; + + // Both have priority, sort by priority value (ascending) + if (a.priority !== undefined && b.priority !== undefined) { + if (a.priority !== b.priority) return a.priority - b.priority; + } + + // Same priority or both undefined, sort alphabetically by name + return a.name.localeCompare(b.name); + }); + + // Generate TypeScript file + const output = `// This file is auto-generated by scripts/build/index.ts +// Do not edit manually + +export interface Template { + name: string; + displayName: string; + description: string; + technologies: string[]; + tags: string[]; + noFrontend: boolean; + priority?: number; +} + +export const templates: Template[] = ${JSON.stringify(templates, null, 2)}; +`; + + await fs.writeFile(outputFile, output, "utf-8"); + console.log(`✅ Generated ${templates.length} templates to ${outputFile}`); + + // Delete public images for noFrontend templates + for (const template of templates) { + if (template.noFrontend) { + const imageDir = path.join(websitePublicDir, template.name); + try { + await fs.rm(imageDir, { recursive: true }); + console.log(`🗑️ Deleted image directory for ${template.name} (noFrontend)`); + } catch { + // Directory doesn't exist, nothing to delete + } + } + } + + // Generate screenshots + await generateScreenshots(examplesDir, websitePublicDir); +} + +main().catch((error) => { + console.error("Failed to generate templates:", error); + process.exit(1); +}); diff --git a/frontend/packages/example-registry/scripts/build/screenshots.ts b/frontend/packages/example-registry/scripts/build/screenshots.ts new file mode 100644 index 0000000000..27343fc162 --- /dev/null +++ b/frontend/packages/example-registry/scripts/build/screenshots.ts @@ -0,0 +1,230 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import { spawn } from "node:child_process"; +import puppeteer from "puppeteer"; + +const SCREENSHOT_WIDTH = 1200; +const SCREENSHOT_HEIGHT = 675; // 16:9 aspect ratio +const DEV_SERVER_TIMEOUT = 60000; // 60 seconds to start dev server +const SCREENSHOT_DELAY = 3000; // Wait 3 seconds after page load for rendering + +async function waitForServer(url: string, timeout: number): Promise { + const startTime = Date.now(); + + while (Date.now() - startTime < timeout) { + try { + const response = await fetch(url); + if (response.ok || response.status === 404) { + return true; + } + } catch { + // Server not ready yet + } + await new Promise((resolve) => setTimeout(resolve, 500)); + } + + return false; +} + +async function takeScreenshot( + exampleName: string, + examplePath: string, + outputPath: string, +): Promise { + console.log(`📸 Taking screenshot for ${exampleName}...`); + + // Check if package.json has a dev script + const packageJsonPath = path.join(examplePath, "package.json"); + const packageJson = JSON.parse( + await fs.readFile(packageJsonPath, "utf-8"), + ); + + if (!packageJson.scripts?.dev) { + console.log(`⚠️ Skipping ${exampleName}: no dev script found`); + return; + } + + // Start dev server + console.log(`🚀 Starting dev server for ${exampleName}...`); + const devProcess = spawn("pnpm", ["dev"], { + cwd: examplePath, + stdio: ["ignore", "pipe", "pipe"], + shell: true, + }); + + let serverUrl: string | null = null; + let serverReady = false; + let processExited = false; + let processError: Error | null = null; + + // Track if process exits prematurely + devProcess.on("exit", (code) => { + processExited = true; + if (code !== 0 && code !== null) { + processError = new Error(`Dev server exited with code ${code}`); + } + }); + + // Capture output to detect server URL and readiness + const outputHandler = (data: Buffer) => { + const output = data.toString(); + console.log(`[${exampleName}] ${output.trim()}`); + + // Try to detect common dev server URLs + const urlMatch = output.match(/https?:\/\/localhost:\d+/); + if (urlMatch && !serverUrl) { + serverUrl = urlMatch[0]; + console.log(`🔍 Detected server URL: ${serverUrl}`); + } + }; + + devProcess.stdout?.on("data", outputHandler); + devProcess.stderr?.on("data", outputHandler); + + try { + // Wait for URL to be detected from output + console.log(`⏳ Waiting for dev server URL to be detected...`); + const urlDetectionStart = Date.now(); + while ( + !serverUrl && + !processExited && + Date.now() - urlDetectionStart < DEV_SERVER_TIMEOUT + ) { + await new Promise((resolve) => setTimeout(resolve, 100)); + } + + if (processError) { + throw processError; + } + + if (processExited) { + throw new Error(`Dev server exited unexpectedly before starting`); + } + + if (!serverUrl) { + throw new Error( + `Could not detect server URL from dev server output within ${DEV_SERVER_TIMEOUT}ms`, + ); + } + + // Wait for server to be ready + console.log(`⏳ Waiting for server at ${serverUrl}...`); + serverReady = await waitForServer(serverUrl, DEV_SERVER_TIMEOUT); + + if (!serverReady) { + throw new Error( + `Dev server did not start within ${DEV_SERVER_TIMEOUT}ms`, + ); + } + + console.log(`✅ Server ready at ${serverUrl}`); + + // Additional delay for app to fully render + await new Promise((resolve) => setTimeout(resolve, SCREENSHOT_DELAY)); + + // Launch browser and take screenshot + const browser = await puppeteer.launch({ + headless: true, + args: ["--no-sandbox", "--disable-setuid-sandbox"], + }); + + const page = await browser.newPage(); + await page.setViewport({ + width: SCREENSHOT_WIDTH, + height: SCREENSHOT_HEIGHT, + deviceScaleFactor: 2, // Capture at 2x resolution + }); + + const response = await page.goto(serverUrl, { waitUntil: "networkidle0" }); + + if (!response || !response.ok()) { + const status = response?.status() ?? "unknown"; + throw new Error( + `Frontend returned non-200 status: ${status} for ${exampleName}`, + ); + } + + // Additional delay for any animations or async content + await new Promise((resolve) => setTimeout(resolve, 2000)); + + await page.screenshot({ + path: outputPath, + type: "png", + }); + + await browser.close(); + + console.log(`✅ Screenshot saved to ${outputPath}`); + } finally { + // Kill dev server + devProcess.kill("SIGTERM"); + + // Give it a moment to clean up + await new Promise((resolve) => setTimeout(resolve, 1000)); + + // Force kill if still running + if (!devProcess.killed) { + devProcess.kill("SIGKILL"); + } + } +} + +export async function generateScreenshots( + examplesDir: string, + websitePublicDir: string, +) { + console.log("\n🖼️ Generating screenshots..."); + + // Ensure output directory exists + await fs.mkdir(websitePublicDir, { recursive: true }); + + // Read all example directories + const entries = await fs.readdir(examplesDir, { withFileTypes: true }); + const exampleDirs = entries.filter((entry) => entry.isDirectory()); + + for (const dir of exampleDirs) { + const examplePath = path.join(examplesDir, dir.name); + const packageJsonPath = path.join(examplePath, "package.json"); + + // Skip if no package.json + try { + await fs.access(packageJsonPath); + } catch { + console.log(`⏭️ Skipping ${dir.name}: no package.json`); + continue; + } + + // Skip if noFrontend is set + const packageJson = JSON.parse( + await fs.readFile(packageJsonPath, "utf-8"), + ); + if (packageJson.template?.noFrontend) { + console.log(`⏭️ Skipping ${dir.name}: noFrontend is set`); + continue; + } + + const outputDir = path.join(websitePublicDir, dir.name); + const outputPath = path.join(outputDir, "image.png"); + + // Check if screenshot already exists + try { + await fs.access(outputPath); + console.log(`⏭️ Skipping ${dir.name}: screenshot already exists`); + continue; + } catch { + // Screenshot doesn't exist, create it + } + + // Create output directory + await fs.mkdir(outputDir, { recursive: true }); + + try { + await takeScreenshot(dir.name, examplePath, outputPath); + } catch (error) { + console.error(`❌ Failed to generate screenshot for ${dir.name}:`, error); + // Continue with next example + } + } + + console.log("\n✅ Screenshot generation complete!"); +} diff --git a/frontend/packages/example-registry/scripts/build/validate.ts b/frontend/packages/example-registry/scripts/build/validate.ts new file mode 100644 index 0000000000..4eb8c550a6 --- /dev/null +++ b/frontend/packages/example-registry/scripts/build/validate.ts @@ -0,0 +1,152 @@ +interface PackageJson { + name: string; + license?: string; + template?: { + technologies: string[]; + tags: string[]; + }; + scripts?: Record; + dependencies?: Record; + devDependencies?: Record; +} + +const MAX_TITLE_LENGTH = 60; +const MAX_DESCRIPTION_LENGTH = 200; + +export function validateReadmeFormat( + readmeContent: string, + exampleName: string, +): { displayName: string; description: string } { + const lines = readmeContent.split("\n"); + let displayName = ""; + let description = ""; + let foundTitle = false; + + for (const line of lines) { + // Extract display name from title (e.g., "# Counter Example" -> "Counter Example") + if (line.startsWith("# ")) { + displayName = line.slice(2).trim(); + foundTitle = true; + continue; + } + // Get first non-empty line after title as description + if (foundTitle && line.trim() !== "") { + description = line.trim(); + break; + } + } + + // Validate README format + if (!displayName) { + throw new Error( + `README format validation failed for ${exampleName}: Missing title (# Heading)`, + ); + } + + // Validate title length + if (displayName.length > MAX_TITLE_LENGTH) { + throw new Error( + `README format validation failed for ${exampleName}: Title too long (${displayName.length} > ${MAX_TITLE_LENGTH}). Title: "${displayName}"`, + ); + } + + // Check for "rivet" or "rivetkit" in title (case-insensitive) + if (/rivet/i.test(displayName)) { + throw new Error( + `README format validation failed for ${exampleName}: Title should not contain "rivet" or "rivetkit". Title: "${displayName}"`, + ); + } + + // Check for "Learn More" section + if (readmeContent.includes("[Learn More")) { + throw new Error( + `README format validation failed for ${exampleName}: README should not contain "Learn More" section`, + ); + } + + // Check for Discord/Documentation/Issues links + if ( + readmeContent.includes("[Discord]") && + readmeContent.includes("[Documentation]") && + readmeContent.includes("[Issues]") + ) { + throw new Error( + `README format validation failed for ${exampleName}: README should not contain Discord/Documentation/Issues links section`, + ); + } + + return { displayName, description }; +} + +export function validateRivetKitVersions( + packageJson: PackageJson, + exampleName: string, +): void { + const allDeps = { + ...packageJson.dependencies, + ...packageJson.devDependencies, + }; + + for (const [pkgName, version] of Object.entries(allDeps)) { + // Check if it's a rivetkit or @rivetkit/* package + if (pkgName === "rivetkit" || pkgName.startsWith("@rivetkit/")) { + // Allow workspace:* for monorepo development + if (version === "workspace:*") { + continue; + } + + // Otherwise, must be exactly "latest" + if (version !== "latest") { + throw new Error( + `Package version validation failed for ${exampleName}: Package "${pkgName}" version must be "latest" (found "${version}")`, + ); + } + } + } +} + +export function validatePackageJson( + packageJson: PackageJson, + exampleName: string, +): void { + // Check for MIT license + if (packageJson.license !== "MIT") { + throw new Error( + `Package.json validation failed for ${exampleName}: license must be "MIT" (found "${packageJson.license || 'none'}")`, + ); + } + + // Check for required scripts + if (!packageJson.scripts) { + throw new Error( + `Package.json validation failed for ${exampleName}: Missing scripts section`, + ); + } + + if (!packageJson.scripts.dev) { + throw new Error( + `Package.json validation failed for ${exampleName}: Missing "dev" script`, + ); + } + + if (!packageJson.scripts["check-types"]) { + throw new Error( + `Package.json validation failed for ${exampleName}: Missing "check-types" script`, + ); + } +} + +export async function validateTurboJson( + exampleDir: string, + exampleName: string, +): Promise { + const turboJsonPath = `${exampleDir}/turbo.json`; + try { + const fs = await import("node:fs/promises"); + await fs.access(turboJsonPath); + } catch { + throw new Error( + `Validation failed for ${exampleName}: Missing turbo.json file`, + ); + } +} diff --git a/frontend/packages/example-registry/scripts/migrate-templates.ts b/frontend/packages/example-registry/scripts/migrate-templates.ts deleted file mode 100644 index 585fb0f86a..0000000000 --- a/frontend/packages/example-registry/scripts/migrate-templates.ts +++ /dev/null @@ -1,225 +0,0 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -// Template metadata from website/src/data/templates/shared.ts -const templateMetadata: Record = { - "ai-agent": { - technologies: ["rivet", "typescript"], - tags: ["ai", "real-time"], - }, - "background-jobs": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "better-auth-external-db": { - technologies: ["rivet", "typescript"], - tags: ["database"], - }, - "bots": { - technologies: ["rivet", "typescript"], - tags: ["ai"], - }, - "chat-room": { - technologies: ["rivet", "react", "typescript"], - tags: ["real-time"], - }, - "cloudflare-workers": { - technologies: ["rivet", "cloudflare-workers", "typescript"], - tags: [], - }, - "cloudflare-workers-hono": { - technologies: ["rivet", "cloudflare-workers", "hono", "typescript"], - tags: [], - }, - "cloudflare-workers-inline-client": { - technologies: ["rivet", "cloudflare-workers", "typescript"], - tags: [], - }, - "counter": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "counter-next-js": { - technologies: ["rivet", "next-js", "react", "typescript"], - tags: ["real-time"], - }, - "counter-serverless": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "crdt": { - technologies: ["rivet", "typescript"], - tags: ["real-time"], - }, - "cursors": { - technologies: ["rivet", "react", "typescript"], - tags: ["real-time"], - }, - "cursors-raw-websocket": { - technologies: ["rivet", "websocket", "typescript"], - tags: ["real-time"], - }, - "database": { - technologies: ["rivet", "typescript"], - tags: ["database"], - }, - "deno": { - technologies: ["rivet", "deno", "typescript"], - tags: [], - }, - "drizzle": { - technologies: ["rivet", "drizzle", "typescript"], - tags: ["database"], - }, - "elysia": { - technologies: ["rivet", "elysia", "bun", "typescript"], - tags: [], - }, - "express": { - technologies: ["rivet", "express", "typescript"], - tags: [], - }, - "game": { - technologies: ["rivet", "react", "typescript"], - tags: ["gaming", "real-time"], - }, - "hono": { - technologies: ["rivet", "hono", "typescript"], - tags: [], - }, - "hono-bun": { - technologies: ["rivet", "hono", "bun", "typescript"], - tags: [], - }, - "hono-react": { - technologies: ["rivet", "hono", "react", "typescript"], - tags: ["real-time"], - }, - "kitchen-sink": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "next-js": { - technologies: ["rivet", "next-js", "react", "typescript"], - tags: [], - }, - "quickstart-actions": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "quickstart-cross-actor-actions": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "quickstart-multi-region": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "quickstart-native-websockets": { - technologies: ["rivet", "websocket", "typescript"], - tags: ["quickstart", "real-time"], - }, - "quickstart-realtime": { - technologies: ["rivet", "typescript"], - tags: ["quickstart", "real-time"], - }, - "quickstart-scheduling": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "quickstart-state": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "rate": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "raw-fetch-handler": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "raw-websocket-handler": { - technologies: ["rivet", "websocket", "typescript"], - tags: ["real-time"], - }, - "raw-websocket-handler-proxy": { - technologies: ["rivet", "websocket", "typescript"], - tags: [], - }, - "react": { - technologies: ["rivet", "react", "typescript"], - tags: [], - }, - "smoke-test": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "starter": { - technologies: ["rivet", "typescript"], - tags: ["quickstart"], - }, - "stream": { - technologies: ["rivet", "typescript"], - tags: ["real-time"], - }, - "sync": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "tenant": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "trpc": { - technologies: ["rivet", "trpc", "typescript"], - tags: [], - }, - "user-generated-actors-freestyle": { - technologies: ["rivet", "typescript"], - tags: [], - }, - "workflows": { - technologies: ["rivet", "typescript"], - tags: [], - }, -}; - -async function main() { - const examplesDir = path.join(__dirname, "../../../../examples"); - - for (const [exampleName, metadata] of Object.entries(templateMetadata)) { - const packageJsonPath = path.join(examplesDir, exampleName, "package.json"); - - try { - // Read existing package.json - const content = await fs.readFile(packageJsonPath, "utf-8"); - const packageJson = JSON.parse(content); - - // Add template metadata - packageJson.template = metadata; - - // Write back with pretty formatting - await fs.writeFile( - packageJsonPath, - JSON.stringify(packageJson, null, "\t") + "\n", - "utf-8", - ); - - console.log(`✅ Updated ${exampleName}/package.json`); - } catch (error) { - console.warn(`⚠️ Could not update ${exampleName}:`, error); - } - } - - console.log("\n✅ Migration complete!"); -} - -main().catch((error) => { - console.error("Migration failed:", error); - process.exit(1); -}); diff --git a/frontend/packages/example-registry/scripts/remove-rivet-tech.ts b/frontend/packages/example-registry/scripts/remove-rivet-tech.ts deleted file mode 100644 index 22fd3f01fa..0000000000 --- a/frontend/packages/example-registry/scripts/remove-rivet-tech.ts +++ /dev/null @@ -1,61 +0,0 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -async function main() { - const examplesDir = path.join(__dirname, "../../../../examples"); - - // Read all example directories - const entries = await fs.readdir(examplesDir, { withFileTypes: true }); - const exampleDirs = entries.filter((entry) => entry.isDirectory()); - - let updatedCount = 0; - - for (const dir of exampleDirs) { - const packageJsonPath = path.join(examplesDir, dir.name, "package.json"); - - try { - // Read package.json - const content = await fs.readFile(packageJsonPath, "utf-8"); - const packageJson = JSON.parse(content); - - // Skip if no template metadata - if (!packageJson.template) { - continue; - } - - // Remove "rivet" from technologies - const originalTechnologies = packageJson.template.technologies; - const filteredTechnologies = originalTechnologies.filter( - (tech: string) => tech !== "rivet", - ); - - // Only update if there was a change - if (filteredTechnologies.length !== originalTechnologies.length) { - packageJson.template.technologies = filteredTechnologies; - - // Write back with pretty formatting - await fs.writeFile( - packageJsonPath, - JSON.stringify(packageJson, null, "\t") + "\n", - "utf-8", - ); - - console.log(`✅ Updated ${dir.name}/package.json`); - updatedCount++; - } - } catch (error) { - console.warn(`⚠️ Could not update ${dir.name}:`, error); - } - } - - console.log(`\n✅ Removed "rivet" from ${updatedCount} package.json files`); -} - -main().catch((error) => { - console.error("Script failed:", error); - process.exit(1); -}); diff --git a/frontend/packages/example-registry/src/_gen.ts b/frontend/packages/example-registry/src/_gen.ts index 0614c5f8ef..cc364b09ed 100644 --- a/frontend/packages/example-registry/src/_gen.ts +++ b/frontend/packages/example-registry/src/_gen.ts @@ -1,4 +1,4 @@ -// This file is auto-generated by scripts/build.ts +// This file is auto-generated by scripts/build/index.ts // Do not edit manually export interface Template { @@ -7,13 +7,15 @@ export interface Template { description: string; technologies: string[]; tags: string[]; + noFrontend: boolean; + priority?: number; } export const templates: Template[] = [ { "name": "ai-agent", - "displayName": "AI Agent Chat for RivetKit", - "description": "Example project demonstrating AI agent integration with [RivetKit](https://rivetkit.org).", + "displayName": "AI Agent Chat", + "description": "Example project demonstrating AI agent integration.", "technologies": [ "rivet", "typescript" @@ -21,12 +23,14 @@ export const templates: Template[] = [ "tags": [ "ai", "real-time" - ] + ], + "noFrontend": false, + "priority": 100 }, { "name": "chat-room", - "displayName": "Chat Room for RivetKit", - "description": "Example project demonstrating real-time messaging and actor state management with [RivetKit](https://rivetkit.org).", + "displayName": "Chat Room", + "description": "Example project demonstrating real-time messaging and actor state management.", "technologies": [ "rivet", "react", @@ -34,375 +38,411 @@ export const templates: Template[] = [ ], "tags": [ "real-time" - ] + ], + "noFrontend": false, + "priority": 200 }, { - "name": "cloudflare-workers", - "displayName": "Cloudflare Workers for RivetKit", - "description": "Example project demonstrating Cloudflare Workers deployment with [RivetKit](https://rivetkit.org).", + "name": "cursors", + "displayName": "Real-time Collaborative Cursors", + "description": "Example project demonstrating real-time cursor tracking and collaborative canvas.", "technologies": [ "rivet", - "cloudflare-workers", + "react", "typescript" ], - "tags": [] + "tags": [ + "real-time" + ], + "noFrontend": false, + "priority": 300 }, { - "name": "cloudflare-workers-hono", - "displayName": "Cloudflare Workers with Hono for RivetKit", - "description": "Example project demonstrating Cloudflare Workers deployment with Hono router using [RivetKit](https://rivetkit.org).", + "name": "ai-and-user-generated-actors-freestyle", + "displayName": "User and AI Generated Actors Freestyle Deployer", + "description": "Shows how to deploy user or AI-generated Rivet Actor code using a sandboxed namespace and Freestyle", "technologies": [ "rivet", - "cloudflare-workers", + "react", "hono", "typescript" ], - "tags": [] + "tags": [ + "ai" + ], + "noFrontend": false, + "priority": 400 }, { - "name": "cloudflare-workers-inline-client", - "displayName": "Cloudflare Workers Inline Client Example", - "description": "Simple example demonstrating accessing Rivet Actors via Cloudflare Workers without exposing a public API. This uses the `createInlineClient` function to connect directly to your Durable Object.", + "name": "actor-actions", + "displayName": "Actor Actions", + "description": "Demonstrates how to define and call actions on Rivet Actors for RPC-style communication between actors and clients.", "technologies": [ "rivet", - "cloudflare-workers", "typescript" ], - "tags": [] + "tags": [ + "quickstart" + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "counter", - "displayName": "Counter for RivetKit", - "description": "Example project demonstrating basic actor state management and RPC calls with [RivetKit](https://rivetkit.org).", + "name": "cross-actor-actions", + "displayName": "Cross-Actor Actions", + "description": "Demonstrates how actors can call actions on other actors for inter-actor communication and coordination.", "technologies": [ "rivet", "typescript" ], "tags": [ "quickstart" - ] + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "counter-next-js", - "displayName": "Counter for RivetKit (Next.js)", - "description": "Example Next.js project demonstrating basic actor state management and real-time updates with [RivetKit](https://rivetkit.org).", + "name": "multi-region", + "displayName": "Multi-Region", + "description": "Demonstrates deploying Rivet Actors across multiple geographic regions for low-latency global access.", "technologies": [ "rivet", - "next-js", - "react", "typescript" ], "tags": [ - "real-time" - ] + "quickstart" + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "counter-serverless", - "displayName": "Counter (Serverless) for RivetKit", - "description": "Example project demonstrating serverless actor deployment with automatic engine configuration using [RivetKit](https://rivetkit.org).", + "name": "raw-fetch-handler", + "displayName": "Raw Fetch Handler Example", + "description": "Example project demonstrating raw HTTP fetch handling with Hono integration.", "technologies": [ "rivet", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": false, + "priority": 1000 }, { - "name": "cursors", - "displayName": "Real-time Collaborative Cursors for RivetKit", - "description": "Example project demonstrating real-time cursor tracking and collaborative canvas with [RivetKit](https://rivetkit.org).", + "name": "raw-websocket-handler", + "displayName": "Raw WebSocket Handler", + "description": "Demonstrates raw WebSocket handling with direct actor connections and real-time chat functionality.", "technologies": [ "rivet", - "react", + "websocket", "typescript" ], "tags": [ "real-time" - ] + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "cursors-raw-websocket", - "displayName": "Real-time Collaborative Cursors for RivetKit", - "description": "Example project demonstrating real-time cursor tracking and collaborative canvas with [RivetKit](https://rivetkit.org).", + "name": "scheduling", + "displayName": "Scheduling", + "description": "Demonstrates how to schedule tasks and execute code at specific times or intervals using Rivet Actors.", "technologies": [ "rivet", - "websocket", "typescript" ], "tags": [ - "real-time" - ] + "quickstart" + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "deno", - "displayName": "Deno Example for RivetKit", - "description": "Example project demonstrating basic actor state management and RPC calls with [RivetKit](https://rivetkit.org) using Deno runtime.", + "name": "state", + "displayName": "State Management", + "description": "Demonstrates persistent state management in Rivet Actors with automatic state saving and restoration.", "technologies": [ "rivet", - "deno", "typescript" ], - "tags": [] + "tags": [ + "quickstart" + ], + "noFrontend": false, + "priority": 1000 }, { - "name": "drizzle", - "displayName": "Hono Integration for RivetKit", - "description": "Example project demonstrating Hono web framework integration with [RivetKit](https://rivetkit.org).", + "name": "chat-room-next-js", + "displayName": "Chat Room (Next.js)", + "description": "Next.js chat room demonstrating real-time messaging with actor state management.", "technologies": [ "rivet", - "drizzle", + "next-js", + "react", "typescript" ], "tags": [ - "database" - ] + "real-time" + ], + "noFrontend": false }, { - "name": "elysia", - "displayName": "Elysia Integration for RivetKit", - "description": "Example project demonstrating Elysia web framework integration with [RivetKit](https://rivetkit.org).", + "name": "cloudflare-workers", + "displayName": "Cloudflare Workers", + "description": "Example project demonstrating Cloudflare Workers deployment.", "technologies": [ "rivet", - "elysia", - "bun", + "cloudflare-workers", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": true }, { - "name": "express", - "displayName": "Express Integration for RivetKit", - "description": "Example project demonstrating Express web framework integration with [RivetKit](https://rivetkit.org).", + "name": "cloudflare-workers-hono", + "displayName": "Cloudflare Workers with Hono", + "description": "Example project demonstrating Cloudflare Workers deployment with Hono router.", "technologies": [ "rivet", - "express", + "cloudflare-workers", + "hono", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": true }, { - "name": "hono", - "displayName": "Hono Integration for RivetKit", - "description": "Example project demonstrating Hono web framework integration with [RivetKit](https://rivetkit.org).", + "name": "cloudflare-workers-inline-client", + "displayName": "Cloudflare Workers Inline Client Example", + "description": "Simple example demonstrating accessing Rivet Actors via Cloudflare Workers without exposing a public API. This uses the `createInlineClient` function to connect directly to your Durable Object.", "technologies": [ "rivet", - "hono", + "cloudflare-workers", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": true }, { - "name": "hono-bun", - "displayName": "Hono + Bun Integration for RivetKit", - "description": "Example project demonstrating Hono web framework with Bun runtime and React frontend integration with [RivetKit](https://rivetkit.org).", + "name": "cursors-raw-websocket", + "displayName": "Real-time Collaborative Cursors (Raw WebSocket)", + "description": "Demonstrates real-time cursor tracking and collaborative canvas using raw WebSocket handlers instead of RivetKit's higher-level WebSocket abstraction.", "technologies": [ "rivet", - "hono", - "bun", + "websocket", "typescript" ], - "tags": [] + "tags": [ + "real-time" + ], + "noFrontend": false }, { - "name": "hono-react", - "displayName": "Hono React Integration for RivetKit", - "description": "Example project demonstrating full-stack Hono backend with React frontend integration with [RivetKit](https://rivetkit.org).", + "name": "custom-serverless", + "displayName": "Custom Serverless", + "description": "Example demonstrating custom serverless actor deployment with automatic engine configuration.", "technologies": [ "rivet", - "hono", - "react", "typescript" ], "tags": [ - "real-time" - ] + "starter" + ], + "noFrontend": true }, { - "name": "kitchen-sink", - "displayName": "Kitchen Sink Example for RivetKit", - "description": "Example project demonstrating all RivetKit features with [RivetKit](https://rivetkit.org).", + "name": "deno", + "displayName": "Deno Example", + "description": "Example project demonstrating basic actor state management and RPC calls using Deno runtime.", "technologies": [ "rivet", + "deno", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": true }, { - "name": "next-js", - "displayName": "or", - "description": "yarn dev", + "name": "drizzle", + "displayName": "Drizzle Integration", + "description": "Demonstrates Drizzle ORM integration with Rivet Actors for type-safe database operations.", "technologies": [ "rivet", - "next-js", - "react", + "drizzle", "typescript" ], - "tags": [] + "tags": [ + "database" + ], + "noFrontend": true }, { - "name": "quickstart-actions", - "displayName": "quickstart-actions", - "description": "Example project for quickstart-actions", + "name": "elysia", + "displayName": "Elysia Integration", + "description": "Example project demonstrating Elysia web framework integration.", "technologies": [ "rivet", + "elysia", + "bun", "typescript" ], - "tags": [ - "quickstart" - ] + "tags": [], + "noFrontend": true }, { - "name": "quickstart-cross-actor-actions", - "displayName": "quickstart-cross-actor-actions", - "description": "Example project for quickstart-cross-actor-actions", + "name": "express", + "displayName": "Express Integration", + "description": "Example project demonstrating Express web framework integration.", "technologies": [ "rivet", + "express", "typescript" ], - "tags": [ - "quickstart" - ] + "tags": [], + "noFrontend": true }, { - "name": "quickstart-multi-region", - "displayName": "quickstart-multi-region", - "description": "Example project for quickstart-multi-region", + "name": "hono", + "displayName": "Hono Integration", + "description": "Example project demonstrating Hono web framework integration.", "technologies": [ "rivet", + "hono", "typescript" ], - "tags": [ - "quickstart" - ] + "tags": [], + "noFrontend": true }, { - "name": "quickstart-native-websockets", - "displayName": "quickstart-native-websockets", - "description": "Example project for quickstart-native-websockets", + "name": "hono-bun", + "displayName": "Hono + Bun", + "description": "Example demonstrating Hono web framework with Bun runtime and React frontend integration.", "technologies": [ "rivet", - "websocket", + "hono", + "bun", "typescript" ], "tags": [ - "quickstart", - "real-time" - ] + "starter" + ], + "noFrontend": true }, { - "name": "quickstart-realtime", - "displayName": "quickstart-realtime", - "description": "Example project for quickstart-realtime", + "name": "hono-react", + "displayName": "Hono + React", + "description": "Example demonstrating full-stack Hono backend with React frontend integration.", "technologies": [ "rivet", + "hono", + "react", "typescript" ], "tags": [ - "quickstart", - "real-time" - ] + "starter" + ], + "noFrontend": false }, { - "name": "quickstart-scheduling", - "displayName": "quickstart-scheduling", - "description": "Example project for quickstart-scheduling", + "name": "kitchen-sink", + "displayName": "Kitchen Sink Example", + "description": "Example project demonstrating all RivetKit features.", "technologies": [ "rivet", "typescript" ], - "tags": [ - "quickstart" - ] + "tags": [], + "noFrontend": false }, { - "name": "quickstart-state", - "displayName": "quickstart-state", - "description": "Example project for quickstart-state", + "name": "native-websockets", + "displayName": "Native WebSockets", + "description": "Demonstrates native WebSocket integration with Rivet Actors for real-time bidirectional communication.", "technologies": [ "rivet", + "websocket", "typescript" ], "tags": [ - "quickstart" - ] + "quickstart", + "real-time" + ], + "noFrontend": false }, { - "name": "raw-fetch-handler", - "displayName": "Raw Fetch Handler Example for RivetKit", - "description": "Example project demonstrating raw HTTP fetch handling with Hono integration in [RivetKit](https://rivetkit.org).", + "name": "next-js", + "displayName": "Next.js", + "description": "Minimal Next.js example demonstrating basic actor state management and real-time updates.", "technologies": [ "rivet", + "next-js", + "react", "typescript" ], - "tags": [] + "tags": [ + "starter" + ], + "noFrontend": false }, { - "name": "raw-websocket-handler", - "displayName": "Raw WebSocket Handler Proxy for RivetKit", - "description": "Example project demonstrating raw WebSocket handling with [RivetKit](https://rivetkit.org).", + "name": "node", + "displayName": "Node.js", + "description": "Minimal Node.js example demonstrating basic actor state management.", "technologies": [ "rivet", - "websocket", "typescript" ], "tags": [ - "real-time" - ] + "starter" + ], + "noFrontend": true }, { "name": "raw-websocket-handler-proxy", - "displayName": "Raw WebSocket Handler Proxy for RivetKit", - "description": "Example project demonstrating raw WebSocket handling with [RivetKit](https://rivetkit.org).", + "displayName": "Raw WebSocket Handler Proxy", + "description": "Demonstrates raw WebSocket handling using a proxy endpoint pattern for routing connections to actors.", "technologies": [ "rivet", "websocket", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": false }, { "name": "react", - "displayName": "Hono React Integration for RivetKit", - "description": "Example project demonstrating full-stack Hono backend with React frontend integration with [RivetKit](https://rivetkit.org).", + "displayName": "React Integration", + "description": "Demonstrates React frontend integration with Rivet Actors.", "technologies": [ "rivet", "react", "typescript" ], - "tags": [] - }, - { - "name": "starter", - "displayName": "Rivet Platform for RivetKit", - "description": "Example project demonstrating Rivet cloud platform deployment with [RivetKit](https://rivetkit.org).", - "technologies": [ - "rivet", - "typescript" - ], - "tags": [ - "quickstart" - ] + "tags": [], + "noFrontend": false }, { "name": "stream", - "displayName": "Stream Processor for RivetKit", - "description": "Example project demonstrating real-time top-K stream processing with [RivetKit](https://rivetkit.org).", + "displayName": "Stream Processor", + "description": "Example project demonstrating real-time top-K stream processing.", "technologies": [ "rivet", "typescript" ], "tags": [ "real-time" - ] + ], + "noFrontend": false }, { "name": "trpc", - "displayName": "tRPC Integration for RivetKit", - "description": "Example project demonstrating tRPC integration with [RivetKit](https://rivetkit.org).", + "displayName": "tRPC Integration", + "description": "Example project demonstrating tRPC integration.", "technologies": [ "rivet", "trpc", "typescript" ], - "tags": [] + "tags": [], + "noFrontend": true } ]; diff --git a/frontend/packages/example-registry/turbo.json b/frontend/packages/example-registry/turbo.json new file mode 100644 index 0000000000..1baf1af036 --- /dev/null +++ b/frontend/packages/example-registry/turbo.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "inputs": [ + "scripts/**", + "src/**", + "../../examples/**/package.json", + "../../examples/**/README.md" + ], + "outputs": ["src/_gen.ts"] + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7abbc8c18..197a7cde2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -240,6 +240,49 @@ importers: specifier: ^5.7.3 version: 5.9.2 + examples/actor-actions: + dependencies: + rivetkit: + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/rivetkit + devDependencies: + '@rivetkit/react': + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/react + '@types/node': + specifier: ^22.13.9 + version: 22.19.1 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + tsx: + specifier: ^3.12.7 + version: 3.14.0 + typescript: + specifier: ^5.5.2 + version: 5.9.3 + vite: + specifier: ^5.0.0 + version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + vitest: + specifier: ^3.1.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + examples/ai-agent: dependencies: '@ai-sdk/openai': @@ -304,8 +347,8 @@ importers: specifier: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@715f221 version: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@715f221 '@rivetkit/engine-api-full': - specifier: ^25.7.2 - version: 25.8.1 + specifier: latest + version: 2.0.25 dotenv: specifier: ^17.2.2 version: 17.2.3 @@ -402,6 +445,37 @@ importers: specifier: ^3.1.1 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@3.1.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + examples/chat-room-next-js: + dependencies: + '@rivetkit/next-js': + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/next-js + next: + specifier: 15.4.5 + version: 15.4.5(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) + react: + specifier: 19.1.0 + version: 19.1.0 + react-dom: + specifier: 19.1.0 + version: 19.1.0(react@19.1.0) + rivetkit: + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/rivetkit + devDependencies: + '@types/node': + specifier: ^20 + version: 20.19.13 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + typescript: + specifier: ^5 + version: 5.9.3 + examples/cloudflare-workers: dependencies: '@rivetkit/cloudflare-workers': @@ -480,75 +554,48 @@ importers: specifier: ^4.22.0 version: 4.44.0(@cloudflare/workers-types@4.20251014.0) - examples/counter: - devDependencies: - '@types/node': - specifier: ^22.13.9 - version: 22.18.1 - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - tsx: - specifier: ^3.12.7 - version: 3.14.0 - typescript: - specifier: ^5.7.3 - version: 5.9.2 - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@3.1.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - - examples/counter-next-js: + examples/cross-actor-actions: dependencies: - '@rivetkit/next-js': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/next-js - next: - specifier: 15.4.5 - version: 15.4.5(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) - react: - specifier: 19.1.0 - version: 19.1.0 - react-dom: - specifier: 19.1.0 - version: 19.1.0(react@19.1.0) rivetkit: specifier: workspace:* version: link:../../rivetkit-typescript/packages/rivetkit devDependencies: + '@rivetkit/react': + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/react '@types/node': - specifier: ^20 - version: 20.19.13 + specifier: ^22.13.9 + version: 22.19.1 '@types/react': specifier: ^19 version: 19.2.2 '@types/react-dom': specifier: ^19 version: 19.2.2(@types/react@19.2.2) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) tsx: specifier: ^3.12.7 version: 3.14.0 typescript: - specifier: ^5 + specifier: ^5.5.2 version: 5.9.3 - - examples/counter-serverless: - devDependencies: - '@types/node': - specifier: ^22.13.9 - version: 22.18.1 - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - tsx: - specifier: ^3.12.7 - version: 3.14.0 - typescript: - specifier: ^5.7.3 - version: 5.9.2 + vite: + specifier: ^5.0.0 + version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) vitest: specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@3.1.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) examples/cursors: dependencies: @@ -648,6 +695,24 @@ importers: specifier: ^3.1.1 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@3.1.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + examples/custom-serverless: + devDependencies: + '@types/node': + specifier: ^22.13.9 + version: 22.19.1 + rivetkit: + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/rivetkit + tsx: + specifier: ^3.12.7 + version: 3.14.0 + typescript: + specifier: ^5.7.3 + version: 5.9.3 + vitest: + specifier: ^3.1.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + examples/deno: dependencies: hono: @@ -694,9 +759,12 @@ importers: '@rivetkit/react': specifier: workspace:* version: link:../../rivetkit-typescript/packages/react + '@sinclair/typebox': + specifier: ^0.34.15 + version: 0.34.41 elysia: specifier: ^1.3.5 - version: 1.4.12(@sinclair/typebox@0.27.8)(exact-mirror@0.2.2(@sinclair/typebox@0.27.8))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.9.2) + version: 1.4.12(@sinclair/typebox@0.34.41)(exact-mirror@0.2.2(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.9.2) react: specifier: ^18.2.0 version: 18.3.1 @@ -896,38 +964,7 @@ importers: specifier: ^5.2.0 version: 5.4.20(@types/node@24.10.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - examples/next-js: - dependencies: - '@rivetkit/next-js': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/next-js - next: - specifier: 15.4.5 - version: 15.4.5(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) - react: - specifier: 19.1.0 - version: 19.1.0 - react-dom: - specifier: 19.1.0 - version: 19.1.0(react@19.1.0) - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - devDependencies: - '@types/node': - specifier: ^20 - version: 20.19.13 - '@types/react': - specifier: ^19 - version: 19.2.2 - '@types/react-dom': - specifier: ^19 - version: 19.2.2(@types/react@19.2.2) - typescript: - specifier: ^5 - version: 5.9.2 - - examples/quickstart-actions: + examples/multi-region: dependencies: rivetkit: specifier: workspace:* @@ -970,93 +1007,7 @@ importers: specifier: ^3.1.1 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - examples/quickstart-cross-actor-actions: - dependencies: - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - devDependencies: - '@rivetkit/react': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/react - '@types/node': - specifier: ^22.13.9 - version: 22.19.1 - '@types/react': - specifier: ^19 - version: 19.2.2 - '@types/react-dom': - specifier: ^19 - version: 19.2.2(@types/react@19.2.2) - '@vitejs/plugin-react': - specifier: ^4.2.0 - version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - tsx: - specifier: ^3.12.7 - version: 3.14.0 - typescript: - specifier: ^5.5.2 - version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - - examples/quickstart-multi-region: - dependencies: - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - devDependencies: - '@rivetkit/react': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/react - '@types/node': - specifier: ^22.13.9 - version: 22.19.1 - '@types/react': - specifier: ^19 - version: 19.2.2 - '@types/react-dom': - specifier: ^19 - version: 19.2.2(@types/react@19.2.2) - '@vitejs/plugin-react': - specifier: ^4.2.0 - version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - tsx: - specifier: ^3.12.7 - version: 3.14.0 - typescript: - specifier: ^5.5.2 - version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - - examples/quickstart-native-websockets: + examples/native-websockets: dependencies: rivetkit: specifier: workspace:* @@ -1105,134 +1056,55 @@ importers: specifier: ^8.16.0 version: 8.18.3 - examples/quickstart-realtime: + examples/next-js: dependencies: - rivetkit: - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/rivetkit - devDependencies: - '@rivetkit/react': + '@rivetkit/next-js': specifier: workspace:* - version: link:../../rivetkit-typescript/packages/react - '@types/node': - specifier: ^22.13.9 - version: 22.19.1 - '@types/react': - specifier: ^19 - version: 19.2.2 - '@types/react-dom': - specifier: ^19 - version: 19.2.2(@types/react@19.2.2) - '@vitejs/plugin-react': - specifier: ^4.2.0 - version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 + version: link:../../rivetkit-typescript/packages/next-js + next: + specifier: 15.4.5 + version: 15.4.5(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) react: - specifier: ^18.2.0 - version: 18.3.1 + specifier: 19.1.0 + version: 19.1.0 react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) - tsx: - specifier: ^3.12.7 - version: 3.14.0 - typescript: - specifier: ^5.5.2 - version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - - examples/quickstart-scheduling: - dependencies: + specifier: 19.1.0 + version: 19.1.0(react@19.1.0) rivetkit: specifier: workspace:* version: link:../../rivetkit-typescript/packages/rivetkit devDependencies: - '@rivetkit/react': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/react '@types/node': - specifier: ^22.13.9 - version: 22.19.1 + specifier: ^20 + version: 20.19.13 '@types/react': specifier: ^19 version: 19.2.2 '@types/react-dom': specifier: ^19 version: 19.2.2(@types/react@19.2.2) - '@vitejs/plugin-react': - specifier: ^4.2.0 - version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) tsx: specifier: ^3.12.7 version: 3.14.0 typescript: - specifier: ^5.5.2 - version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + specifier: ^5 + version: 5.9.2 - examples/quickstart-state: + examples/node: dependencies: rivetkit: specifier: workspace:* version: link:../../rivetkit-typescript/packages/rivetkit devDependencies: - '@rivetkit/react': - specifier: workspace:* - version: link:../../rivetkit-typescript/packages/react '@types/node': specifier: ^22.13.9 version: 22.19.1 - '@types/react': - specifier: ^19 - version: 19.2.2 - '@types/react-dom': - specifier: ^19 - version: 19.2.2(@types/react@19.2.2) - '@vitejs/plugin-react': - specifier: ^4.2.0 - version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 - react: - specifier: ^18.2.0 - version: 18.3.1 - react-dom: - specifier: ^18.2.0 - version: 18.3.1(react@18.3.1) tsx: specifier: ^3.12.7 version: 3.14.0 typescript: specifier: ^5.5.2 version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - vitest: - specifier: ^3.1.1 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) examples/raw-fetch-handler: dependencies: @@ -1427,21 +1299,91 @@ importers: specifier: ^3.1.1 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/ui@3.1.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) - examples/starter: + examples/scheduling: dependencies: rivetkit: specifier: workspace:* version: link:../../rivetkit-typescript/packages/rivetkit devDependencies: + '@rivetkit/react': + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/react '@types/node': specifier: ^22.13.9 - version: 22.18.1 + version: 22.19.1 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) tsx: specifier: ^3.12.7 version: 3.14.0 typescript: specifier: ^5.5.2 - version: 5.9.2 + version: 5.9.3 + vite: + specifier: ^5.0.0 + version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + vitest: + specifier: ^3.1.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + + examples/state: + dependencies: + rivetkit: + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/rivetkit + devDependencies: + '@rivetkit/react': + specifier: workspace:* + version: link:../../rivetkit-typescript/packages/react + '@types/node': + specifier: ^22.13.9 + version: 22.19.1 + '@types/react': + specifier: ^19 + version: 19.2.2 + '@types/react-dom': + specifier: ^19 + version: 19.2.2(@types/react@19.2.2) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.7.0(vite@5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0)) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 + react: + specifier: ^18.2.0 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) + tsx: + specifier: ^3.12.7 + version: 3.14.0 + typescript: + specifier: ^5.5.2 + version: 5.9.3 + vite: + specifier: ^5.0.0 + version: 5.4.20(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) + vitest: + specifier: ^3.1.1 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(less@4.4.1)(lightningcss@1.30.2)(sass@1.93.2)(stylus@0.62.0)(terser@5.44.0) examples/stream: dependencies: @@ -2087,6 +2029,9 @@ importers: '@types/node': specifier: ^22.13.9 version: 22.19.1 + puppeteer: + specifier: ^23.11.1 + version: 23.11.1(typescript@5.9.3) tsx: specifier: ^4.20.6 version: 4.20.6 @@ -2461,12 +2406,12 @@ importers: '@rivet-gg/components': specifier: workspace:* version: link:../frontend/packages/components - '@rivet-gg/example-registry': - specifier: workspace:* - version: link:../frontend/packages/example-registry '@rivet-gg/icons': specifier: workspace:^ version: link:../frontend/packages/icons + '@rivetkit/example-registry': + specifier: workspace:* + version: link:../frontend/packages/example-registry '@shikijs/transformers': specifier: ^3.15.0 version: 3.15.0 @@ -5705,6 +5650,11 @@ packages: '@posthog/core@1.5.3': resolution: {integrity: sha512-1cHCMR2uS/rAdBIFlBPJ4rPYaw1O42VkFy/LwQLtoy2hMQb2DdhCoSHfgA66R9TvcOybZsSANlbuihmGEZUKVQ==} + '@puppeteer/browsers@2.6.1': + resolution: {integrity: sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==} + engines: {node: '>=18'} + hasBin: true + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -6454,8 +6404,8 @@ packages: resolution: {tarball: https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@bf2ebb2} version: 0.0.0 - '@rivetkit/engine-api-full@25.8.1': - resolution: {integrity: sha512-nkQeBUdirq4VYEed1HePCp4zA/BjWg0GoO//MXW+B2ZuDk2FHmADt85VolB8M8y/0Q8Swlx6xQEVbFRJDXDeYQ==} + '@rivetkit/engine-api-full@2.0.25': + resolution: {integrity: sha512-34ibIpDZjTTU6qm3SctdMZGc1PxHC+vGmT26NwR7cuIWT7QNehuiquIB/5YlbgtnkK0JO4GMf9dAp3xHuDFemQ==} '@rivetkit/fast-json-patch@3.1.2': resolution: {integrity: sha512-CtA50xgsSSzICQduF/NDShPRzvucnNvsW/lQO0WgMTT1XAj9Lfae4pm7r3llFwilgG+9iq76Hv1LUqNy72v6yw==} @@ -6894,6 +6844,9 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sinclair/typebox@0.34.41': + resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + '@sindresorhus/is@7.1.0': resolution: {integrity: sha512-7F/yz2IphV39hiS2zB4QYVkivrptHHh0K8qJJd9HhuWSdvf8AN7NpebW3CcDZDBQsUPMoDKWsY2WWgW7bqOcfA==} engines: {node: '>=18'} @@ -7105,6 +7058,9 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@trpc/client@11.6.0': resolution: {integrity: sha512-DyWbYk2hd50BaVrXWVkaUnaSwgAF5g/lfBkXtkF1Aqlk6BtSzGUo3owPkgqQO2I5LwWy1+ra9TsSfBBvIZpTwg==} peerDependencies: @@ -7374,6 +7330,9 @@ packages: '@types/yargs@17.0.35': resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@typescript-eslint/eslint-plugin@8.47.0': resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -8044,6 +8003,10 @@ packages: ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -8095,6 +8058,14 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} + b4a@1.7.3: + resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true + babel-dead-code-elimination@1.0.10: resolution: {integrity: sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==} @@ -8175,6 +8146,44 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} + peerDependencies: + bare-abort-controller: '*' + peerDependenciesMeta: + bare-abort-controller: + optional: true + + bare-fs@4.5.2: + resolution: {integrity: sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==} + engines: {bare: '>=1.16.0'} + peerDependencies: + bare-buffer: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + + bare-os@3.6.2: + resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} + engines: {bare: '>=1.14.0'} + + bare-path@3.0.0: + resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} + + bare-stream@2.7.0: + resolution: {integrity: sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==} + peerDependencies: + bare-buffer: '*' + bare-events: '*' + peerDependenciesMeta: + bare-buffer: + optional: true + bare-events: + optional: true + + bare-url@2.3.2: + resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -8186,6 +8195,10 @@ packages: resolution: {integrity: sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==} hasBin: true + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + bcryptjs@2.4.3: resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} @@ -8257,6 +8270,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -8417,6 +8433,11 @@ packages: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} + chromium-bidi@0.11.0: + resolution: {integrity: sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==} + peerDependencies: + devtools-protocol: '*' + chromium-edge-launcher@0.2.0: resolution: {integrity: sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==} @@ -8640,6 +8661,15 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -8717,6 +8747,10 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -8844,6 +8878,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -8875,6 +8913,9 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + devtools-protocol@0.0.1367902: + resolution: {integrity: sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -9100,6 +9141,10 @@ packages: resolution: {integrity: sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==} engines: {node: '>=8'} + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -9212,6 +9257,11 @@ packages: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-next@16.0.3: resolution: {integrity: sha512-5F6qDjcZldf0Y0ZbqvWvap9xzYUxyDf7/of37aeyhvkrQokj/4bT1JYWZdlWUr283aeVa+s52mPq9ogmGg+5dw==} peerDependencies: @@ -9382,6 +9432,9 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -9536,6 +9589,11 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + fast-copy@3.0.2: resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} @@ -9549,6 +9607,9 @@ packages: resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} + fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} @@ -9612,6 +9673,9 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -9861,6 +9925,10 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} @@ -9879,6 +9947,10 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + getenv@1.0.0: resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==} engines: {node: '>=6'} @@ -10102,6 +10174,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -10207,6 +10283,10 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -10872,6 +10952,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + lucide-react@0.439.0: resolution: {integrity: sha512-PafSWvDTpxdtNEndS2HIHxcNAbd54OaqSYJO90/b63rab2HWYqDbH194j0i82ZFdWOAcf0AHinRykXRRK2PJbw==} peerDependencies: @@ -11306,6 +11390,9 @@ packages: resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -11403,6 +11490,10 @@ packages: nested-error-stacks@2.0.1: resolution: {integrity: sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==} + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + next-router-mock@1.0.4: resolution: {integrity: sha512-EBOd/J2PxgZ9WH732ppfEojZgSTSOkjEz0DgQn+9c/PELKnc9P19PAcmQUi7fSlk3LAKbMGzl5DEOb40x7l8kA==} peerDependencies: @@ -11705,6 +11796,14 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -11803,6 +11902,9 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -12127,6 +12229,10 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -12144,6 +12250,16 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + puppeteer-core@23.11.1: + resolution: {integrity: sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==} + engines: {node: '>=18'} + + puppeteer@23.11.1: + resolution: {integrity: sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==} + engines: {node: '>=18'} + deprecated: < 24.15.0 is no longer supported + hasBin: true + qrcode-terminal@0.11.0: resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==} hasBin: true @@ -12844,6 +12960,10 @@ packages: resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} engines: {node: '>=8.0.0'} + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -12862,6 +12982,14 @@ packages: resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} engines: {node: '>=10.2.0'} + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + solid-js@1.9.9: resolution: {integrity: sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA==} @@ -12962,6 +13090,9 @@ packages: resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} engines: {node: '>= 0.10.0'} + streamx@2.23.0: + resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} + strict-uri-encode@2.0.0: resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} engines: {node: '>=4'} @@ -13165,10 +13296,16 @@ packages: tar-fs@2.1.3: resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} + tar-fs@3.1.1: + resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} + tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} + tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} @@ -13206,6 +13343,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-decoder@1.2.3: + resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -13226,6 +13366,9 @@ packages: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} engines: {node: '>=18'} + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -13464,6 +13607,9 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} + typed-query-selector@2.12.0: + resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} + typedoc@0.28.14: resolution: {integrity: sha512-ftJYPvpVfQvFzpkoSfHLkJybdA/geDJ8BGQt/ZnkkhnBYoYW6lBgPQXu6vqLxO4X75dA55hX8Af847H5KXlEFA==} engines: {node: '>= 18', pnpm: '>= 10'} @@ -13523,6 +13669,9 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} + unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -14281,6 +14430,9 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -14323,6 +14475,9 @@ packages: zod@3.22.3: resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -17519,6 +17674,22 @@ snapshots: dependencies: cross-spawn: 7.0.6 + '@puppeteer/browsers@2.6.1': + dependencies: + debug: 4.4.3 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.5.0 + semver: 7.7.3 + tar-fs: 3.1.1 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + - supports-color + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.3': {} @@ -18482,7 +18653,7 @@ snapshots: transitivePeerDependencies: - encoding - '@rivetkit/engine-api-full@25.8.1': + '@rivetkit/engine-api-full@2.0.25': dependencies: form-data: 4.0.5 js-base64: 3.7.8 @@ -19013,6 +19184,8 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@sinclair/typebox@0.34.41': {} + '@sindresorhus/is@7.1.0': {} '@sindresorhus/merge-streams@4.0.0': {} @@ -19263,6 +19436,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@trpc/client@11.6.0(@trpc/server@11.6.0(typescript@5.9.2))(typescript@5.9.2)': dependencies: '@trpc/server': 11.6.0(typescript@5.9.2) @@ -19561,6 +19736,11 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.19.1 + optional: true + '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -20459,6 +20639,10 @@ snapshots: ast-types-flow@0.0.8: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + ast-types@0.16.1: dependencies: tslib: 2.8.1 @@ -20509,6 +20693,8 @@ snapshots: axobject-query@4.1.0: {} + b4a@1.7.3: {} + babel-dead-code-elimination@1.0.10: dependencies: '@babel/core': 7.28.4 @@ -20659,12 +20845,51 @@ snapshots: balanced-match@1.0.2: {} + bare-events@2.8.2: {} + + bare-fs@4.5.2: + dependencies: + bare-events: 2.8.2 + bare-path: 3.0.0 + bare-stream: 2.7.0(bare-events@2.8.2) + bare-url: 2.3.2 + fast-fifo: 1.3.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-os@3.6.2: + optional: true + + bare-path@3.0.0: + dependencies: + bare-os: 3.6.2 + optional: true + + bare-stream@2.7.0(bare-events@2.8.2): + dependencies: + streamx: 2.23.0 + optionalDependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + optional: true + + bare-url@2.3.2: + dependencies: + bare-path: 3.0.0 + optional: true + base64-js@1.5.1: {} base64id@2.0.0: {} baseline-browser-mapping@2.8.29: {} + basic-ftp@5.0.5: {} + bcryptjs@2.4.3: {} better-opn@3.0.2: @@ -20756,6 +20981,8 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-crc32@0.2.13: {} + buffer-from@1.1.2: {} buffer@5.7.1: @@ -20944,6 +21171,12 @@ snapshots: chrome-trace-event@1.0.4: {} + chromium-bidi@0.11.0(devtools-protocol@0.0.1367902): + dependencies: + devtools-protocol: 0.0.1367902 + mitt: 3.0.1 + zod: 3.23.8 + chromium-edge-launcher@0.2.0: dependencies: '@types/node': 22.19.1 @@ -21179,6 +21412,15 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 + cosmiconfig@9.0.0(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + crelt@1.0.6: {} cross-fetch@4.1.0: @@ -21243,6 +21485,8 @@ snapshots: damerau-levenshtein@1.0.8: {} + data-uri-to-buffer@6.0.2: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -21339,6 +21583,12 @@ snapshots: defu@6.1.4: {} + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + delayed-stream@1.0.0: {} depd@2.0.0: {} @@ -21358,6 +21608,8 @@ snapshots: dependencies: dequal: 2.0.3 + devtools-protocol@0.0.1367902: {} + didyoumean@1.2.2: {} diff-match-patch@1.0.5: {} @@ -21430,11 +21682,11 @@ snapshots: electron-to-chromium@1.5.257: {} - elysia@1.4.12(@sinclair/typebox@0.27.8)(exact-mirror@0.2.2(@sinclair/typebox@0.27.8))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.9.2): + elysia@1.4.12(@sinclair/typebox@0.34.41)(exact-mirror@0.2.2(@sinclair/typebox@0.34.41))(file-type@21.0.0)(openapi-types@12.1.3)(typescript@5.9.2): dependencies: - '@sinclair/typebox': 0.27.8 + '@sinclair/typebox': 0.34.41 cookie: 1.0.2 - exact-mirror: 0.2.2(@sinclair/typebox@0.27.8) + exact-mirror: 0.2.2(@sinclair/typebox@0.34.41) fast-decode-uri-component: 1.0.1 file-type: 21.0.0 openapi-types: 12.1.3 @@ -21498,6 +21750,8 @@ snapshots: env-editor@0.4.2: {} + env-paths@2.2.1: {} + errno@0.1.8: dependencies: prr: 1.0.1 @@ -21812,6 +22066,14 @@ snapshots: escape-string-regexp@5.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-config-next@16.0.3(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 16.0.3 @@ -22072,6 +22334,12 @@ snapshots: eventemitter3@5.0.1: {} + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + events@3.3.0: {} eventsource-parser@1.1.2: {} @@ -22082,9 +22350,9 @@ snapshots: dependencies: eventsource-parser: 3.0.6 - exact-mirror@0.2.2(@sinclair/typebox@0.27.8): + exact-mirror@0.2.2(@sinclair/typebox@0.34.41): optionalDependencies: - '@sinclair/typebox': 0.27.8 + '@sinclair/typebox': 0.34.41 exec-async@2.2.0: {} @@ -22322,6 +22590,16 @@ snapshots: extend@3.0.2: {} + extract-zip@2.0.1: + dependencies: + debug: 4.4.3 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + fast-copy@3.0.2: {} fast-decode-uri-component@1.0.1: {} @@ -22330,6 +22608,8 @@ snapshots: fast-equals@5.2.2: {} + fast-fifo@1.3.2: {} + fast-glob@3.3.1: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -22387,6 +22667,10 @@ snapshots: dependencies: bser: 2.1.1 + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -22674,6 +22958,10 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stream@5.2.0: + dependencies: + pump: 3.0.3 + get-stream@8.0.1: {} get-stream@9.0.1: @@ -22695,6 +22983,14 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-uri@6.0.5: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + getenv@1.0.0: {} getenv@2.0.0: {} @@ -23018,6 +23314,13 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 @@ -23108,6 +23411,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + ip-address@10.1.0: {} + ipaddr.js@1.9.1: {} is-alphabetical@2.0.1: {} @@ -23741,6 +24046,8 @@ snapshots: dependencies: yallist: 4.0.0 + lru-cache@7.18.3: {} + lucide-react@0.439.0(react@19.1.1): dependencies: react: 19.1.1 @@ -24664,6 +24971,8 @@ snapshots: dependencies: minipass: 7.1.2 + mitt@3.0.1: {} + mkdirp-classic@0.5.3: {} mkdirp@1.0.4: {} @@ -24738,6 +25047,8 @@ snapshots: nested-error-stacks@2.0.1: {} + netmask@2.0.2: {} + next-router-mock@1.0.4(next@15.5.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2))(react@19.2.0): dependencies: next: 15.5.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.2) @@ -25104,6 +25415,24 @@ snapshots: p-try@2.2.0: {} + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + package-json-from-dist@1.0.1: {} pako@1.0.11: {} @@ -25194,6 +25523,8 @@ snapshots: pathval@2.0.1: {} + pend@1.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -25475,6 +25806,19 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + proxy-from-env@1.1.0: {} prr@1.0.1: @@ -25489,6 +25833,39 @@ snapshots: punycode@2.3.1: {} + puppeteer-core@23.11.1: + dependencies: + '@puppeteer/browsers': 2.6.1 + chromium-bidi: 0.11.0(devtools-protocol@0.0.1367902) + debug: 4.4.3 + devtools-protocol: 0.0.1367902 + typed-query-selector: 2.12.0 + ws: 8.18.3 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - utf-8-validate + + puppeteer@23.11.1(typescript@5.9.3): + dependencies: + '@puppeteer/browsers': 2.6.1 + chromium-bidi: 0.11.0(devtools-protocol@0.0.1367902) + cosmiconfig: 9.0.0(typescript@5.9.3) + devtools-protocol: 0.0.1367902 + puppeteer-core: 23.11.1 + typed-query-selector: 2.12.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - bufferutil + - react-native-b4a + - supports-color + - typescript + - utf-8-validate + qrcode-terminal@0.11.0: {} qrcode.react@4.2.0(react@19.1.1): @@ -26527,6 +26904,8 @@ snapshots: slugify@1.6.6: {} + smart-buffer@4.2.0: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -26573,6 +26952,19 @@ snapshots: - supports-color - utf-8-validate + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + solid-js@1.9.9: dependencies: csstype: 3.1.3 @@ -26648,6 +27040,15 @@ snapshots: stream-buffers@2.2.0: {} + streamx@2.23.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.3 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + strict-uri-encode@2.0.0: {} string-argv@0.3.2: {} @@ -26944,6 +27345,18 @@ snapshots: pump: 3.0.3 tar-stream: 2.2.0 + tar-fs@3.1.1: + dependencies: + pump: 3.0.3 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 4.5.2 + bare-path: 3.0.0 + transitivePeerDependencies: + - bare-abort-controller + - bare-buffer + - react-native-b4a + tar-stream@2.2.0: dependencies: bl: 4.1.0 @@ -26952,6 +27365,15 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + tar-stream@3.1.7: + dependencies: + b4a: 1.7.3 + fast-fifo: 1.3.2 + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + tar@7.5.2: dependencies: '@isaacs/fs-minipass': 4.0.1 @@ -27003,6 +27425,12 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-decoder@1.2.3: + dependencies: + b4a: 1.7.3 + transitivePeerDependencies: + - react-native-b4a + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -27021,6 +27449,8 @@ snapshots: throttleit@2.1.0: {} + through@2.3.8: {} + tiny-invariant@1.3.3: {} tiny-warning@1.0.3: {} @@ -27362,6 +27792,8 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typed-query-selector@2.12.0: {} + typedoc@0.28.14(typescript@5.9.3): dependencies: '@gerrit0/mini-shiki': 3.15.0 @@ -27436,6 +27868,11 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 + unbzip2-stream@1.4.3: + dependencies: + buffer: 5.7.1 + through: 2.3.8 + undici-types@5.26.5: {} undici-types@6.21.0: {} @@ -28682,6 +29119,11 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + yocto-queue@0.1.0: {} yocto-queue@1.2.1: {} @@ -28723,6 +29165,8 @@ snapshots: zod@3.22.3: {} + zod@3.23.8: {} + zod@3.25.76: {} zustand@5.0.3(@types/react@19.2.2)(react@19.1.1)(use-sync-external-store@1.6.0(react@19.1.1)): diff --git a/website/package.json b/website/package.json index 3ca745be3a..d989a19e9f 100644 --- a/website/package.json +++ b/website/package.json @@ -9,7 +9,7 @@ "format": "prettier --write .", "create-article": "vite-node scripts/generateArticle.js", "generate-favicon": "npx cli-real-favicon generate scripts/faviconConfig.json faviconData.json public/icons", - "prebuild": "pnpm --filter @rivet-gg/example-registry build && pnpm gen:navigation && pnpm gen:markdown", + "prebuild": "pnpm gen:navigation && pnpm gen:markdown", "gen:navigation": "tsx scripts/generateNavigation.ts", "gen:examples": "node scripts/generateExamples.mjs", "gen:markdown": "tsx scripts/generateMarkdownAndLlms.ts", @@ -34,7 +34,7 @@ "@rivet-gg/api": "25.5.3", "@rivet-gg/cloud": "https://pkg.pr.new/rivet-dev/cloud/@rivet-gg/cloud@bf2ebb2", "@rivet-gg/components": "workspace:*", - "@rivet-gg/example-registry": "workspace:*", + "@rivetkit/example-registry": "workspace:*", "@rivet-gg/icons": "workspace:^", "@shikijs/transformers": "^3.15.0", "@sindresorhus/slugify": "^3.0.0", diff --git a/website/public/examples/actor-actions/image.png b/website/public/examples/actor-actions/image.png new file mode 100644 index 0000000000..3cbf6d83a4 Binary files /dev/null and b/website/public/examples/actor-actions/image.png differ diff --git a/website/public/examples/ai-agent/image.png b/website/public/examples/ai-agent/image.png new file mode 100644 index 0000000000..857930f231 Binary files /dev/null and b/website/public/examples/ai-agent/image.png differ diff --git a/website/public/examples/ai-and-user-generated-actors-freestyle/image.png b/website/public/examples/ai-and-user-generated-actors-freestyle/image.png new file mode 100644 index 0000000000..34a71d8d21 Binary files /dev/null and b/website/public/examples/ai-and-user-generated-actors-freestyle/image.png differ diff --git a/website/public/examples/chat-room-next-js/image.png b/website/public/examples/chat-room-next-js/image.png new file mode 100644 index 0000000000..e30a5abc16 Binary files /dev/null and b/website/public/examples/chat-room-next-js/image.png differ diff --git a/website/public/examples/chat-room/image.png b/website/public/examples/chat-room/image.png new file mode 100644 index 0000000000..d40b329557 Binary files /dev/null and b/website/public/examples/chat-room/image.png differ diff --git a/website/public/examples/cross-actor-actions/image.png b/website/public/examples/cross-actor-actions/image.png new file mode 100644 index 0000000000..e9e29fe9ea Binary files /dev/null and b/website/public/examples/cross-actor-actions/image.png differ diff --git a/website/public/examples/cursors-raw-websocket/image.png b/website/public/examples/cursors-raw-websocket/image.png new file mode 100644 index 0000000000..b47e7277ca Binary files /dev/null and b/website/public/examples/cursors-raw-websocket/image.png differ diff --git a/website/public/examples/cursors/image.png b/website/public/examples/cursors/image.png new file mode 100644 index 0000000000..f47d1ce427 Binary files /dev/null and b/website/public/examples/cursors/image.png differ diff --git a/website/public/examples/hono-react/image.png b/website/public/examples/hono-react/image.png new file mode 100644 index 0000000000..7e8b300641 Binary files /dev/null and b/website/public/examples/hono-react/image.png differ diff --git a/website/public/examples/kitchen-sink/image.png b/website/public/examples/kitchen-sink/image.png new file mode 100644 index 0000000000..34a71d8d21 Binary files /dev/null and b/website/public/examples/kitchen-sink/image.png differ diff --git a/website/public/examples/multi-region/image.png b/website/public/examples/multi-region/image.png new file mode 100644 index 0000000000..93dba7f667 Binary files /dev/null and b/website/public/examples/multi-region/image.png differ diff --git a/website/public/examples/native-websockets/image.png b/website/public/examples/native-websockets/image.png new file mode 100644 index 0000000000..d7a92ca2ec Binary files /dev/null and b/website/public/examples/native-websockets/image.png differ diff --git a/website/public/examples/next-js/image.png b/website/public/examples/next-js/image.png new file mode 100644 index 0000000000..42d5e5886b Binary files /dev/null and b/website/public/examples/next-js/image.png differ diff --git a/website/public/examples/raw-fetch-handler/image.png b/website/public/examples/raw-fetch-handler/image.png new file mode 100644 index 0000000000..d40b329557 Binary files /dev/null and b/website/public/examples/raw-fetch-handler/image.png differ diff --git a/website/public/examples/raw-websocket-handler-proxy/image.png b/website/public/examples/raw-websocket-handler-proxy/image.png new file mode 100644 index 0000000000..65f0d4517b Binary files /dev/null and b/website/public/examples/raw-websocket-handler-proxy/image.png differ diff --git a/website/public/examples/raw-websocket-handler/image.png b/website/public/examples/raw-websocket-handler/image.png new file mode 100644 index 0000000000..65f0d4517b Binary files /dev/null and b/website/public/examples/raw-websocket-handler/image.png differ diff --git a/website/public/examples/react/image.png b/website/public/examples/react/image.png new file mode 100644 index 0000000000..65f0d4517b Binary files /dev/null and b/website/public/examples/react/image.png differ diff --git a/website/public/examples/scheduling/image.png b/website/public/examples/scheduling/image.png new file mode 100644 index 0000000000..24e012a7b6 Binary files /dev/null and b/website/public/examples/scheduling/image.png differ diff --git a/website/public/examples/state/image.png b/website/public/examples/state/image.png new file mode 100644 index 0000000000..35400fd30d Binary files /dev/null and b/website/public/examples/state/image.png differ diff --git a/website/public/examples/stream/image.png b/website/public/examples/stream/image.png new file mode 100644 index 0000000000..16af067ef3 Binary files /dev/null and b/website/public/examples/stream/image.png differ diff --git a/website/src/app/(v2)/(marketing)/templates/TemplatesPageClient.tsx b/website/src/app/(v2)/(marketing)/templates/TemplatesPageClient.tsx index 22e884cde9..a61fad4206 100644 --- a/website/src/app/(v2)/(marketing)/templates/TemplatesPageClient.tsx +++ b/website/src/app/(v2)/(marketing)/templates/TemplatesPageClient.tsx @@ -84,7 +84,7 @@ export default function TemplatesPageClient() { }; return ( -
+
@@ -113,7 +113,7 @@ export default function TemplatesPageClient() { type="text" value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} - className="block w-full rounded-lg border border-white/20 bg-white/5 pl-10 pr-3 py-3 text-white placeholder:text-zinc-500 focus:border-[#FF4500] focus:outline-none focus:ring-1 focus:ring-[#FF4500] text-base" + className="block w-full rounded-lg border border-white/20 bg-white/5 pl-10 pr-3 py-3 text-white placeholder:text-zinc-500 focus:border-white/50 focus:outline-none focus:ring-1 focus:ring-white/50 text-base" placeholder="Search templates..." />
diff --git a/website/src/app/(v2)/(marketing)/templates/[slug]/TemplateDetailClient.tsx b/website/src/app/(v2)/(marketing)/templates/[slug]/TemplateDetailClient.tsx index e0d09c20e5..529b800a87 100644 --- a/website/src/app/(v2)/(marketing)/templates/[slug]/TemplateDetailClient.tsx +++ b/website/src/app/(v2)/(marketing)/templates/[slug]/TemplateDetailClient.tsx @@ -4,8 +4,11 @@ import type { Template } from "@/data/templates/shared"; import { templates, TECHNOLOGIES, TAGS } from "@/data/templates/shared"; import { Markdown } from "@/components/Markdown"; import { TemplateCard } from "../components/TemplateCard"; -import { Icon, faGithub } from "@rivet-gg/icons"; +import { Code } from "@/components/v2/Code"; +import { Icon, faGithub, faVercel, faRailway } from "@rivet-gg/icons"; import Link from "next/link"; +import Image from "next/image"; +import { CodeBlock } from "@/components/CodeBlock"; interface TemplateDetailClientProps { template: Template; @@ -33,39 +36,131 @@ export default function TemplateDetailClient({ ? relatedTemplates : templates.filter((t) => t.name !== template.name).slice(0, 3); - const githubUrl = `https://github.com/rivet-dev/rivetkit/tree/main/examples/${template.name}`; + const githubUrl = `https://github.com/rivet-dev/rivet/tree/main/examples/${template.name}`; + + // Strip auto-generated sections from README since they're displayed in the UI + const cleanedReadmeContent = readmeContent + .replace(/^#\s+.+$/m, '') // Remove first heading + .replace(/^\n+/, '') // Remove leading newlines + .replace(/^.+?(?=\n\n|\n#)/s, '') // Remove first paragraph + .replace(/##\s+Getting Started[\s\S]*?(?=\n##|$)/m, '') // Remove Getting Started section + .replace(/##\s+License[\s\S]*$/m, '') // Remove License section + .trim(); + + // Strip markdown links from description + const description = template.description.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); + + // Construct Vercel deploy URL with demo card parameters + const vercelDeployUrl = new URL('https://vercel.com/new/clone'); + vercelDeployUrl.searchParams.set('repository-url', `https://github.com/rivet-dev/rivet/tree/main/examples/${template.name}`); + vercelDeployUrl.searchParams.set('project-name', template.displayName); + vercelDeployUrl.searchParams.set('demo-title', template.displayName); + vercelDeployUrl.searchParams.set('demo-description', description); + vercelDeployUrl.searchParams.set('demo-image', `https://www.rivet.dev/examples/${template.name}/image.png`); + vercelDeployUrl.searchParams.set('demo-url', `https://www.rivet.dev/templates/${template.name}`); return ( -
+
{/* Header with Image */} -
-
- {/* Placeholder Image */} -
- - - -
+
+
+ {!template.noFrontend ? ( +
+ {/* Screenshot on top */} +
+ + {/* Linear gradient overlay - darker on bottom */} +
- {/* Title and Description */} -
-

- {template.displayName} -

-

- {template.description} -

-
+
+ {/* Top Shine Highlight */} +
+ {/* Window Bar */} +
+
+
+
+
+
+
+ {/* Content Area - Screenshot */} +
+ {template.displayName} +
+
+
+ + {/* Text content overlapping bottom */} +
+
+

+ {template.displayName} +

+

+ {description} +

+
+ + + Deploy to Vercel + + + + Deploy to Railway + + + + View on GitHub + +
+
+
+
+ ) : ( +
+

+ {template.displayName} +

+

+ {description} +

+
+ )}
@@ -75,31 +170,35 @@ export default function TemplateDetailClient({ {/* Left Column - README Content */}
- {readmeContent} + {cleanedReadmeContent}
{/* Right Column - Sidebar */}