├── .env.example ├── .eslintrc.json ├── public └── logo.png ├── src ├── app │ ├── favicon.ico │ ├── layout.tsx │ ├── api │ │ └── predictions │ │ │ ├── [id] │ │ │ └── route.ts │ │ │ └── route.ts │ ├── globals.css │ └── page.tsx └── components │ ├── Footer.tsx │ ├── Footer.css │ ├── Navbar.tsx │ └── Navbar.css ├── postcss.config.js ├── .vscode └── settings.json ├── next-env.d.ts ├── .gitignore ├── next.config.js ├── tailwind.config.ts ├── tsconfig.json ├── package.json └── README.md /.env.example: -------------------------------------------------------------------------------- 1 | REPLICATE_API_TOKEN = -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaureshpai/ggreplicater/HEAD/public/logo.png -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaureshpai/ggreplicater/HEAD/src/app/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": "explicit" 4 | }, 5 | "eslint.validate": [ 6 | "typescript" 7 | ], 8 | "editor.formatOnSave": true 9 | } -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. 6 | -------------------------------------------------------------------------------- /.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 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | .env 31 | # vercel 32 | .vercel 33 | 34 | .vercel 35 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | images: { 4 | remotePatterns: [ 5 | { 6 | protocol: "https", 7 | hostname: "replicate.com", 8 | }, 9 | { 10 | protocol: 'https', 11 | hostname: 'replicate.delivery', 12 | port: '', 13 | pathname: '/pbxt/**', 14 | }, 15 | { 16 | protocol: 'https', 17 | hostname: 'raw.githubusercontent.com', 18 | } 19 | ], 20 | }, 21 | } 22 | 23 | module.exports = nextConfig 24 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Inter } from 'next/font/google' 3 | import './globals.css' 4 | 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata: Metadata = { 8 | title: 'ai replicater', 9 | description: 'Replicate AI Image generator', 10 | } 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: { 15 | children: React.ReactNode 16 | }) { 17 | return ( 18 | 19 | {children} 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import Link from 'next/link'; 3 | import './Footer.css'; 4 | 5 | export default function Footer() { 6 | return ( 7 |
8 |
9 | {/*

© {new Date().getFullYear()} Gauresh G Pai. All rights reserved.

*/} 10 |

Team Members: Shrepathi, Yashas, Saikumar, Adon

11 |
12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | const config: Config = { 4 | content: [ 5 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 6 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 7 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 13 | 'gradient-conic': 14 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | } 20 | export default config 21 | -------------------------------------------------------------------------------- /src/app/api/predictions/[id]/route.ts: -------------------------------------------------------------------------------- 1 | import Replicate from "replicate"; 2 | 3 | const replicate = new Replicate({ 4 | auth: process.env.REPLICATE_API_TOKEN 5 | }); 6 | 7 | export async function GET(request: Request, 8 | { params }: { params: { id: string } }) { 9 | const prediction = await replicate.predictions.get(params.id); 10 | 11 | if (prediction?.error) { 12 | return new Response( 13 | JSON.stringify({ detail: prediction.error.detail }), 14 | { status: 500 } 15 | ); 16 | } 17 | 18 | return new Response( 19 | JSON.stringify(prediction), 20 | { status: 200 } 21 | ); 22 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./src/*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ggreplicater", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "test": "npm run lint && npm run build" 11 | }, 12 | "dependencies": { 13 | "next": "^14.2.21", 14 | "react": "^18", 15 | "react-dom": "^18", 16 | "replicate": "^0.34.0" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^22", 20 | "@types/react": "^18", 21 | "@types/react-dom": "^18", 22 | "autoprefixer": "^10.4.20", 23 | "eslint": "^8", 24 | "eslint-config-next": "15.1.6", 25 | "postcss": "^8", 26 | "tailwindcss": "^3.4.17", 27 | "typescript": "^5" 28 | } 29 | } -------------------------------------------------------------------------------- /src/app/api/predictions/route.ts: -------------------------------------------------------------------------------- 1 | import Replicate from "replicate"; 2 | 3 | const replicate = new Replicate({ 4 | auth: process.env.REPLICATE_API_TOKEN, 5 | }); 6 | 7 | export async function POST(req: Request) { 8 | 9 | const data = await req.formData(); 10 | if (!process.env.REPLICATE_API_TOKEN) { 11 | throw new Error( 12 | "The REPLICATE_API_TOKEN environment variable is not set. See README.md for instructions on how to set it." 13 | ); 14 | } 15 | 16 | const prediction = await replicate.predictions.create({ 17 | // Pinned to a specific version of Stable Diffusion 18 | // See https://replicate.com/stability-ai/sdxl 19 | version: "8beff3369e81422112d93b89ca01426147de542cd4684c244b673b105188fe5f", 20 | 21 | // This is the text prompt that will be submitted by a form on the frontend 22 | input: { prompt: data.get("prompt") }, 23 | }); 24 | 25 | if (prediction?.error) { 26 | return new Response( 27 | JSON.stringify({ detail: prediction.error.detail }), 28 | { status: 500 } 29 | ); 30 | } 31 | 32 | return new Response( 33 | JSON.stringify(prediction), 34 | { status: 201 } 35 | ); 36 | } -------------------------------------------------------------------------------- /src/components/Footer.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-color: rgb(0, 0, 0); 7 | --background-start-color: #f3f4f6; 8 | --background-end-color: #ffffff; 9 | --primary-color: #4f46e5; 10 | --hover-color: #6b63ff; 11 | --title-hover-color: #f3f87a; 12 | } 13 | 14 | @media (prefers-color-scheme: dark) { 15 | :root { 16 | --foreground-color: rgb(255, 255, 255); 17 | --background-start-color: #111827; 18 | --background-end-color: #1f2937; 19 | --primary-color: #7c3aed; 20 | --hover-color: #9561e2; 21 | --title-hover-color: #f3f87a; 22 | } 23 | } 24 | 25 | footer { 26 | background-color: var(--primary-color); 27 | color: white; 28 | } 29 | 30 | footer a { 31 | color: white; 32 | text-decoration: none; 33 | } 34 | 35 | footer a:hover { 36 | text-decoration: underline; 37 | } 38 | 39 | .footer-container { 40 | background-color: #4f46e5; 41 | color: white; 42 | padding: 1rem 0; 43 | } 44 | 45 | .footer-box { 46 | text-align: center; 47 | } 48 | 49 | .footer-box p { 50 | margin: 0; 51 | } 52 | 53 | .hehe { 54 | text-decoration: none; 55 | } -------------------------------------------------------------------------------- /src/components/Navbar.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import './Navbar.css' 3 | import Image from "next/image"; 4 | 5 | export default function Navbar() { 6 | return ( 7 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Navbar.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-color: rgb(0, 0, 0); 7 | --background-start-color: #f3f4f6; 8 | --background-end-color: #ffffff; 9 | --primary-color: #4f46e5; 10 | --hover-color: #6b63ff; 11 | --title-hover-color: #f3f87a; 12 | } 13 | 14 | @media (prefers-color-scheme: dark) { 15 | :root { 16 | --foreground-color: rgb(255, 255, 255); 17 | --background-start-color: #111827; 18 | --background-end-color: #1f2937; 19 | --primary-color: #7c3aed; 20 | --hover-color: #9561e2; 21 | --title-hover-color: #f3f87a; 22 | } 23 | } 24 | 25 | .titleb { 26 | display: flex; 27 | align-items: center; 28 | text-decoration: none; 29 | color: white; 30 | font-size: 2rem; 31 | font-weight: bold; 32 | } 33 | 34 | .titleb:hover { 35 | opacity: 0.8; 36 | text-decoration: none; 37 | color: #f3f87a; 38 | } 39 | 40 | .button-container { 41 | display: flex; 42 | flex-direction: column; 43 | align-items: center; 44 | gap: 1rem; 45 | } 46 | 47 | .buttons { 48 | color: white; 49 | text-decoration: none; 50 | padding: 0.5rem 1rem; 51 | border-radius: 0.25rem; 52 | transition: background-color 0.3s ease; 53 | } 54 | 55 | .buttons:hover { 56 | background-color: #4f46e5; 57 | text-decoration: none; 58 | color: #f3f87a; 59 | } 60 | 61 | nav{ 62 | background-color: var(--primary-color); 63 | color: white; 64 | padding: 1rem; 65 | } 66 | 67 | nav a{ 68 | color: white; 69 | text-decoration: none; 70 | } 71 | 72 | nav a:hover{ 73 | text-decoration: underline; 74 | } 75 | 76 | @media (min-width: 768px) { 77 | .button-container { 78 | flex-direction: row; 79 | } 80 | 81 | .buttons { 82 | width: 100%; 83 | } 84 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to GGReplicater 🚀 2 | 3 | ![GGReplicater Logo](https://raw.githubusercontent.com/gaureshpai/GGReplicater/main/public/logo.png) 4 | 5 | GGReplicater is a web application hosted on Vercel that utilizes Replicate AI to generate images based on user prompts. 6 | 7 | ## 🌟 Features 8 | 9 | - **Generate Images**: Input a prompt and receive an AI-generated image in response. 10 | - **Download Images**: Download the generated image with ease. 11 | - **Open Source**: GGReplicater is built on open-source technologies, encouraging collaboration and innovation. 12 | 13 | ## 🚀 Getting Started 14 | 15 | 1. **Clone the Repository:** 16 | 17 | ```bash 18 | git clone https://github.com/gaureshpai/ggreplicater.git 19 | cd ggreplicater 20 | ``` 21 | 22 | 2. **Install Dependencies:** 23 | 24 | ```bash 25 | npm install 26 | ``` 27 | 28 | 3. **Run the Application:** 29 | 30 | ```bash 31 | npm run dev 32 | ``` 33 | 34 | Open [http://localhost:3000](http://localhost:3000) in your browser to explore GGReplicater. 35 | 36 | ## 🎨 Usage 37 | 38 | Enter a prompt in the provided input field to generate an image. The application will utilize Replicate AI to generate an image based on your prompt. You can then download the generated image for your use. 39 | 40 | ## 🤝 Contributing 41 | 42 | We welcome contributions from the community! If you have ideas for improvements, new features, or bug fixes, please open an issue or submit a pull request. 43 | 44 | ## 🔧 Technologies Used 45 | 46 | - **Next.js**: The foundation for building React applications with server-side rendering. 47 | - **Replicate AI**: Advanced AI algorithms power our image generation. 48 | - **Tailwind CSS**: A utility-first CSS framework for building modern and responsive designs. 49 | 50 | ## 📄 License 51 | 52 | GGReplicater is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 53 | 54 | ## 🙌 Acknowledgments 55 | 56 | GGReplicater is made possible by the contributions of our community and the following technologies: 57 | 58 | - React 59 | - Next.js 60 | - Tailwind CSS 61 | - Replicate AI 62 | 63 | Thank you for using GGReplicater! 🎉 64 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-color: rgb(0, 0, 0); 7 | --background-start-color: #f3f4f6; 8 | --background-end-color: #ffffff; 9 | --primary-color: #4f46e5; 10 | --hover-color: #6b63ff; 11 | --title-hover-color: #f3f87a; 12 | } 13 | 14 | @media (prefers-color-scheme: dark) { 15 | :root { 16 | --foreground-color: rgb(255, 255, 255); 17 | --background-start-color: #111827; 18 | --background-end-color: #1f2937; 19 | --primary-color: #7c3aed; 20 | --hover-color: #9561e2; 21 | --title-hover-color: #f3f87a; 22 | } 23 | } 24 | 25 | body { 26 | font-family: 'Arial', sans-serif; 27 | background: linear-gradient(to right, var(--background-start-color), var(--background-end-color)); 28 | color: var(--foreground-color); 29 | margin: 0; 30 | padding: 0; 31 | box-sizing: border-box; 32 | } 33 | 34 | input:focus, 35 | button:focus { 36 | outline: none; 37 | } 38 | 39 | nav, 40 | footer { 41 | background-color: var(--primary-color); 42 | color: white; 43 | } 44 | 45 | nav a, 46 | footer a { 47 | color: white; 48 | text-decoration: none; 49 | } 50 | 51 | nav a:hover, 52 | footer a:hover { 53 | text-decoration: underline; 54 | } 55 | 56 | .button { 57 | cursor: pointer; 58 | padding: 8px 16px; 59 | border: none; 60 | border-radius: 4px; 61 | transition: background-color 0.3s ease, box-shadow 0.3s ease; 62 | } 63 | 64 | .button-link { 65 | display: inline-block; 66 | margin-right: 10px; 67 | } 68 | 69 | .button-link:last-child { 70 | margin-right: 0; 71 | } 72 | 73 | .button-link:hover { 74 | box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); 75 | } 76 | 77 | main { 78 | flex-grow: 1; 79 | display: flex; 80 | flex-direction: column; 81 | align-items: center; 82 | justify-content: center; 83 | padding: 20px; 84 | } 85 | 86 | .title-link:hover { 87 | color: var(--title-hover-color); 88 | } 89 | 90 | .titleb { 91 | display: flex; 92 | align-items: center; 93 | text-decoration: none; 94 | color: white; 95 | font-size: 2rem; 96 | font-weight: bold; 97 | } 98 | 99 | .titleb:hover { 100 | opacity: 0.8; 101 | text-decoration: none; 102 | color: #f3f87a; 103 | } 104 | 105 | .buttons { 106 | color: white; 107 | text-decoration: none; 108 | padding: 0.5rem 1rem; 109 | border-radius: 0.25rem; 110 | transition: background-color 0.3s ease; 111 | } 112 | 113 | .buttons:hover { 114 | background-color: #4f46e5; 115 | text-decoration: none; 116 | color: #f3f87a; 117 | } 118 | 119 | .button-container { 120 | display: flex; 121 | flex-direction: column; 122 | align-items: center; 123 | gap: 1rem; 124 | } 125 | 126 | .footer-container { 127 | background-color: var(--primary-color); 128 | color: white; 129 | padding: 1rem 0; 130 | } 131 | 132 | .footer-box { 133 | text-align: center; 134 | } 135 | 136 | .footer-box p { 137 | margin: 0; 138 | } 139 | 140 | @media (max-width: 767px) { 141 | .button-container { 142 | flex-direction: column; 143 | align-items: center; 144 | } 145 | 146 | .buttons { 147 | width: 100%; 148 | } 149 | } -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { useState } from "react"; 3 | import Head from "next/head"; 4 | import Image from "next/image"; 5 | import Navbar from "../components/Navbar"; 6 | import Footer from "../components/Footer"; 7 | 8 | import { Prediction } from "replicate"; 9 | const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); 10 | 11 | export default function Home() { 12 | const [prediction, setPrediction] = useState(null); 13 | const [error, setError] = useState(null); 14 | 15 | const handleSubmit = async (e: React.FormEvent) => { 16 | e.preventDefault(); 17 | 18 | const response = await fetch("/api/predictions", { 19 | method: "POST", 20 | body: new FormData(e.currentTarget), 21 | }); 22 | 23 | let prediction = await response.json(); 24 | 25 | if (response.status !== 201) { 26 | setError(prediction.detail); 27 | return; 28 | } 29 | setPrediction(prediction); 30 | 31 | while (prediction?.status !== "succeeded" && prediction?.status !== "failed") { 32 | await sleep(1000); 33 | const response = await fetch("/api/predictions/" + prediction?.id, { cache: "no-store" }); 34 | prediction = await response.json(); 35 | if (response.status !== 200) { 36 | setError(prediction.detail); 37 | return; 38 | } 39 | setPrediction(prediction); 40 | } 41 | }; 42 | 43 | const handleDownload = () => { 44 | if (prediction) { 45 | const downloadLink = document.createElement("a"); 46 | downloadLink.href = prediction.output[prediction.output.length - 1]; 47 | downloadLink.download = "generated_image.png"; 48 | downloadLink.click(); 49 | } 50 | }; 51 | 52 | return ( 53 |
54 | 55 | The AI Replicater 56 | 57 | 58 | 59 | 60 |
61 |
62 |

Generate Images

63 | 74 |
75 | 81 | 82 | 88 |
89 | 90 | {error &&
{error}
} 91 | 92 | {prediction ? ( 93 |
94 | {prediction.output && ( 95 |
96 | output 103 | 109 |
110 | )} 111 |

Status: {prediction.status}

112 |
113 | ) : null} 114 | 115 |
116 |
117 | 118 |
121 | ); 122 | } --------------------------------------------------------------------------------