├── public ├── g22.png ├── g23.png ├── p8.png └── spark.png ├── src ├── app │ ├── icon.png │ ├── api │ │ ├── auth │ │ │ └── [...nextauth] │ │ │ │ ├── route.ts │ │ │ │ └── options.ts │ │ ├── corePrompt │ │ │ └── save │ │ │ │ └── route.ts │ │ ├── interaction │ │ │ ├── delete │ │ │ │ └── route.ts │ │ │ ├── get │ │ │ │ └── route.ts │ │ │ └── save │ │ │ │ └── route.ts │ │ ├── improve │ │ │ └── route.ts │ │ └── generate │ │ │ └── route.ts │ ├── font.ts │ ├── page.tsx │ ├── Providers.tsx │ ├── layout.tsx │ ├── history │ │ ├── components │ │ │ └── Utility.tsx │ │ └── page.tsx │ ├── i │ │ └── [interactionId] │ │ │ └── page.tsx │ └── globals.css ├── types │ ├── UtilityProps.ts │ ├── ApiResponse.ts │ ├── LoginModelProps.ts │ ├── InteractionPageProps.ts │ ├── HistoryType.ts │ └── ResultProps.ts ├── lib │ ├── genAI.ts │ ├── utils.ts │ └── prisma.ts ├── constants │ ├── corePromptInputPlaceholder.ts │ └── smaples.ts ├── components │ ├── Hero.tsx │ ├── ui │ │ ├── skeleton.tsx │ │ ├── textarea.tsx │ │ ├── input.tsx │ │ ├── separator.tsx │ │ ├── tooltip.tsx │ │ ├── popover.tsx │ │ ├── avatar.tsx │ │ ├── border-beam.tsx │ │ ├── button.tsx │ │ ├── shiny-button.tsx │ │ ├── shine-border.tsx │ │ ├── dialog.tsx │ │ ├── sheet.tsx │ │ ├── select.tsx │ │ ├── dropdown-menu.tsx │ │ └── sidebar.tsx │ ├── theme-provider.tsx │ ├── UsageCount.tsx │ ├── BackgroundImage.tsx │ ├── Appbar.tsx │ ├── LoginModel.tsx │ ├── Samples.tsx │ ├── ThemeToggleButton.tsx │ ├── Footer.tsx │ ├── TypeWriter.tsx │ ├── CorePromptForm.tsx │ ├── Profile.tsx │ ├── Result.tsx │ ├── app-sidebar.tsx │ └── Main.tsx ├── hooks │ ├── useResult.ts │ ├── useTweet.ts │ ├── use-mobile.tsx │ └── useUsageTracker.ts └── context │ ├── ResultContext.tsx │ └── TweetContext.tsx ├── .vscode └── settings.json ├── prisma ├── migrations │ ├── 20250128080146_added_coreprompt │ │ └── migration.sql │ ├── migration_lock.toml │ ├── 20250519143011_added_ip_model │ │ └── migration.sql │ ├── 20250123082253_init │ │ └── migration.sql │ ├── 20250125060127_changed_interaction_id_type │ │ └── migration.sql │ └── 20250123115123_added_interaction_model │ │ └── migration.sql └── schema.prisma ├── next.config.ts ├── postcss.config.mjs ├── eslint.config.mjs ├── components.json ├── .gitignore ├── tsconfig.json ├── README.md ├── package.json └── tailwind.config.ts /public/g22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fardeen26/flick-ai/HEAD/public/g22.png -------------------------------------------------------------------------------- /public/g23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fardeen26/flick-ai/HEAD/public/g23.png -------------------------------------------------------------------------------- /public/p8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fardeen26/flick-ai/HEAD/public/p8.png -------------------------------------------------------------------------------- /public/spark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fardeen26/flick-ai/HEAD/public/spark.png -------------------------------------------------------------------------------- /src/app/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fardeen26/flick-ai/HEAD/src/app/icon.png -------------------------------------------------------------------------------- /src/types/UtilityProps.ts: -------------------------------------------------------------------------------- 1 | export interface UtilityProps { 2 | aiResponse: string, 3 | id: string 4 | } -------------------------------------------------------------------------------- /src/types/ApiResponse.ts: -------------------------------------------------------------------------------- 1 | export interface ApiResponse { 2 | success: boolean; 3 | message: string; 4 | }; -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "crackboard.sessionKey": "31ab2416049d4fb530c581415028d6c438706bdb65d39c16aeca972c20abbf96" 3 | } -------------------------------------------------------------------------------- /src/types/LoginModelProps.ts: -------------------------------------------------------------------------------- 1 | export interface LoginModelProps { 2 | onClose: () => void, 3 | showLoginModal: boolean 4 | } -------------------------------------------------------------------------------- /prisma/migrations/20250128080146_added_coreprompt/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE "User" ADD COLUMN "corePrompt" TEXT; 3 | -------------------------------------------------------------------------------- /src/types/InteractionPageProps.ts: -------------------------------------------------------------------------------- 1 | export interface InteractionPageProps { 2 | params: Promise<{ 3 | interactionId: string 4 | }> 5 | } -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (e.g., Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /src/lib/genAI.ts: -------------------------------------------------------------------------------- 1 | import { GoogleGenerativeAI } from '@google/generative-ai'; 2 | 3 | export const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY as string); -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | }; 6 | 7 | export default nextConfig; 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/constants/corePromptInputPlaceholder.ts: -------------------------------------------------------------------------------- 1 | export const corePromptPlaceholder = `e.g. Make tweets engaging, concise, and goal-aligned. Use multi-lines, relevant emojis, and a [tone, e.g., professional, casual].`; -------------------------------------------------------------------------------- /src/constants/smaples.ts: -------------------------------------------------------------------------------- 1 | export const samples = [ 2 | "Coding all night again. Need coffee.", 3 | "I think feb I gotta take some health time off", 4 | "I love reading about human psychology" 5 | ] -------------------------------------------------------------------------------- /src/app/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import NextAuth from 'next-auth/next'; 2 | import { authOptions } from './options'; 3 | 4 | const handler = NextAuth(authOptions); 5 | 6 | export { handler as GET, handler as POST }; -------------------------------------------------------------------------------- /src/components/Hero.tsx: -------------------------------------------------------------------------------- 1 | export default function Hero() { 2 | return ( 3 |
4 |

What can I help you refine?

5 |
6 | ) 7 | } -------------------------------------------------------------------------------- /prisma/migrations/20250519143011_added_ip_model/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "UserIp" ( 3 | "id" TEXT NOT NULL, 4 | "ipAddress" TEXT NOT NULL, 5 | 6 | CONSTRAINT "UserIp_pkey" PRIMARY KEY ("id") 7 | ); 8 | -------------------------------------------------------------------------------- /src/app/font.ts: -------------------------------------------------------------------------------- 1 | import { Inter } from "next/font/google"; 2 | 3 | const inter_init = Inter({ 4 | subsets: ["latin"], 5 | display: "swap", 6 | }) 7 | 8 | const fontInter = inter_init.className; 9 | export default fontInter; -------------------------------------------------------------------------------- /src/types/HistoryType.ts: -------------------------------------------------------------------------------- 1 | export interface HistoryType { 2 | id: string, 3 | userPrompt: string, 4 | aiResponse: string, 5 | mood: string | null, 6 | action: string | null, 7 | createdAt: Date, 8 | userId: number 9 | } -------------------------------------------------------------------------------- /src/types/ResultProps.ts: -------------------------------------------------------------------------------- 1 | export interface ResultProps { 2 | improvePrompt: string; 3 | isImprovingField: boolean; 4 | setImprovePrompt: (improvePrompt: string) => void; 5 | handleRegenerate: () => void; 6 | copyToClipboard: () => void; 7 | saveInteraction: () => void 8 | } -------------------------------------------------------------------------------- /src/lib/prisma.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client' 2 | 3 | const globalForPrisma = global as unknown as { prisma: PrismaClient } 4 | 5 | export const prisma = globalForPrisma.prisma || new PrismaClient() 6 | 7 | if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma -------------------------------------------------------------------------------- /prisma/migrations/20250123082253_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "User" ( 3 | "id" SERIAL NOT NULL, 4 | "email" TEXT NOT NULL, 5 | "name" TEXT, 6 | "profileImage" TEXT, 7 | 8 | CONSTRAINT "User_pkey" PRIMARY KEY ("id") 9 | ); 10 | 11 | -- CreateIndex 12 | CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); 13 | -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /src/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { ThemeProvider as NextThemesProvider } from "next-themes" 5 | 6 | export function ThemeProvider({ 7 | children, 8 | ...props 9 | }: React.ComponentProps) { 10 | return {children} 11 | } 12 | -------------------------------------------------------------------------------- /src/hooks/useResult.ts: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useContext } from "react"; 4 | import { ResultContext } from "@/context/ResultContext"; 5 | 6 | export default function useResult() { 7 | const context = useContext(ResultContext); 8 | if (!context) { 9 | throw new Error('useResult must be used within a ResultProvider'); 10 | } 11 | return context; 12 | } 13 | -------------------------------------------------------------------------------- /src/hooks/useTweet.ts: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useContext } from 'react'; 4 | import { TweetContext } from "@/context/TweetContext"; 5 | 6 | export default function useTweet() { 7 | const context = useContext(TweetContext); 8 | 9 | if (!context) { 10 | throw new Error('useTweet must be used within a TweetProvider'); 11 | } 12 | 13 | return context; 14 | } -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /prisma/migrations/20250125060127_changed_interaction_id_type/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - The primary key for the `Interaction` table will be changed. If it partially fails, the table could be left without primary key constraint. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE "Interaction" DROP CONSTRAINT "Interaction_pkey", 9 | ALTER COLUMN "id" DROP DEFAULT, 10 | ALTER COLUMN "id" SET DATA TYPE TEXT, 11 | ADD CONSTRAINT "Interaction_pkey" PRIMARY KEY ("id"); 12 | DROP SEQUENCE "Interaction_id_seq"; 13 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /src/context/ResultContext.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { createContext, useState } from "react"; 4 | 5 | type ResultContextType = { 6 | result: string; 7 | setResult: (result: string) => void; 8 | }; 9 | 10 | export const ResultContext = createContext(undefined); 11 | 12 | export default function ResultProvider({ children }: { children: React.ReactNode }) { 13 | const [result, setResult] = useState(''); 14 | return {children}; 15 | } -------------------------------------------------------------------------------- /src/components/UsageCount.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { MAX_FREE_USES, useUsageTracker } from "@/hooks/useUsageTracker"; 4 | import { useSession } from "next-auth/react"; 5 | import { CgInfinity } from "react-icons/cg"; 6 | 7 | export default function UsageCount() { 8 | const { usageCount } = useUsageTracker(); 9 | const { data: session } = useSession() 10 | return ( 11 |

Credit Left:  {session?.user ? : MAX_FREE_USES - usageCount}

12 | ) 13 | } -------------------------------------------------------------------------------- /src/context/TweetContext.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { createContext, useState } from "react"; 4 | 5 | type TweetContextType = { 6 | tweet: string; 7 | setTweet: (tweet: string) => void; 8 | }; 9 | 10 | export const TweetContext = createContext(undefined); 11 | 12 | export default function TweetProvider({ children }: 13 | { children: React.ReactNode } 14 | ) { 15 | const [tweet, setTweet] = useState(''); 16 | return 17 | {children} 18 | ; 19 | }; -------------------------------------------------------------------------------- /prisma/migrations/20250123115123_added_interaction_model/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "Interaction" ( 3 | "id" SERIAL NOT NULL, 4 | "userPrompt" TEXT NOT NULL, 5 | "aiResponse" TEXT NOT NULL, 6 | "mood" TEXT, 7 | "action" TEXT, 8 | "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, 9 | "userId" INTEGER NOT NULL, 10 | 11 | CONSTRAINT "Interaction_pkey" PRIMARY KEY ("id") 12 | ); 13 | 14 | -- AddForeignKey 15 | ALTER TABLE "Interaction" ADD CONSTRAINT "Interaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; 16 | -------------------------------------------------------------------------------- /src/hooks/use-mobile.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /.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.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 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 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Appbar from "@/components/Appbar"; 2 | import Footer from "@/components/Footer"; 3 | import Hero from "@/components/Hero"; 4 | import Main from "@/components/Main"; 5 | import Samples from "@/components/Samples"; 6 | 7 | export default function Home() { 8 | return ( 9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |