├── .eslintrc.json ├── .gitignore ├── README.md ├── app ├── api │ └── paste │ │ └── route.ts ├── delete │ └── [slug] │ │ └── page.tsx ├── favicon.ico ├── globals.css ├── layout.tsx ├── loading.tsx ├── page.tsx ├── paste │ └── [slug] │ │ └── page.tsx ├── pastes │ └── page.tsx └── raw │ └── [slug] │ └── route.ts ├── components.json ├── components ├── ads │ └── ad.tsx ├── footer │ └── footer.tsx ├── highlight │ └── code.tsx ├── main │ ├── combo-box.tsx │ └── upload-area.tsx ├── navigation │ └── nav.tsx ├── theme │ ├── theme-provider.tsx │ └── theme-toggle.tsx └── ui │ ├── button.tsx │ ├── command.tsx │ ├── dialog.tsx │ ├── dropdown-menu.tsx │ ├── popover.tsx │ ├── separator.tsx │ ├── textarea.tsx │ ├── toast.tsx │ ├── toaster.tsx │ └── use-toast.ts ├── lib ├── prisma.ts └── utils.ts ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── prisma ├── migrations │ ├── 20230902234402_wow │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma ├── public ├── cat.png └── catdns.gif ├── tailwind.config.js ├── tailwind.config.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.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 | .env 30 | /.env/ 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Hero](https://i.ibb.co/Ldsx1Zy/Captureaaa.jpg) 2 | 3 | 1. **Clone the Repository** 4 | 5 | ```sh 6 | git clone https://github.com/TeaByte/catpaste.git 7 | cd catpaste 8 | ``` 9 | 10 | 2. **Install Dependencies** 11 | 12 | ```sh 13 | npm install 14 | ``` 15 | 16 | 3. **Make `.env` File** 17 | 18 | ```env 19 | DATABASE_URL=postgres://TeaByte:HuypCZG.... 20 | SHADOW_DATABASE_URL=postgres://TeaByte:H.... 21 | ``` 22 | 23 | Neon PostgreSQL: https://console.neon.tech 24 | 25 | 4. **Start the Development Server** 26 | 27 | ```sh 28 | npm run dev 29 | ``` 30 | 31 | ## 32 | -------------------------------------------------------------------------------- /app/api/paste/route.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "@/lib/prisma"; 2 | import { NextResponse } from "next/server"; 3 | import { NextRequest } from "next/server"; 4 | import { v4 as uuidv4 } from "uuid"; 5 | 6 | export async function POST(request: NextRequest) { 7 | const data = await request.json(); 8 | let { text, syntax } = data; 9 | if (!syntax && !text) { 10 | return NextResponse.json({ 11 | message: "Not all fields are filled.", 12 | }); 13 | } 14 | syntax = syntax.toLowerCase(); 15 | 16 | if ((text as string).length > 2000) { 17 | return NextResponse.json({ 18 | message: "Text too long.", 19 | }); 20 | } 21 | 22 | try { 23 | const deleteToken = uuidv4(); 24 | const paste = await prisma.paste.create({ 25 | data: { 26 | text: text as string, 27 | syntax: syntax as string, 28 | delete: deleteToken, 29 | }, 30 | }); 31 | return NextResponse.json({ 32 | message: `${paste.id} Pasted successfully.`, 33 | token: deleteToken, 34 | id: paste.id, 35 | }); 36 | } catch (e) { 37 | return NextResponse.json({ 38 | message: "Error while creating paste.", 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/delete/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import { prisma } from "@/lib/prisma"; 2 | import { 3 | ExclamationTriangleIcon, 4 | CheckCircledIcon, 5 | } from "@radix-ui/react-icons"; 6 | 7 | interface Props { 8 | params: { slug: string }; 9 | } 10 | 11 | export default async function DeletePage({ params }: Props) { 12 | try { 13 | const paste = await prisma.paste.delete({ 14 | where: { 15 | delete: params.slug, 16 | }, 17 | }); 18 | return ( 19 |
20 | 21 |

{`${paste.id} deleted successfully.`}

22 |
23 | ); 24 | } catch { 25 | return ( 26 |
27 | 28 |

Already deleted or not found.

29 |
30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeaByte/cat-paste/7d112ab891574a83b7cb1d50eec2859b563bf9f4/app/favicon.ico -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --background: 0 0% 100%; 8 | --foreground: 240 10% 3.9%; 9 | --card: 0 0% 100%; 10 | --card-foreground: 240 10% 3.9%; 11 | --popover: 0 0% 100%; 12 | --popover-foreground: 240 10% 3.9%; 13 | --primary: 142.1 76.2% 36.3%; 14 | --primary-foreground: 355.7 100% 97.3%; 15 | --secondary: 240 4.8% 95.9%; 16 | --secondary-foreground: 240 5.9% 10%; 17 | --muted: 240 4.8% 95.9%; 18 | --muted-foreground: 240 3.8% 46.1%; 19 | --accent: 240 4.8% 95.9%; 20 | --accent-foreground: 240 5.9% 10%; 21 | --destructive: 0 84.2% 60.2%; 22 | --destructive-foreground: 0 0% 98%; 23 | --border: 240 5.9% 90%; 24 | --input: 240 5.9% 90%; 25 | --ring: 142.1 76.2% 36.3%; 26 | --radius: 0.5rem; 27 | } 28 | 29 | .dark { 30 | --background: 20 14.3% 4.1%; 31 | --foreground: 0 0% 95%; 32 | --card: 24 9.8% 10%; 33 | --card-foreground: 0 0% 95%; 34 | --popover: 0 0% 9%; 35 | --popover-foreground: 0 0% 95%; 36 | --primary: 142.1 70.6% 45.3%; 37 | --primary-foreground: 144.9 80.4% 10%; 38 | --secondary: 240 3.7% 15.9%; 39 | --secondary-foreground: 0 0% 98%; 40 | --muted: 0 0% 15%; 41 | --muted-foreground: 240 5% 64.9%; 42 | --accent: 12 6.5% 15.1%; 43 | --accent-foreground: 0 0% 98%; 44 | --destructive: 0 62.8% 30.6%; 45 | --destructive-foreground: 0 85.7% 97.3%; 46 | --border: 240 3.7% 15.9%; 47 | --input: 240 3.7% 15.9%; 48 | --ring: 142.4 71.8% 29.2%; 49 | } 50 | } 51 | 52 | @layer base { 53 | * { 54 | @apply border-border; 55 | } 56 | body { 57 | @apply bg-background text-foreground; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import "./globals.css"; 2 | 3 | import Nav from "@/components/navigation/nav"; 4 | import Ad from "@/components/ads/ad"; 5 | import Footer from "@/components/footer/footer"; 6 | import { ThemeProvider } from "@/components/theme/theme-provider"; 7 | import { Toaster } from "@/components/ui/toaster"; 8 | 9 | import type { Metadata } from "next"; 10 | import { Rubik } from "next/font/google"; 11 | 12 | const font = Rubik({ subsets: ["latin"] }); 13 | 14 | export const metadata: Metadata = { 15 | title: "Cat Paste", 16 | description: 17 | "CatPaste is a user-friendly online platform that allows individuals to easily and securely share and store text-based information, code snippets, and notes. Similar in concept to the popular Pastebin service, CatPaste offers a simple and efficient way to create, manage, and share text-based content with others. Whether you're a developer looking to share code snippets, a student collaborating on a project, or anyone in need of a convenient text-sharing solution, CatPaste is designed to simplify the process. With its clean and intuitive interface, users can quickly paste, share, and access text-based content, making it an indispensable tool for the digital age.", 18 | keywords: [ 19 | "Text sharing", 20 | "Code sharing", 21 | "Paste tool", 22 | "Collaborative notes", 23 | "Secure sharing", 24 | "Text storage", 25 | "Content management", 26 | "Data sharing", 27 | "Online clipboard", 28 | "Information sharing", 29 | "Note collaboration", 30 | "Code repository", 31 | "Text collaboration", 32 | "Document sharing", 33 | "Text hosting", 34 | "Code storage", 35 | "Collaborative text", 36 | "Note hosting", 37 | "Text repository", 38 | ], 39 | }; 40 | 41 | export default function RootLayout({ 42 | children, 43 | }: { 44 | children: React.ReactNode; 45 | }) { 46 | return ( 47 | 48 | 49 | 50 |