Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian-AT committed Oct 13, 2024
1 parent 9871705 commit 313722a
Show file tree
Hide file tree
Showing 164 changed files with 22,651 additions and 117 deletions.
1 change: 1 addition & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
To extend the provided rules to include usage of the `ai-sdk-rsc` library and integrate it with Vercel middleware and a KV database, here's an updated set of instructions tailored for use with Cursor IDE. These instructions are designed to help you effectively implement generative user interfaces using React Server Components (RSC) with the AI SDK.### Extended Rules for AI SDK RSC Integration with Vercel Middleware and KV Database**Environment and Tools**- You are an expert in TypeScript, Node.js, Next.js App Router, React, Shadcn UI, Radix UI, Tailwind, and Vercel middleware.- You are familiar with Vercel's KV database for managing stateful data.**Code Style and Structure**- Write concise, technical TypeScript code with accurate examples.- Use functional and declarative programming patterns; avoid classes.- Prefer iteration and modularization over code duplication.- Use descriptive variable names with auxiliary verbs (e.g., `isLoading`, `hasError`).- Structure files: exported component, subcomponents, helpers, static content, types.**Naming Conventions**- Use lowercase with dashes for directories (e.g., `components/auth-wizard`).- Favor named exports for components.**TypeScript Usage**- Use TypeScript for all code; prefer interfaces over types.- Avoid enums; use maps instead.- Use functional components with TypeScript interfaces.**Syntax and Formatting**- Use the `function` keyword for pure functions.- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.- Use declarative JSX.**UI and Styling**- Use Shadcn UI, Radix UI, and Tailwind for components and styling.- Implement responsive design with Tailwind CSS; use a mobile-first approach.**Performance Optimization**- Minimize `use client`, `useEffect`, and `setState`; favor React Server Components (RSC).- Wrap client components in `Suspense` with fallback.- Use dynamic loading for non-critical components.- Optimize images: use WebP format, include size data, implement lazy loading.**Key Conventions**- Use `nuqs` for URL search parameter state management.- Optimize Web Vitals (LCP, CLS, FID).- Limit `use client`: - Favor server components and Next.js SSR. - Use only for Web API access in small components. - Avoid for data fetching or state management.- Follow Next.js docs for Data Fetching, Rendering, and Routing.**AI SDK RSC Integration**- **Setup and Installation**: Integrate `ai-sdk-rsc` into your Next.js project. - Install the library using `npm install ai-sdk-rsc` or `yarn add ai-sdk-rsc`. - Configure middleware in `middleware.ts` to manage requests and sessions using Vercel's KV database.  - **Middleware Implementation**: Use Vercel middleware to handle incoming requests. - Create a middleware file in the `middleware` directory (e.g., `middleware/ai-middleware.ts`). - Use middleware to parse user input and manage sessions with the KV database. - Example:  ```typescript  import { NextRequest, NextResponse } from 'next/server';  import { kv } from '@vercel/kv';  export async function middleware(req: NextRequest) {   const sessionId = req.cookies.get('session-id');   if (!sessionId) {    const newSessionId = generateSessionId();    await kv.set(newSessionId, { state: {} }); // Initialize state in KV database    const res = NextResponse.next();    res.cookies.set('session-id', newSessionId);    return res;   }   // Fetch state from KV database   const state = await kv.get(sessionId);   req.nextUrl.searchParams.set('state', JSON.stringify(state));   return NextResponse.next();  }  function generateSessionId() {   return Math.random().toString(36).substring(2);  }  ```- **React Server Components (RSC) and AI SDK**: - Use `ai-sdk-rsc` hooks to manage state and stream generative content. - Example usage of AI SDK hooks in a React Server Component:  ```typescript  import { useAIStream } from 'ai-sdk-rsc';  import { FC } from 'react';  interface ChatProps {   initialMessage: string;  }  const Chat: FC = ({ initialMessage }) => {   const { messages, sendMessage } = useAIStream({    initialMessage,    onMessage: (message) => console.log('New message:', message),   });   return (    {msg.content}  export default Chat;  ```- **KV Database Integration**: - Use Vercel's KV database to store and retrieve session data. - Utilize `kv.set`, `kv.get`, and `kv.delete` to manage data. - Ensure the database operations are asynchronous to avoid blocking server-side rendering (SSR).- **Data Fetching and State Management**: - Use Next.js data fetching methods (`getServerSideProps`, `getStaticProps`) to manage server-side state. - Avoid client-side data fetching methods (`useEffect`, `fetch`) except for critical, non-blocking operations.- **Deployment Considerations**: - Ensure all environment variables (e.g., API keys, database credentials) are securely stored in Vercel's environment settings. - Configure Vercel's KV and other serverless functions correctly to handle scalability and performance needs.By following these extended rules, you'll be able to create a well-optimized, scalable, and efficient Next.js application that leverages `ai-sdk-rsc`, Vercel middleware, and KV database for building sophisticated AI-driven interfaces.
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# editorconfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
32 changes: 32 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "https://json.schemastore.org/eslintrc",
"root": true,
"extends": [
"next/core-web-vitals",
"turbo",
"prettier",
"plugin:tailwindcss/recommended"
],
"plugins": ["tailwindcss"],
"ignorePatterns": ["**/fixtures/**"],
"rules": {
"@next/next/no-html-link-for-pages": "off",
"tailwindcss/no-custom-classname": "off",
"tailwindcss/classnames-order": "error"
},
"settings": {
"tailwindcss": {
"callees": ["cn", "cva"],
"config": "tailwind.config.cjs"
},
"next": {
"rootDir": ["apps/*/"]
}
},
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"parser": "@typescript-eslint/parser"
}
]
}
145 changes: 28 additions & 117 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,130 +1,41 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# Runtime data
pids
*.pid
*.seed
*.pid.lock
# dependencies
node_modules
.pnp
.pnp.js

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
# testing
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# next.js
.next/
out/
build

# Optional REPL history
.node_repl_history
# misc
.DS_Store
*.pem

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# dotenv environment variable files
.env
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port
# turbo
.turbo

# Stores VSCode versions used for testing VSCode extensions
.vscode-test
.contentlayer
tsconfig.tsbuildinfo

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# ide
.idea
.fleet
.vscode
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto-install-peers=true
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dist
node_modules
.next
build
.contentlayer
apps/www/pages/api/registry.json
**/fixtures
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"plugins": [
"prettier-plugin-tailwindcss"
]
}
54 changes: 54 additions & 0 deletions app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { cn } from "@/lib/utils";
import { HorizontalGradient } from "@/components/marketing/horizontal-gradient";
import Link from "next/link";
import { buttonVariants } from "@/components/ui/button";
import { ArrowLeftIcon } from "@radix-ui/react-icons";
import { FileScriptIcon } from "hugeicons-react";

export default function AuthLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
<div className="grid min-h-screen w-full grid-cols-1 md:grid-cols-2">
<Link
href="/"
className={cn(
buttonVariants({ variant: "ghost" }),
"absolute left-4 top-4 flex items-center gap-2",
)}
>
<ArrowLeftIcon className="h-4 w-4" />
Back
</Link>
<div className="flex items-center justify-center">{children}</div>
<div className="relative z-20 hidden w-full items-center justify-center overflow-hidden border-l border-neutral-100 bg-gray-50 dark:border-neutral-800 dark:bg-muted/40 md:flex">
<div className="mx-auto max-w-sm">
<FileScriptIcon className="mx-auto h-12 w-12" />
<p
className={cn(
"py-6 text-center text-xl font-semibold text-secondary-foreground",
)}
>
Generate & Ship UI with minimal effort
</p>
<p
className={cn(
"-mt-4 text-center text-base font-normal text-neutral-500 dark:text-neutral-400",
)}
>
Synth UI allows you to generate User-Interfaces without writing a
single line of code.
</p>
</div>
<HorizontalGradient className="top-20 text-secondary" />
<HorizontalGradient className="bottom-20 text-secondary" />
<HorizontalGradient className="inset-y-0 -right-80 h-full rotate-90 scale-x-150 transform text-secondary" />
<HorizontalGradient className="inset-y-0 -left-80 h-full rotate-90 scale-x-150 transform text-secondary" />
</div>
</div>
</>
);
}
5 changes: 5 additions & 0 deletions app/(auth)/sign-in/[[...sign-in]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SignIn } from "@clerk/nextjs";

export default function SignInPage() {
return <SignIn />;
}
5 changes: 5 additions & 0 deletions app/(auth)/sign-up/[[...sign-up]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SignUp } from "@clerk/nextjs";

export default function SignUpPage() {
return <div className="flex h-screen items-center justify-center">test</div>;
}
63 changes: 63 additions & 0 deletions app/(chat)/chat/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Chat } from "@/components/chat";
import ChatHeader from "@/components/chat-header";
import { getChat, getMissingKeys } from "@/lib/actions/chat";
import { AI, getUIStateFromAIState } from "@/lib/ai/core";
import { currentUser } from "@clerk/nextjs/server";
import { Metadata } from "next";
import { notFound, redirect } from "next/navigation";

export interface ChatPageProps {
params: {
id: string;
};
}

export async function generateMetadata({
params,
}: ChatPageProps): Promise<Metadata> {
const user = await currentUser();

if (!user) {
return {};
}

const chat = await getChat(params.id, user.id);

if (!chat || "error" in chat) {
redirect("/chat");
} else {
return {
title:
(chat?.title.toString().slice(0, 50) ?? "Untitled Chat") +
" - Synth UI",
};
}
}

export default async function ChatPage({ params }: ChatPageProps) {
const user = await currentUser();
const missingKeys = await getMissingKeys();

if (!user) {
redirect(`/login?next=/chat/${params.id}`);
}

const userId = user.id;
const chat = await getChat(params.id, userId);

if (!chat || "error" in chat) {
redirect("/chat");
} else {
if (chat?.userId !== user?.id) {
notFound();
}

const messages = getUIStateFromAIState(chat);

return (
<AI initialAIState={chat} initialUIState={messages}>
<Chat id={params.id} missingKeys={missingKeys} />
</AI>
);
}
}
Loading

0 comments on commit 313722a

Please sign in to comment.