├── .eslintrc.json ├── src ├── app │ ├── favicon.ico │ ├── globals.css │ ├── layout.js │ ├── page.js │ ├── tokens │ │ └── page.js │ └── prompts │ │ ├── page.js │ │ └── [prompt_id] │ │ └── page.js └── lib │ ├── dbutil.js │ └── auth.js ├── jsconfig.json ├── next.config.js ├── postcss.config.js ├── .vscode └── settings.json ├── .env.example ├── .editorconfig ├── pages └── api │ ├── auth │ └── [...nextauth].js │ ├── tokens │ ├── generate │ │ └── index.js │ └── index.js │ ├── prompts │ ├── [prompt_id] │ │ └── index.js │ └── chat │ │ └── index.js │ ├── prompts.js │ └── parse.js ├── .gitignore ├── tailwind.config.js ├── public ├── vercel.svg └── next.svg ├── package.json └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sugarforever/amazing-jo.js/main/src/app/favicon.ico -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./src/*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[javascript]": { 3 | "editor.defaultFormatter": "vscode.typescript-language-features" 4 | } 5 | } -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | GITHUB_CLIENT_ID= 2 | GITHUB_CLIENT_SECRET= 3 | NEXTAUTH_SECRET= 4 | NEXTAUTH_URL= 5 | 6 | SUPABASE_URL= 7 | SUPABASE_API_KEY= -------------------------------------------------------------------------------- /src/lib/dbutil.js: -------------------------------------------------------------------------------- 1 | import { createClient } from '@supabase/supabase-js'; 2 | 3 | const getSupabaseClient = () => { 4 | return createClient(process.env.SUPABASE_URL, process.env.SUPABASE_API_KEY); 5 | } 6 | 7 | export { 8 | getSupabaseClient 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [*.{vue,js}] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [docker-compose.yml] 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /pages/api/auth/[...nextauth].js: -------------------------------------------------------------------------------- 1 | import NextAuth from "next-auth" 2 | import GithubProvider from "next-auth/providers/github" 3 | export const authOptions = { 4 | // Configure one or more authentication providers 5 | providers: [ 6 | GithubProvider({ 7 | clientId: process.env.GITHUB_CLIENT_ID, 8 | clientSecret: process.env.GITHUB_CLIENT_SECRET, 9 | }), 10 | // ...add more providers here 11 | ], 12 | } 13 | export default NextAuth(authOptions) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 5 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 6 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 7 | ], 8 | theme: { 9 | extend: { 10 | backgroundImage: { 11 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 12 | 'gradient-conic': 13 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 14 | }, 15 | }, 16 | }, 17 | plugins: [], 18 | } 19 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | -------------------------------------------------------------------------------- /src/lib/auth.js: -------------------------------------------------------------------------------- 1 | import { getSupabaseClient } from '@/lib/dbutil'; 2 | 3 | const validate = async (token) => { 4 | if (!token) { 5 | return null; 6 | } 7 | 8 | const supabase = getSupabaseClient(); 9 | try { 10 | const { data, error } = await supabase 11 | .from('tokens') 12 | .select('*') 13 | .eq('token', token) 14 | .limit(1); 15 | 16 | if (error) { 17 | console.error('Error querying data:', error.message); 18 | return null; 19 | } 20 | return data.length > 0 ? data[0].user_name : null; 21 | } catch (error) { 22 | console.error('Error querying data:', error.message); 23 | return null; 24 | } 25 | } 26 | 27 | export { 28 | validate 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amazing-jo.js", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.11.1", 13 | "@emotion/styled": "^11.11.0", 14 | "@mui/icons-material": "^5.14.8", 15 | "@mui/lab": "5.0.0-alpha.143", 16 | "@mui/material": "^5.14.8", 17 | "@supabase/auth-helpers-nextjs": "^0.7.4", 18 | "@supabase/auth-helpers-react": "^0.4.2", 19 | "@supabase/supabase-js": "^2.33.2", 20 | "@vercel/analytics": "^1.0.2", 21 | "autoprefixer": "10.4.15", 22 | "eslint": "8.48.0", 23 | "eslint-config-next": "13.4.19", 24 | "express": "^4.18.2", 25 | "jsdom": "^22.1.0", 26 | "langchain": "^0.0.135", 27 | "next": "13.4.19", 28 | "next-auth": "^4.23.1", 29 | "openai": "^4.2.0", 30 | "postcss": "8.4.28", 31 | "react": "18.2.0", 32 | "react-markdown": "^8.0.7", 33 | "rehype-highlight": "^7.0.0", 34 | "remark": "^14.0.3", 35 | "remark-gfm": "^3.0.1", 36 | "remark-html": "^15.0.2", 37 | "tailwindcss": "3.3.3", 38 | "uuid": "^9.0.1", 39 | "zod": "^3.22.2" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/api/tokens/generate/index.js: -------------------------------------------------------------------------------- 1 | import { getSupabaseClient } from '@/lib/dbutil'; 2 | import { getServerSession } from "next-auth/next" 3 | import { authOptions } from "../../auth/[...nextauth]" 4 | import { v4 as uuidv4 } from "uuid"; 5 | 6 | export default async function handler(req, res) { 7 | res.setHeader('Cache-Control', 'no-cache'); 8 | 9 | const session = await getServerSession(req, res, authOptions) 10 | const email = session?.user?.email; 11 | 12 | if (req.method === 'POST') { 13 | if (email) { 14 | const supabase = getSupabaseClient(); 15 | try { 16 | const { data, error } = await supabase 17 | .from('tokens') 18 | .upsert( 19 | [ 20 | { 21 | user_name: email, 22 | token: uuidv4() 23 | }, 24 | ], 25 | { onConflict: ["user_name"] } 26 | ) 27 | .select(); 28 | 29 | if (error) { 30 | console.error('Error inserting data:', error.message); 31 | res.status(500) 32 | } else { 33 | res.status(200).json({ 34 | token: data[0] 35 | }); 36 | } 37 | } catch (error) { 38 | console.error('Error inserting data:', error.message); 39 | res.status(500) 40 | } 41 | } else { 42 | res.status(401).json({ error: 'Unauthorized' }); 43 | } 44 | } else { 45 | res.status(405).json({ error: 'Method not allowed.' }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pages/api/tokens/index.js: -------------------------------------------------------------------------------- 1 | import { getSupabaseClient } from '@/lib/dbutil'; 2 | import { getServerSession } from "next-auth/next" 3 | import { authOptions } from "../auth/[...nextauth]" 4 | 5 | const queryTokens = async (email) => { 6 | const supabase = getSupabaseClient(); 7 | try { 8 | const { data, error } = await supabase 9 | .from('tokens') 10 | .select('*') 11 | .eq('user_name', email); 12 | 13 | return { data, error }; 14 | } catch (error) { 15 | console.error('Error querying data:', error.message); 16 | return { data: [], error } 17 | } 18 | } 19 | 20 | export default async function handler(req, res) { 21 | res.setHeader('Cache-Control', 'no-cache'); 22 | 23 | const session = await getServerSession(req, res, authOptions) 24 | const email = session?.user?.email; 25 | 26 | if (req.method === 'GET') { 27 | if (email) { 28 | const { data, error } = await queryTokens(email); 29 | if (error) { 30 | console.error('Error querying data:', error.message); 31 | res.status(500).json({ 32 | error: error.message 33 | }) 34 | } else { 35 | if (data) { 36 | res.status(200).json({ 37 | tokens: data 38 | }); 39 | } else { 40 | res.status(404); 41 | } 42 | } 43 | } else { 44 | res.status(401).json({ error: 'Unauthorized' }); 45 | } 46 | } else { 47 | res.status(405).json({ error: 'Method not allowed.' }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /pages/api/prompts/[prompt_id]/index.js: -------------------------------------------------------------------------------- 1 | import { getSupabaseClient } from '@/lib/dbutil'; 2 | import { getServerSession } from "next-auth/next" 3 | import { authOptions } from "../../auth/[...nextauth]" 4 | 5 | const queryPrompt = async (email, prompt_id) => { 6 | const supabase = getSupabaseClient(); 7 | try { 8 | const { data, error } = await supabase 9 | .from('prompts') 10 | .select('*') 11 | .eq('id', prompt_id) 12 | .eq('user_name', email) 13 | .limit(1); 14 | 15 | return { data, error }; 16 | } catch (error) { 17 | console.error('Error querying data:', error.message); 18 | return { data: [], error } 19 | } 20 | } 21 | 22 | export default async function handler(req, res) { 23 | res.setHeader('Cache-Control', 'no-cache'); 24 | 25 | const session = await getServerSession(req, res, authOptions) 26 | const email = session?.user?.email; 27 | const { prompt_id } = req.query; 28 | 29 | if (req.method === 'GET') { 30 | if (email) { 31 | const { data, error } = await queryPrompt(email, prompt_id); 32 | if (error) { 33 | console.error('Error querying data:', error.message); 34 | res.status(500).json({ 35 | error: error.message 36 | }) 37 | } else { 38 | const [first] = data; 39 | if (first) { 40 | res.status(200).json({ 41 | prompt: first 42 | }); 43 | } else { 44 | res.status(404); 45 | } 46 | } 47 | } else { 48 | res.status(401).json({ error: 'Unauthorized' }); 49 | } 50 | } else { 51 | res.status(405).json({ error: 'Method not allowed.' }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/app/layout.js: -------------------------------------------------------------------------------- 1 | 2 | import './globals.css'; 3 | import { Inter } from 'next/font/google'; 4 | import { getServerSession } from "next-auth/next" 5 | import { authOptions } from "pages/api/auth/[...nextauth]" 6 | import Link from 'next/link'; 7 | import { Analytics } from '@vercel/analytics/react'; 8 | 9 | const inter = Inter({ subsets: ['latin'] }) 10 | 11 | const pages = ['Prompts']; 12 | const settings = ['Logout']; 13 | 14 | export const metadata = { 15 | title: "Amazing JO", 16 | description: "Amazing JO is the AI driven services hub that provides useful features to customers.", 17 | } 18 | 19 | export default async function RootLayout({ children }) { 20 | const session = await getServerSession(authOptions) 21 | 22 | return ( 23 | 24 |
25 |{JSON.stringify(recipe, null, 2)}
45 | )}
46 |