stack/examples/convex/app/page.tsx
BilalG1 609579abab
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
feat(hexclave): PR 3 — native @hexclave/* source rename + delete dual-publish wiring (#1482)
2026-05-29 15:21:59 -07:00

167 lines
5.3 KiB
TypeScript

"use client";
import { UserButton, useUser } from "@hexclave/next";
import { useMutation, useQuery } from "convex/react";
import Link from "next/link";
import { api } from "../convex/_generated/api";
import { getUserInfoConvexClient, getUserInfoConvexHttpClient } from "./user-info";
export default function Home() {
const user = useUser();
return (
<>
<header className="sticky top-0 z-10 bg-background p-4 border-b-2 border-slate-200 dark:border-slate-800 flex flex-row justify-between items-center">
Convex + Next.js
<UserButton />
</header>
<main className="p-8 flex flex-col gap-16">
<h1 className="text-4xl font-bold text-center">Convex + Next.js</h1>
<p className="text-center">User (client): {user ? user?.primaryEmail ?? "null" : "Not logged in"}</p>
<Content />
</main>
</>
);
}
function Content() {
const { viewer, numbers } =
useQuery(api.myFunctions.listNumbers, {
count: 10,
}) ?? {};
const addNumber = useMutation(api.myFunctions.addNumber);
const getUserInfo = useQuery(api.myFunctions.getUserInfo, {});
if (viewer === undefined || numbers === undefined) {
return (
<div className="mx-auto">
<p>loading... (consider a loading skeleton)</p>
</div>
);
}
return (
<div className="flex flex-col gap-8 max-w-lg mx-auto">
<p>Welcome {viewer ?? "Anonymous"}!</p>
<div className="flex flex-col gap-2">
<button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => {
alert(getUserInfo);
}}>
View user info
</button>
<button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => {
getUserInfoConvexHttpClient().then(userInfo => {
alert(userInfo);
});
}}>
View user info (http client)
</button>
<button className="bg-foreground text-background text-sm px-4 py-2 rounded-md" onClick={() => {
getUserInfoConvexClient().then(userInfo => {
alert(userInfo);
});
}}>
View user info (js client)
</button>
</div>
<p>
Click the button below and open this page in another window - this data
is persisted in the Convex cloud database!
</p>
<p>
<button
className="bg-foreground text-background text-sm px-4 py-2 rounded-md"
onClick={() => {
void addNumber({ value: Math.floor(Math.random() * 10) });
}}
>
Add a random number
</button>
</p>
<p>
Numbers:{" "}
{numbers?.length === 0
? "Click the button!"
: numbers?.join(", ") ?? "..."}
</p>
<p>
Edit{" "}
<code className="text-sm font-bold font-mono bg-slate-200 dark:bg-slate-800 px-1 py-0.5 rounded-md">
convex/myFunctions.ts
</code>{" "}
to change your backend
</p>
<p>
Edit{" "}
<code className="text-sm font-bold font-mono bg-slate-200 dark:bg-slate-800 px-1 py-0.5 rounded-md">
app/page.tsx
</code>{" "}
to change your frontend
</p>
<p>
See the{" "}
<Link href="/server" className="underline hover:no-underline">
/server route
</Link>{" "}
for an example of loading data in a server component
</p>
<p>
See the{" "}
<Link href="/action" className="underline hover:no-underline">
/action route
</Link>{" "}
for an example of using a convex action to update user data in stack auth
</p>
<div className="flex flex-col">
<p className="text-lg font-bold">Useful resources:</p>
<div className="flex gap-2">
<div className="flex flex-col gap-2 w-1/2">
<ResourceCard
title="Convex docs"
description="Read comprehensive documentation for all Convex features."
href="https://docs.convex.dev/home"
/>
<ResourceCard
title="Stack articles"
description="Learn about best practices, use cases, and more from a growing
collection of articles, videos, and walkthroughs."
href="https://www.typescriptlang.org/docs/handbook/2/basic-types.html"
/>
</div>
<div className="flex flex-col gap-2 w-1/2">
<ResourceCard
title="Templates"
description="Browse our collection of templates to get started quickly."
href="https://www.convex.dev/templates"
/>
<ResourceCard
title="Discord"
description="Join our developer community to ask questions, trade tips & tricks,
and show off your projects."
href="https://www.convex.dev/community"
/>
</div>
</div>
</div>
</div>
);
}
function ResourceCard({
title,
description,
href,
}: {
title: string;
description: string;
href: string;
}) {
return (
<div className="flex flex-col gap-2 bg-slate-200 dark:bg-slate-800 p-4 rounded-md h-28 overflow-auto">
<a href={href} className="text-sm underline hover:no-underline">
{title}
</a>
<p className="text-xs">{description}</p>
</div>
);
}