Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# NEON_DATA_API_URL, required, the URL of your Neon Data API
VITE_NEON_DATA_API_URL=https://data-api-url
# PUBLIC_STACK_PROJECT_ID, required, your Stack Auth project id
VITE_PUBLIC_STACK_PROJECT_ID=432a953b-30fb-4fbf-a73d-c0294dc5fdf5
# PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY, required, your Stack Auth publishable client key
VITE_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=pck_mf296kj2dky278d62bkyefs63w3w492qgajcwx55v13bg
# NEON_AUTH_URL, required, your Neon Auth URL
VITE_NEON_AUTH_URL=https://neon-auth-url

# DATABASE_URL, optional, only if you want to run drizzle migrations with bun db:migrate
DATABASE_URL=your-database-url
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Ignore artifacts:
build
coverage
src/routeTree.gen.ts
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ Follow these steps to run the demo:
VITE_NEON_DATA_API_URL=your_neon_data_api_url

# Neon Auth
VITE_PUBLIC_STACK_PROJECT_ID=your_project_id
VITE_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY=your_client_key
VITE_NEON_AUTH_URL=your_neon_auth_url
```

Optionally, you can configure a `DATABASE_URL` environment variable and run `bun run db:migrate` to migrate your database.
Expand Down Expand Up @@ -79,6 +78,6 @@ This application is configured for deployment on Vercel:
1. Push your code to a Git repository
2. Import the project in Vercel
3. Configure environment variables:
- Neon Data API credentials
- Neon Auth credentials
- `VITE_NEON_DATA_API_URL`: Neon Data API URL
- `VITE_NEON_AUTH_URL`: Neon Auth URL
4. Deploy!
1,096 changes: 661 additions & 435 deletions bun.lock

Large diffs are not rendered by default.

51 changes: 25 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,39 @@
"prettier-check": "prettier --check ."
},
"dependencies": {
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-toggle": "^1.1.6",
"@stackframe/react": "^2.8.8",
"@supabase/postgrest-js": "^1.19.4",
"@tailwindcss/vite": "^4.1.4",
"@tanstack/react-query": "^5.74.4",
"@tanstack/react-router": "^1.117.1",
"@neondatabase/neon-js": "^0.1.0-alpha.6",
"@neondatabase/serverless": "^1.0.2",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-toggle": "^1.1.10",
"@tailwindcss/vite": "^4.1.17",
"@tanstack/react-query": "^5.90.11",
"@tanstack/react-router": "^1.139.10",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"drizzle-kit": "^0.31.0",
"drizzle-orm": "^0.43.1",
"@neondatabase/serverless": "^0.10.4",
"drizzle-kit": "^0.31.7",
"drizzle-orm": "^0.44.7",
"lucide-react": "^0.503.0",
"moment": "^2.30.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.17",
"unique-names-generator": "^4.7.1"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@tanstack/react-router-devtools": "^1.117.1",
"@tanstack/router-plugin": "^1.117.2",
"@types/node": "^22.15.2",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
"dotenv": "^16.5.0",
"globals": "^16.0.0",
"@tanstack/react-router-devtools": "^1.139.10",
"@tanstack/router-plugin": "^1.139.10",
"@types/node": "^22.19.1",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^4.7.0",
"dotenv": "^16.6.1",
"globals": "^16.5.0",
"prettier": "3.5.3",
"tsx": "^4.19.3",
"tw-animate-css": "^1.2.8",
"typescript": "~5.7.2",
"vite": "^6.3.1"
"tsx": "^4.20.6",
"tw-animate-css": "^1.4.0",
"typescript": "~5.7.3",
"vite": "^6.4.1"
}
}
3 changes: 0 additions & 3 deletions src/access-token-context.tsx

This file was deleted.

38 changes: 0 additions & 38 deletions src/access-token-provider.tsx

This file was deleted.

17 changes: 3 additions & 14 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { StrictMode, useContext } from "react";
import { StrictMode } from "react";

// Import the generated route tree
import { routeTree } from "./routeTree.gen";

import { AccessTokenProvider } from "@/access-token-provider";
import { stackClientApp } from "@/lib/stack";
import { StackProvider } from "@stackframe/react";
import { AccessTokenContext } from "./access-token-context";

// Create a new router instance
const router = createRouter({
routeTree,
Expand All @@ -33,20 +28,14 @@ function App() {
return (
<StrictMode>
<QueryClientProvider client={queryClient}>
<StackProvider app={stackClientApp}>
<AccessTokenProvider>
<RouterWithAuth />
</AccessTokenProvider>
</StackProvider>
<RouterWithAuth />
</QueryClientProvider>
</StrictMode>
);
}

function RouterWithAuth() {
const accessToken = useContext(AccessTokenContext);

return <RouterProvider router={router} context={{ accessToken }} />;
return <RouterProvider router={router} />;
}

export default App;
13 changes: 9 additions & 4 deletions src/components/app/header.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import type { CurrentUser } from "@stackframe/react";
import { client } from "@/lib/auth";
import { useRouter } from "@tanstack/react-router";

export default function Header({ user }: { user: CurrentUser }) {
export default function Header({ name }: { name: string }) {
const router = useRouter();
return (
<header className="flex flex-col gap-6 mb-14">
<div className="flex items-center justify-between">
<h3>Welcome {user.displayName?.split(" ")[0]}</h3>
<h3>Welcome {name}</h3>
<button
type="button"
className="text-foreground/70 font-normal cursor-pointer"
onClick={() => user.signOut()}
onClick={async () => {
await client.auth.signOut();
router.navigate({ to: "/signin" });
}}
>
Sign out
</button>
Expand Down
6 changes: 2 additions & 4 deletions src/components/app/note-header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NoteTitle } from "@/components/app/note-title";
import { Toggle } from "@/components/ui/toggle";
import { Note } from "@/lib/api";
import { usePostgrest } from "@/lib/postgrest";
import { client } from "@/lib/auth";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { Share2 } from "lucide-react";
import { useEffect, useState } from "react";
Expand All @@ -23,8 +23,6 @@ export default function NoteHeader({
user_id,
onShareToggle,
}: Props) {
const postgrest = usePostgrest();

// Optimistic UI state for shared toggle
const [optimisticShared, setOptimisticShared] = useState<boolean | null>(
null,
Expand All @@ -43,7 +41,7 @@ export default function NoteHeader({

const toggleShareMutation = useMutation({
mutationFn: async (newSharedState: boolean) => {
const { error } = await postgrest
const { error } = await client
.from("notes")
.update({
shared: newSharedState,
Expand Down
5 changes: 2 additions & 3 deletions src/components/app/note-title.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Note } from "@/lib/api";
import { usePostgrest } from "@/lib/postgrest";
import { client } from "@/lib/auth";
import { useQueryClient } from "@tanstack/react-query";
import { Copy } from "lucide-react";
import { type KeyboardEvent, useEffect, useRef, useState } from "react";
Expand All @@ -18,7 +18,6 @@ export function NoteTitle({
const [isEditingTitle, setIsEditingTitle] = useState(false);
const [titleValue, setTitleValue] = useState(title);
const titleRef = useRef<HTMLHeadingElement>(null);
const postgrest = usePostgrest();

// Focus title when editing
useEffect(() => {
Expand Down Expand Up @@ -52,7 +51,7 @@ export function NoteTitle({
const newTitle = titleRef.current.textContent.trim();
if (newTitle !== title) {
try {
const { error } = await postgrest
const { error } = await client
.from("notes")
.update({ title: newTitle })
.eq("id", id);
Expand Down
8 changes: 1 addition & 7 deletions src/components/app/notes-list.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import NoteCard from "@/components/app/note-card";
import type { Note } from "@/lib/api";
import type { CurrentUser } from "@stackframe/react";
import { useRouter } from "@tanstack/react-router";
import { PlusCircleIcon } from "lucide-react";

export default function NotesList({
notes,
}: {
user: CurrentUser;
notes: Note[];
}) {
export default function NotesList({ notes }: { notes: Note[] }) {
const router = useRouter();

const addNote = async () => {
Expand Down
12 changes: 12 additions & 0 deletions src/lib/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createClient, BetterAuthReactAdapter } from "@neondatabase/neon-js";
import type { Database } from "../../types/database";

export const client = createClient<Database>({
auth: {
adapter: BetterAuthReactAdapter(),
url: import.meta.env.VITE_NEON_AUTH_URL,
},
dataApi: {
url: import.meta.env.VITE_NEON_DATA_API_URL,
},
});
26 changes: 0 additions & 26 deletions src/lib/postgrest.ts

This file was deleted.

21 changes: 0 additions & 21 deletions src/lib/stack.ts

This file was deleted.

Loading