omg apps
omg.dev v1.0.0
Build and share apps by link
Save this plugin to Following and return to review observed changes. Follow up to 10 plugins free.
Description
From the marketplace listing
Describe an app or a game and get a live link you can share. Every app has a database, sign-in and live updates between everyone who opens it, so votes, boards, chats and two-player games work from the first version. Apps are hosted at your-app.omgs.app.
Language: English · Automatically detected from descriptions.
Competitor profile
From the developer’s listing and package; capabilities are not independently tested. Package observed Nov 3, 2026.
Declared capabilities
- Build and publish web apps and games
- Shared data and live updates between users
- Sign-in for private data
Declared limitations
- General coding question
- Native app store build
- Unrelated task
Review scenarios; not an exhaustive list.
Cost & access
This plugin does not sell products or process payments.
Terms may have changed since this observation.
Starter prompt
Make a team vote app that everyone with the link can use, with live counts
Screenshots
From the developer.
Keywords
Matches for “apps”
Exact text from the indicated source. A mention alone does not establish support for your task.
Plugin name
omg apps
Package name
omg-apps
Publisher subtitle
Build and share apps by link
Publisher capabilities · listing
Build and publish web apps and games Shared data and live updates between users Sign-in for private data Share an app by link
Publisher keywords · listing
apps games multiplayer database deploy hosting
Publisher description
Build and publish full-stack apps and games from chat, with a database, sign-in and live updates between users.
Publisher full description
Describe an app or a game and get a live link you can share. Every app has a database, sign-in and live updates between everyone who opens it, so votes, boards, chats and two-player games work from the first version. Apps are hosted at your-app.omgs.app.
Files & skills
File archives
Skill instructions
build-omg-app9.68 KB
---
name: build-omg-app
description: Build and publish a full-stack web app or game with omg, with a database, sign-in and live updates between users. Use when the person asks for an app, a game, a tool, a vote, a board or anything they want to share by link.
---
<!-- Generated by apps/mcp/scripts/build-plugin.ts from GUIDE in apps/mcp/src/apps.ts. Do not edit. -->
This server builds and publishes web apps for the person you are talking to. A published app gets its own address at https://<slug>.omgs.app with a database, sign-in, live updates between users, AI and media generation, and no setup.
How to build one:
1. Write the app's files. Every deploy starts from the omg starter: Vite, React 19, TypeScript, Tailwind v4, shadcn/ui components in src/components/ui/, TanStack file routes in src/routes/, and the @omg-dev/* packages already installed. src/App.tsx is the home screen. Send only the files you write or change from the starter.
2. Call omg_deploy_app with those files. It returns a slug, the app address, and a management link for the person.
3. Call omg_app_status with the slug until the status is ready or failed. If it failed, read buildError and buildLogTail, fix the files, and deploy again.
4. When it is ready, give the person the app address and the management link.
Data and multiplayer: define collections in schema.ts at the project root with defineSchema, collection and fields from @omg-dev/schema. Read and write them in React with useQuery from @omg-dev/sdk: const { data, create, update, remove } = useQuery<T>({ api: "/api/<collection>", collection: "<collection>" }). Every connected browser sees each change at once.
A collection is private by default: each signed-in user sees only their own rows, and a visitor who is not signed in gets an error. Choose one for each collection:
- Data that every visitor shares, such as votes, a chat, a leaderboard or a game state between players: add .scoped("global"), for example collection({ fields: { ... } }).scoped("global"). Visitors do not need to sign in.
- Data that belongs to one person: keep the default, and wrap the app in <VibesAuthProvider><VibesAuthGuard>...</VibesAuthGuard></VibesAuthProvider> from @omg-dev/sdk so visitors sign in first. useUser() returns the signed-in user.
- Data that everyone reads but only its author may change or delete, such as a guestbook, comments or posts: use .scoped("global"), and add functions/<collection>.ts to guard the writes on the server. Hiding a button is not protection, because anyone can call the API. Wrap the app in <VibesAuthProvider> without the guard, so visitors can read. When a signed-out visitor writes, the server answers 401 and the provider opens sign-in by itself. The guestbook example below shows the full pattern.
Custom server routes go in functions/<name>.ts and use named exports. A default export creates no route.
- export async function POST(req: Request) { ... } is served at /api/<name>. GET, PUT, PATCH and DELETE work the same way, and receive the raw Request.
- When <name> is a collection, export async function create(body), update(id, body) or remove(id) replaces that collection's automatic POST, PATCH or DELETE route.
- Import { ctx, db, VibesHttpError } from "@omg-dev/server". ctx.userId is the signed-in user, or null. db.get(collection, id), db.insert(collection, data) and db.delete(collection, id) read and write rows, and every open browser still gets the change live. throw new VibesHttpError(403, "message") refuses a request.
Rules:
- Every deploy replaces the app's source with the starter plus the files you send. When you change an existing app, send all of its files again, and pass the projectId from the first deploy.
- Do not send package.json, node_modules, dist, .vibes, .git or .env files. Use only packages the starter already has.
- Use the semantic color classes (bg-background, bg-primary, text-muted-foreground). The default Tailwind palette is removed, so a class like bg-indigo-600 has no effect.
- Set the page title, which link previews show. Send index.html with your app's name in <title>:
<!doctype html><html lang="en"><head><meta charset="UTF-8" /><meta name="color-scheme" content="light dark" /><link rel="icon" type="image/svg+xml" href="/favicon.svg" /><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover" /><title>App name</title></head><body><div id="root"></div><script type="module" src="/src/main.tsx"></script></body></html>
- Keep the first version small, usually schema.ts and src/App.tsx. The person waits while you write. Improve it after they see it working.
- A new app opens only for people signed in to omg. Call omg_app_visibility with public when the person wants to share it with anyone who has the link.
Example: a vote board that everyone with the link shares, with live counts. Two files.
schema.ts
```ts
import { defineSchema, collection, fields } from "@omg-dev/schema"
export default defineSchema({
collections: {
options: collection({ fields: { label: fields.string() } }).scoped("global"),
// One row per vote. Counting rows never loses a vote when two people vote at once.
votes: collection({ fields: { optionId: fields.string(), voter: fields.string() } }).scoped("global"),
},
})
```
src/App.tsx
```tsx
import { useState } from "react"
import { useQuery } from "@omg-dev/sdk"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
type Option = { id: string; label: string }
type Vote = { id: string; optionId: string; voter: string }
function voterId() {
let id = localStorage.getItem("voter")
if (!id) { id = crypto.randomUUID(); localStorage.setItem("voter", id) }
return id
}
export default function App() {
const options = useQuery<Option>({ api: "/api/options", collection: "options" })
const votes = useQuery<Vote>({ api: "/api/votes", collection: "votes" })
const [label, setLabel] = useState("")
const me = voterId()
return (
<main className="mx-auto max-w-md space-y-4 p-6">
<form className="flex gap-2" onSubmit={(e) => { e.preventDefault(); if (label.trim()) options.create({ label: label.trim() }); setLabel("") }}>
<Input value={label} onChange={(e) => setLabel(e.target.value)} placeholder="Add an option" />
<Button type="submit">Add</Button>
</form>
{options.data.map((o) => {
const count = votes.data.filter((v) => v.optionId === o.id).length
const mine = votes.data.find((v) => v.optionId === o.id && v.voter === me)
return (
<div key={o.id} className="flex items-center justify-between rounded-lg border border-border p-3">
<span>{o.label}</span>
<Button variant={mine ? "secondary" : "default"} onClick={() => (mine ? votes.remove(mine.id) : votes.create({ optionId: o.id, voter: me }))}>
{count}
</Button>
</div>
)
})}
</main>
)
}
```
Example: a guestbook. Everyone reads every message, only signed-in people post, and only the author can delete a message. Three files.
schema.ts
```ts
import { defineSchema, collection, fields } from "@omg-dev/schema"
export default defineSchema({
collections: {
// Everyone reads every message. functions/messages.ts guards writes.
messages: collection({ fields: { text: fields.string(), author: fields.string(), authorName: fields.string() } }).scoped("global"),
},
})
```
functions/messages.ts
```ts
import { ctx, db, VibesHttpError } from "@omg-dev/server"
// These replace the automatic POST, PATCH and DELETE routes for messages.
export async function create(body: { text?: string }) {
if (!ctx.userId) throw new VibesHttpError(401, "Sign in to post")
const text = String(body?.text ?? "").trim().slice(0, 280)
if (!text) throw new VibesHttpError(400, "Write a message")
return db.insert("messages", { text, author: ctx.userId, authorName: ctx.userName ?? ctx.userEmail ?? "" })
}
export async function update() {
throw new VibesHttpError(403, "Messages cannot be edited")
}
export async function remove(id: string) {
const row = await db.get("messages", id)
if (!row) throw new VibesHttpError(404, "Not found")
if (row.author !== ctx.userId) throw new VibesHttpError(403, "Only the author can delete this")
await db.delete("messages", id)
return { ok: true }
}
```
src/App.tsx
```tsx
import { useState } from "react"
import { useQuery, useUser, VibesAuthProvider } from "@omg-dev/sdk"
import { Button } from "@/components/ui/button"
type Message = { id: string; text: string; author: string; authorName: string; created_at: string }
function Guestbook() {
const user = useUser()
const messages = useQuery<Message>({ api: "/api/messages", collection: "messages" })
const [text, setText] = useState("")
return (
<main className="mx-auto max-w-md space-y-4 p-6">
<h1 className="text-2xl font-semibold">Guestbook</h1>
<form className="flex gap-2" onSubmit={async (e) => { e.preventDefault(); if (!text.trim()) return; await messages.create({ text }); setText("") }}>
<input className="flex-1 rounded-md border border-border bg-background px-3 py-2" value={text} onChange={(e) => setText(e.target.value)} placeholder={user ? "Leave a message" : "Sign in to leave a message"} />
<Button type="submit">Post</Button>
</form>
{messages.data.map((m) => (
<div key={m.id} className="flex items-start justify-between gap-2 rounded-lg border border-border p-3">
<div><p>{m.text}</p><p className="text-sm text-muted-foreground">{m.authorName}</p></div>
{user?.id === m.author && <Button variant="ghost" onClick={() => messages.remove(m.id)}>Delete</Button>}
</div>
))}
</main>
)
}
export default function App() {
return <VibesAuthProvider><Guestbook /></VibesAuthProvider>
}
```
Release notes
First release: build and publish full-stack web apps and games from chat, with a database, sign-in, live updates and an in-chat app card.
Declared in the saved package. Remote tools may change independently.
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package license
- Proprietary
- Package author
- omg.dev
- Keywords
- See keywords
- Commerce declaration
- Does not support commerceThis does not establish whether access is free or paid.
- Review scenarios
- 5 positive · 3 negativeScenario counts, not test results.
Declared capabilities
- Build and publish web apps and games
- Shared data and live updates between users
- Sign-in for private data
- Share an app by link
Package observed Nov 3, 2026.
Technical details
- First seen
- Oct 28, 2026 · 12:00 UTC
- Last seen
- Nov 3, 2026 · 18:00 UTC
- Collection status
- Collected
plugin_asdk_app_6ae0501df1c48191b1f2d6abe2a519a2
Download plugin data (JSON)