├── vercel.png ├── page-speed.png ├── public ├── image.png ├── logo.png ├── none.png ├── favicon.png ├── pwa-512.png ├── robots.txt ├── image-white.png └── apple-touch-icon.png ├── src ├── env.d.ts ├── components │ ├── Count.astro │ ├── Footer.astro │ ├── Card.astro │ ├── Categories.astro │ ├── ImgIco.astro │ ├── Lists.astro │ ├── Header.astro │ ├── Themetoggle.astro │ └── Search.astro ├── libs │ ├── postgres.ts │ └── readerList.ts ├── pages │ ├── api │ │ ├── categories.ts │ │ ├── get-by-key.ts │ │ ├── search.json.ts │ │ ├── get-count.ts │ │ └── get.ts │ ├── index.astro │ ├── terms │ │ ├── privacy-policy │ │ │ └── index.astro │ │ └── terms-of-service │ │ │ └── index.astro │ ├── gpts-store │ │ └── [searchKey].astro │ └── 404.astro ├── static │ ├── global.css │ └── widgets.js └── layouts │ └── Layout.astro ├── .vscode ├── extensions.json └── launch.json ├── tsconfig.json ├── .gitignore ├── astro.config.mjs ├── tailwind.config.mjs ├── package.json └── README.md /vercel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/vercel.png -------------------------------------------------------------------------------- /page-speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/page-speed.png -------------------------------------------------------------------------------- /public/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/image.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/logo.png -------------------------------------------------------------------------------- /public/none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/none.png -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/favicon.png -------------------------------------------------------------------------------- /public/pwa-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/pwa-512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: http://gptsurl.com/sitemap.xml -------------------------------------------------------------------------------- /public/image-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/image-white.png -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | 4 | declare module 'markdown-it'; -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CH563/gpts-url/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /src/components/Count.astro: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 |

Share and discover the best custom GPTs in ChatGPT store by OpenAI

-------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "jsxImportSource": "react" 6 | }, 7 | "exclude": ["./src/example/*"] 8 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/libs/postgres.ts: -------------------------------------------------------------------------------- 1 | import { createPool } from '@vercel/postgres'; 2 | 3 | const connectDb = async () => { 4 | const client = createPool({ 5 | connectionString: import.meta.env.POSTGRES_URL 6 | }); 7 | await client.connect(); 8 | return client; 9 | }; 10 | 11 | export default await connectDb(); 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | 7 | # dependencies 8 | node_modules/ 9 | 10 | # logs 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # example to run 24 | example -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import vercel from "@astrojs/vercel/serverless"; 3 | import tailwind from "@astrojs/tailwind"; 4 | 5 | const site = "https://wwww.gptsurl.com"; 6 | 7 | // https://astro.build/config 8 | export default defineConfig({ 9 | site, 10 | output: "server", 11 | adapter: vercel({ 12 | webAnalytics: { 13 | enabled: true 14 | } 15 | }), 16 | integrations: [tailwind()] 17 | }); -------------------------------------------------------------------------------- /tailwind.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | darkMode: 'class', 4 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], 5 | theme: { 6 | container: { 7 | center: true, 8 | padding: '2rem', 9 | screens: { 10 | '2xl': '1400px', 11 | }, 12 | }, 13 | extend: {}, 14 | }, 15 | plugins: [require('@tailwindcss/typography')], 16 | } 17 | -------------------------------------------------------------------------------- /src/pages/api/categories.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from 'astro'; 2 | import client from '../../libs/postgres'; 3 | 4 | export const GET: APIRoute = async () => { 5 | let lists: any[] = []; 6 | const { rows } = await client.sql`SELECT id,categories_name FROM categories order by id;`.catch(() => { 7 | return { 8 | rows: [] 9 | }; 10 | }); 11 | lists = rows; 12 | return new Response( 13 | JSON.stringify({ 14 | code: 0, 15 | data: { 16 | lists 17 | }, 18 | }) 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /src/components/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | -------------------------------------------------------------------------------- /src/pages/api/get-by-key.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from 'astro'; 2 | import client from '../../libs/postgres'; 3 | 4 | export const GET: APIRoute = async ({request}) => { 5 | const _obj: any = {} 6 | new URL(request.url).searchParams.forEach((value, key) => { 7 | _obj[key] = value 8 | }); 9 | const { key } = _obj; 10 | const { rows } = await client.sql`SELECT url, title, icon, description, author, content, twitter FROM gpts_lists WHERE search_key = ${key} limit 1;`.catch(() => { 11 | return { 12 | rows: [] 13 | }; 14 | }); 15 | return new Response( 16 | JSON.stringify({ 17 | code: 0, 18 | data: { 19 | lists: rows, 20 | }, 21 | }) 22 | ); 23 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gpts-url", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/check": "^0.3.1", 14 | "@astrojs/react": "^3.0.4", 15 | "@astrojs/tailwind": "^5.0.2", 16 | "@astrojs/vercel": "^5.2.0", 17 | "@vercel/postgres": "^0.5.1", 18 | "astro": "^3.5.2", 19 | "astro-seo": "^0.8.0", 20 | "markdown-it": "^13.0.2", 21 | "tailwindcss": "^3.0.24", 22 | "typescript": "^5.2.2" 23 | }, 24 | "devDependencies": { 25 | "@tailwindcss/typography": "^0.5.10", 26 | "@types/markdown-it": "^13.0.6" 27 | } 28 | } -------------------------------------------------------------------------------- /src/components/Card.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import ImgIco from '../components/ImgIco.astro'; 3 | 4 | export interface Props { 5 | item: any; 6 | } 7 | const { item } = Astro.props 8 | --- 9 | 10 | 14 | 15 |
16 |

17 | {item.title} 18 |

19 | {item.author &&

by {item.author}

} 20 |

21 | {item.description} 22 |

23 |
24 |
25 | -------------------------------------------------------------------------------- /src/components/Categories.astro: -------------------------------------------------------------------------------- 1 | --- 2 | let lists = [{id:0,categories_name:'👌 All'},{id:-1,categories_name:'🔥 Popular'}]; 3 | const searchVal = Astro.url.searchParams.get('s') || ''; 4 | try { 5 | const response = await fetch(`${Astro.url.origin}/api/categories`); 6 | if (response.ok) { 7 | const json = await response.json(); 8 | lists.push(...json.data.lists); 9 | } 10 | } catch (error) { 11 | 12 | } 13 | --- 14 | 15 |
16 | { 17 | lists.map((item: {id: number, categories_name: string}) => ( 18 | 19 | )) 20 | } 21 |
22 | -------------------------------------------------------------------------------- /src/pages/api/search.json.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from 'astro'; 2 | import client from '../../libs/postgres'; 3 | 4 | export const POST: APIRoute = async ({ request }) => { 5 | const body = await request.json(); 6 | const keyword = body.keyword; 7 | let lists: any[] = []; 8 | if (keyword) { 9 | try { 10 | const k = `%${keyword}%`; 11 | const { rows } = await client.sql`select url, icon, title, description, author from gpts_lists WHERE title ilike ${k} or description ilike ${k} limit 6`; 12 | if (rows?.length) lists = rows; 13 | } catch (error) { 14 | // console.log(error); 15 | } 16 | } else { 17 | try { 18 | const { rows } = await client.sql`SELECT url, title, icon, description, author FROM gpts_lists order by RANDOM() desc limit 51;`; 19 | if (rows?.length) lists = rows; 20 | } catch (error) { 21 | // console.log(error); 22 | } 23 | } 24 | return new Response(JSON.stringify({ 25 | code: 0, 26 | lists 27 | }) 28 | ) 29 | }; -------------------------------------------------------------------------------- /src/components/ImgIco.astro: -------------------------------------------------------------------------------- 1 | --- 2 | export interface Props { 3 | icon: string; 4 | title: string 5 | } 6 | 7 | const { icon, title } = Astro.props; 8 | --- 9 | { 10 | icon ? {title} : 11 |
12 | 13 |
14 | } -------------------------------------------------------------------------------- /src/components/Lists.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Card from '../components/Card.astro'; 3 | let lists = []; 4 | let pageSize = 30; 5 | let count = 0; 6 | const searchVal = Astro.url.searchParams.get('s') || ''; 7 | try { 8 | const response = await fetch(`${Astro.url.origin}/api/get?keyword=${searchVal}`); 9 | if (response.ok) { 10 | const json = await response.json(); 11 | lists = json.data.lists; 12 | pageSize = json.data.page_size; 13 | } 14 | const countRes = await fetch(`${Astro.url.origin}/api/get-count?keyword=${searchVal}`); 15 | if (countRes.ok) { 16 | const json = await countRes.json(); 17 | count = +json.data.count; 18 | } 19 | } catch (error) { 20 | // 21 | } 22 | --- 23 | 24 |
25 | {lists.length ? lists.map((item: any) => ) :
Can't find the "{searchVal}" GPTs
} 26 | {count > pageSize &&
27 | 28 |
} 29 |
30 | -------------------------------------------------------------------------------- /src/static/global.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --accent: 136, 58, 234; 3 | --accent-light: 224, 204, 250; 4 | --accent-dark: 49, 10, 101; 5 | --accent-gradient: linear-gradient( 6 | 45deg, 7 | rgb(var(--accent)), 8 | rgb(var(--accent-light)) 30%, 9 | white 60% 10 | ); 11 | --c-bg: #fbfbfb; 12 | --c-bg-op: #fbfbfb00; 13 | --c-fg: #444444; 14 | --c-scroll: #d9d9d9; 15 | --c-scroll-hover: #bbbbbb; 16 | scrollbar-color: var(--c-scrollbar) var(--c-bg); 17 | --primary-glow: conic-gradient(from 180deg at 50% 50%,#16abff33 0deg,#0885ff33 55deg,#54d6ff33 120deg,#0071ff33 160deg,transparent 360deg); 18 | } 19 | 20 | html { 21 | font-family: system-ui, sans-serif; 22 | background-color: var(--c-bg); 23 | color: var(--c-fg); 24 | } 25 | 26 | html.dark { 27 | --c-bg: #212129; 28 | --c-bg-op: #21212900; 29 | --c-fg: #ddddf0; 30 | --c-scroll: #333333; 31 | --c-scroll-hover: #555555; 32 | } 33 | 34 | ::-webkit-scrollbar { 35 | width: 6px; 36 | height: 6px; 37 | } 38 | ::-webkit-scrollbar-thumb { 39 | background-color: var(--c-scroll); 40 | border-radius: 4px; 41 | } 42 | ::-webkit-scrollbar-thumb:hover { 43 | background-color: var(--c-scroll-hover); 44 | } 45 | ::-webkit-scrollbar-track { 46 | background-color: var(--c-bg); 47 | } -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../layouts/Layout.astro'; 3 | import Header from '../components/Header.astro'; 4 | import Footer from '../components/Footer.astro'; 5 | import Categories from '../components/Categories.astro'; 6 | import Lists from '../components/Lists.astro'; 7 | import Search from '../components/Search.astro'; 8 | import Count from '../components/Count.astro'; 9 | --- 10 | 11 | 12 |
13 |
14 |
15 | GPTs URL - With GPTs Url, you can discover the best GPTs in GPT store | Product Hunt 16 |

Discover Amazing GPTs

17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |