├── .dockerignore ├── public ├── favicon.ico └── images │ ├── screenshot1.png │ ├── screenshot2.png │ └── screenshot3.png ├── .eslintrc.json ├── lib ├── auth-client.ts ├── utils.ts ├── db.ts ├── supabaseClient.ts ├── server │ └── session.ts ├── auth.ts └── minio.ts ├── postcss.config.mjs ├── app ├── api │ ├── auth │ │ └── [...all] │ │ │ └── route.ts │ ├── comments │ │ ├── [id] │ │ │ └── route.ts │ │ └── route.ts │ ├── project │ │ └── [id] │ │ │ └── route.ts │ └── projects │ │ ├── route.ts │ │ └── [id] │ │ └── like │ │ └── route.ts ├── project-form │ ├── layout.tsx │ ├── page.tsx │ └── _components │ │ └── Form.tsx ├── project │ └── [id] │ │ ├── layout.tsx │ │ └── page.tsx ├── edit-form │ └── [id] │ │ ├── layout.tsx │ │ ├── page.tsx │ │ └── _components │ │ └── Edit.tsx ├── auth │ ├── layout.tsx │ ├── sign-in │ │ └── page.tsx │ └── sign-up │ │ └── page.tsx ├── (ProviderWrapper) │ └── layout.tsx ├── page.tsx ├── projects │ ├── layout.tsx │ └── page.tsx ├── layout.tsx └── globals.css ├── drizzle.config.ts ├── drizzle ├── meta │ ├── _journal.json │ └── 0000_snapshot.json └── 0000_great_squadron_supreme.sql ├── components ├── ui │ ├── skeleton.tsx │ ├── label.tsx │ ├── textarea.tsx │ ├── input.tsx │ ├── sonner.tsx │ ├── spinner.tsx │ ├── popover.tsx │ ├── avatar.tsx │ ├── Spotlight.tsx │ ├── alert.tsx │ ├── button.tsx │ ├── card.tsx │ ├── dialog.tsx │ ├── form.tsx │ └── dropdown-menu.tsx ├── container.tsx ├── nothing-here.tsx ├── footer.tsx ├── project-filter.tsx ├── hero.tsx ├── BulbLoading.tsx ├── header.tsx ├── icons │ └── icons.tsx ├── project-card.tsx ├── comments.tsx ├── projects-container.tsx └── github-stats.tsx ├── next.config.mjs ├── components.json ├── .gitignore ├── tsconfig.json ├── better-auth_migrations └── 2024-10-17T12-14-00.359Z.sql ├── Dockerfile ├── schema └── index.ts ├── types └── index.ts ├── LICENSE ├── db ├── relations.ts └── schema.ts ├── README.md ├── constants └── index.ts ├── package.json └── tailwind.config.ts /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .git -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manuel-heav/built/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/images/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manuel-heav/built/HEAD/public/images/screenshot1.png -------------------------------------------------------------------------------- /public/images/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manuel-heav/built/HEAD/public/images/screenshot2.png -------------------------------------------------------------------------------- /public/images/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Manuel-heav/built/HEAD/public/images/screenshot3.png -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next/core-web-vitals", "next/typescript"], 3 | "rules": { 4 | "@typescript-eslint/no-empty-interface": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /lib/auth-client.ts: -------------------------------------------------------------------------------- 1 | import { createAuthClient } from "better-auth/react"; 2 | export const authClient = createAuthClient({ 3 | baseURL: process.env.NEXT_PUBLIC_BASE_URL, 4 | }); 5 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /app/api/auth/[...all]/route.ts: -------------------------------------------------------------------------------- 1 | import { auth } from "@/lib/auth"; 2 | import { toNextJsHandler } from "better-auth/next-js"; 3 | 4 | export const { POST, GET } = toNextJsHandler(auth); 5 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /lib/db.ts: -------------------------------------------------------------------------------- 1 | import { Pool } from "pg"; 2 | import { drizzle } from "drizzle-orm/node-postgres"; 3 | 4 | const pool = new Pool({ 5 | connectionString: process.env.DATABASE_URL, 6 | ssl: false, 7 | }); 8 | 9 | export const db = drizzle(pool); 10 | 11 | 12 | -------------------------------------------------------------------------------- /drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "drizzle-kit"; 2 | 3 | export default defineConfig({ 4 | schema: "./db/schema.ts", 5 | out: "./drizzle", 6 | dialect: "postgresql", 7 | dbCredentials: { 8 | url: process.env.DATABASE_URL!, 9 | }, 10 | }); -------------------------------------------------------------------------------- /drizzle/meta/_journal.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "7", 3 | "dialect": "postgresql", 4 | "entries": [ 5 | { 6 | "idx": 0, 7 | "version": "7", 8 | "when": 1755369915608, 9 | "tag": "0000_great_squadron_supreme", 10 | "breakpoints": true 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /lib/supabaseClient.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from "@supabase/supabase-js"; 2 | 3 | const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string; 4 | const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_KEY as string; 5 | 6 | export const supabase = createClient(supabaseUrl, supabaseKey); 7 | -------------------------------------------------------------------------------- /app/project-form/layout.tsx: -------------------------------------------------------------------------------- 1 | import Header from "@/components/header"; 2 | 3 | export default function RootLayout({ 4 | children, 5 | }: Readonly<{ 6 | children: React.ReactNode; 7 | }>) { 8 | return ( 9 |
10 | Be the first person to post under this tag. 11 |
12 |8 | Made with 💖 by{" "} 9 | 10 | 11 | The Blogrammer 12 | 13 | 14 |
15 |27 | Post your projects, gain likes, and engage with comments from 28 | developers like you. 29 |
30 | {/*
4 | A dynamic platform for developers to showcase their projects! 🌟
5 | Share your work, inspire others, and celebrate the creativity in code. 👨💻
6 |
9 | Introduction · 10 | Tech Stack · 11 | Contributing · 12 | License 13 |
14 | 15 | --- 16 | 17 | ## 🚀 Introduction 18 | 19 | **Built** is a vibrant platform tailored for developers looking to showcase their amazing projects. Whether you're creating innovative tools, building cool libraries, or designing sleek UIs, Built gives you an easy-to-use interface to share your work with the community and get recognized! 🌎✨ 20 | 21 | ## 🛠️ Tech Stack 22 | 23 | We believe in building on a solid foundation! Here’s what powers **Built**: 24 | 25 | - **Next.js 14** – For fast and scalable front-end magic 🧙 26 | - **Hono.js** – A lightweight, efficient backend framework ⚙️ 27 | - **Supabase + PostgreSQL** – For seamless database and storage needs 📦 28 | - **Better-Auth** – Ensuring smooth and secure authentication 🔐 29 | 30 | 31 | ## 👩💻 Contributing 32 | 33 | We’d love your help in making Built even better! Here’s how you can get started: 34 | 35 | 1. **Fork the repository** 🍴 – Create your own copy of the project. 36 | 2. **Create a new branch** 🌿 – Use a descriptive name for your branch (e.g., `feature/awesome-new-feature`). 37 | 3. **Make your changes** ✍️ – Add that shiny new feature or fix that pesky bug. 38 | 4. **Submit a pull request** 🔄 – Once you're done, open a pull request for review. 39 | 40 | > **Note**: Please make sure your code aligns with our coding standards. Bonus points for documenting your changes! 📚 41 | 42 | ## 📜 License 43 | 44 | Built is proudly open-source and licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. 45 | 46 | --- 47 | 48 | Feel free to reach out with questions, suggestions, or just to say hi! 😊 Happy coding, and welcome to **Built**! 🎉 49 | -------------------------------------------------------------------------------- /app/api/project/[id]/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest, NextResponse } from "next/server"; 2 | import { db } from "@/lib/db"; 3 | import { projects } from "@/db/schema"; 4 | import { and, eq } from "drizzle-orm"; 5 | import { getSession } from "@/lib/server/session"; 6 | 7 | export const runtime = "nodejs"; 8 | 9 | export async function GET(_req: NextRequest, { params }: { params: { id: string } }) { 10 | const { id } = params; 11 | try { 12 | const rows = await db.select().from(projects).where(eq(projects.id, id)); 13 | return NextResponse.json({ project: rows }); 14 | } catch (e) { 15 | if (e instanceof Error) { 16 | return NextResponse.json({ error: e.message }, { status: 400 }); 17 | } 18 | return NextResponse.json({ error: "An unknown error occurred" }, { status: 400 }); 19 | } 20 | } 21 | 22 | export async function PATCH(req: NextRequest, { params }: { params: { id: string } }) { 23 | const { id } = params; 24 | const updates = await req.json(); 25 | const session = await getSession() 26 | const userId = session?.user.id; 27 | 28 | try { 29 | await db.update(projects).set(updates).where(and(eq(projects.id, id), eq(projects.userId, userId ?? ""))); 30 | return NextResponse.json({ message: "Project updated successfully" }); 31 | } catch (e) { 32 | if (e instanceof Error) { 33 | return NextResponse.json({ error: e.message }, { status: 400 }); 34 | } 35 | return NextResponse.json({ error: "An unknown error occurred" }, { status: 400 }); 36 | } 37 | } 38 | 39 | export async function DELETE(_req: NextRequest, { params }: { params: { id: string } }) { 40 | const { id } = params; 41 | const session = await getSession() 42 | const userId = session?.user.id; 43 | 44 | try { 45 | await db.delete(projects).where(and(eq(projects.id, id), eq(projects.userId, userId ?? ""))); 46 | return NextResponse.json({ message: "Project deleted successfully" }); 47 | } catch (e) { 48 | if (e instanceof Error) { 49 | return NextResponse.json({ error: e.message }, { status: 400 }); 50 | } 51 | return NextResponse.json({ error: "An unknown error occurred" }, { status: 400 }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributesStar
53 | 54 | {session && ( 55 |163 | {body} 164 |
165 | ) 166 | }) 167 | FormMessage.displayName = "FormMessage" 168 | 169 | export { 170 | useFormField, 171 | Form, 172 | FormItem, 173 | FormLabel, 174 | FormControl, 175 | FormDescription, 176 | FormMessage, 177 | FormField, 178 | } 179 | -------------------------------------------------------------------------------- /components/icons/icons.tsx: -------------------------------------------------------------------------------- 1 | export const TelegramIcon = () => { 2 | return ( 3 |{tags.join(", ")}
94 | 95 | 96 |97 | {truncateDescription(description)} 98 |
99 | 100 | 101 |{likes}
117 |{comments}
122 | 123 |{comment.name || 'Anonymous'}
83 |{new Date(comment.createdAt).toLocaleString()}
84 |{comment.content}
85 | 92 | {replyingTo === comment.id && ( 93 |{error}
} 132 | {!session &&Please Sign In to comment.
} 133 |Edit Project
134 |{project.description}
161 |⚒️ {project.userName}
163 |74 | Error: Couldn't find the data for this repo at the moment 😔 75 |
76 |104 | {repoStats.description} 105 |
106 |