# Real-time
URL: /docs/features/real-time
Build real-time collaborative features with pluv.io.
## Real-time collaboration
[pluv.io](https://pluv.io) is a real-time library that allows you to build real-time collaborative features with ease. It is a type-safe API, and comes with a variety of features out-of-the-box, such as:
* Room authorization
* Real-time data syncs [powered-by CRDTs](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
* Presence
```tsx title="page.tsx"
"use client";
import { event, useBroadcast, useStorage } from "@/lib/react-pluv";
import { yjs } from "@pluv/crdt-yjs";
export default function Page() {
const broadcast = useBroadcast();
const [groceries, yGroceries] = useStorage("groceries");
event.receiveMessage.useEvent(({ data }) => {
console.log(data.message);
});
const sendMessage = (message: string) => {
broadcast.sendMessage({ message });
};
const addGrocery = (grocery: string) => {
yGroceries.push([grocery]);
};
return (
{/* ... */}
{groceries.map((grocery) => (
- {grocery}
))}
{/* ... */}
)
}
```
## Costs
When using the [Cloudflare Monorepo](/docs/picking-a-template/cloudflare-monorepo) template, pluv.io will run on your own [Durable Objects](https://www.cloudflare.com/developer-platform/products/durable-objects/) instances, which are free to use with extremely generous free tier limits.
When using the [Vercel Monorepo](/docs/picking-a-template/vercel-monorepo) template, pluv.io will run on [pluv.io's](https://pluv.io) servers, which have much more limited free tier limits, then cost $29/month.
## Setup
Setting up pluv.io is relatively simple, but depends on the template you are using.
### Cloudflare Monorepo
1. In the `realtime` app, add an environment variable for `PLUV_AUTH_SECRET` to your `.dev.vars` file.
* This secret will be used to generate securely-signed JWT tokens for your users.
```txt title="/apps/realtime/.dev.vars"
PLUV_AUTH_SECRET="your-secret-key"
```
2. In the `web` app, add an environment variable for `NEXT_PUBLIC_REALTIME_ORIGIN_URL` to your `.env` file.
* This should be the origin URL of your realtime app. For example, if you deployed your realtime app to `https://realtime.your-app.com`, you would add the following environment variable:
```txt title="/apps/web/.env"
NEXT_PUBLIC_REALTIME_ORIGIN_URL="https://realtime.your-app.com"
```
### Vercel Monorepo
1. Create an account on [pluv.io](https://pluv.io) and create a new project.
2. Go to the API Keys page and create a new API key. You can find this page by clicking on the "API Keys" link in the left sidebar.
3. Create an API secret key, and store both the "Publishable Key" and "Secret Key" values to your `.env` file.
```txt title="/apps/web/.env"
NEXT_PUBLIC_PLUV_PUBLISHABLE_KEY="your-publishable-key-here"
PLUV_SECRET_KEY="your-secret-key"
```
## Removal
You may not need to add real-time collaboration to your app. [ship.pluv.io](https://ship.pluv.io) has been built so that if you don't need it, removal of the real-time features is as simple as deleting some API routes and removing a React provider.
To remove pluv.io from the app, perform the following steps:
1. Disconnect the `rooms` route from your app's API routes.
```ts title="/apps/web/src/app/api/[[...route]]/route.ts"
const app = new Hono<{ Bindings: CloudflareEnv }>()
.basePath("/api")
.use(cors)
// ...
// Remove the `/rooms` route below
.route("/rooms", router.rooms);
```
2. Remove the `PluvRoomProvider` from your project page's layout, located in `/apps/web/src/app/(app)/[teamSlug]/[projectSlug]layout.tsx`.
```tsx title="/apps/web/src/app/(app)/[teamSlug]/[projectSlug]layout.tsx"
// ...
const Layout: FC = ({ children }) => {
return (
// Remove the `PluvRoomProvider` below
// ...
{children}
// ...
);
};
```
Then, you can optionally clean-up the `pluv.io` files in the codebase by deleting the following files:
1. `/apps/web/src/server/router/rooms/router.ts`
2. `/apps/web/src/lib/react-pluv.ts`
3. `/apps/realtime`
* If you are using the [Cloudflare Monorepo](/docs/picking-a-template/cloudflare-monorepo) template, you can delete this directory, as you will not be using it.