├── .eslintrc.json
├── .gitignore
├── README.md
├── app
├── (marketing)
│ ├── layout.tsx
│ ├── page.tsx
│ └── terminal.tsx
├── api
│ └── generate-code
│ │ └── route.ts
├── favicon.ico
├── fonts
│ ├── GeistMonoVF.woff
│ └── GeistVF.woff
├── generate
│ └── page.tsx
├── globals.css
├── layout.tsx
└── opengraph-image.png
├── components.json
├── components
├── codeDisplay.tsx
├── promptForm.tsx
├── spinner.tsx
└── ui
│ ├── button.tsx
│ ├── scroll-area.tsx
│ ├── select.tsx
│ ├── textarea.tsx
│ ├── toast.tsx
│ └── toaster.tsx
├── hooks
└── use-toast.ts
├── lib
└── utils.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
├── agicode-vf.png
├── favicon.ico
├── hero.webp
├── nebius logo.png
└── opengraph-image.png
├── tailwind.config.ts
└── tsconfig.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["next/core-web-vitals", "next/typescript"]
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 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CRAZY CODER 🚀
2 |
3 | 
4 |
5 | Built with ❤️ using [Nebius](https://nebius.com/studio/inference?utm_medium=cpc&utm_source=crazyCoder&utm_campaign=Network_en_all_lgen_inference_cloud&utm_term=crazyCoder)
6 |
7 | ---
8 |
9 | **CRAZY CODER** is the hottest new way to write code! With the power of open-source AI models and the simplicity of natural language, you can go from idea to implementation in seconds.
10 |
11 | ---
12 |
13 | ## 🌟 Key Features
14 |
15 | ### 🔥 **The Hottest Programming Language is English**
16 | Write your ideas, pseudo-code, or simple instructions in English, and let the AI do the rest. Forget syntax and debugging headaches—focus on what matters: your creativity.
17 |
18 | ### ⚡ **Code Fast Now**
19 | No need to learn complex languages or frameworks. Get your program up and running in seconds using powerful open-source AI models like **Qwen**, **Llama**, **Mixtral**, and more.
20 |
21 | ---
22 |
23 | ## 🌐 Leverage Open Source
24 |
25 | - **Powerful Models**: Utilize cutting-edge coding models like **Qwen-2.5-Coder-32B**, which rivals GPT-4 in performance.
26 | - **Open for All**: These models are available to everyone for rapid prototyping and development.
27 |
28 | ---
29 |
30 | ## 🎨 Experiment Freely
31 | Harness the power of the **Nebius AI Studio** to experiment with different models at **low cost**. Create, test, and refine your applications in a flexible environment.
32 |
33 | 🔗 Learn more about Nebius AI Studio [here](https://nebius.com/studio/inference?utm_medium=cpc&utm_source=crazyCoder&utm_campaign=Network_en_all_lgen_inference_cloud&utm_term=crazyCoder).
34 |
35 | ---
36 |
37 | ## 💡 Want to Replicate This App?
38 | The **CRAZY CODER** project is open source!
39 | You can clone the repository and deploy it easily to **Vercel** or your favorite platform.
40 |
41 | ### 🚀 View the Code on GitHub
42 | - [Clone the repository](#) and start building today!
43 |
44 | ---
45 |
46 | ### ✨ Build Your Next Big Idea with CRAZY CODER!
47 | With **Nebius** and cutting-edge open-source models, the possibilities are endless. Start coding smarter, faster, and more creatively than ever before.
48 |
49 | ---
50 |
51 | ### 📜 License
52 |
53 | This project is licensed under the MIT License.
54 |
--------------------------------------------------------------------------------
/app/(marketing)/layout.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import Link from 'next/link';
4 | import { CircleIcon } from 'lucide-react';
5 |
6 | function Header() {
7 | return (
8 |
31 | );
32 | }
33 |
34 | export default function Layout({ children }: { children: React.ReactNode }) {
35 | return (
36 |
37 |
38 | {children}
39 |
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/app/(marketing)/page.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from '@/components/ui/button';
2 | import { Computer, ArrowRight, FlaskConical, PackageOpen } from 'lucide-react';
3 | import { Terminal } from './terminal';
4 |
5 | export default function HomePage() {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 | The hottest new programming
14 | language is English
15 |
16 |
17 | Code your program in seconds using powerful open source AI
18 | models. Leverage Qwen, Llama, Mixtral, and more to build your next big idea.
19 |
20 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Ship Faster
48 |
49 |
50 | Code is no longer a barrier to entry. Think, write the pseudo code and let the AI do the rest.
51 |
52 |
53 |
54 |
55 |
56 |
59 |
60 |
61 | Leverage Open Source
62 |
63 |
64 | Open source coding models are extremely powerful. Qwen-2.5-Coder-32B for example is on par with GPT-4o.
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Experiment Freely
76 |
77 |
78 | On the Nebius AI Studio, you can experiment with different models at a low cost.
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | Want to replicate this app?
92 |
93 |
94 | The code is open source and available on GitHub.
95 | You can clone the repository and deploy it to Vercel with ease.
96 |
97 |
98 |
109 |
110 |
111 |
112 |
113 | );
114 | }
115 |
--------------------------------------------------------------------------------
/app/(marketing)/terminal.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { useState } from 'react';
4 | import { Copy, Check } from 'lucide-react';
5 | import Image from 'next/image';
6 |
7 | export function Terminal() {
8 | const [copied, setCopied] = useState(false);
9 |
10 | const copyToClipboard = () => {
11 | const terminalSteps = [
12 | 'import { createOpenAI } from "@ai-sdk/openai";',
13 | 'import { generateText } from "ai";',
14 | 'const openai = createOpenAI({',
15 | ' apiKey: process.env.NEBIUS_API_KEY,',
16 | ' baseURL: process.env.NEBIUS_BASE_URL,',
17 | '});',
18 | 'const model = openai("Qwen/Qwen2.5-Coder-32B-Instruct");',
19 | 'const { text } = await generateText({',
20 | ' model,',
21 | ' prompt: "generate a function that returns future date of birth of AGI",',
22 | '});',
23 | ];
24 | navigator.clipboard.writeText(terminalSteps.join('\n'));
25 | setCopied(true);
26 | setTimeout(() => setCopied(false), 2000);
27 | };
28 |
29 | return (
30 |
31 |
32 |
33 |
38 |
49 |
50 |
51 |
59 |
60 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/app/api/generate-code/route.ts:
--------------------------------------------------------------------------------
1 | import { NextRequest, NextResponse } from 'next/server'
2 | import { createOpenAI } from "@ai-sdk/openai";
3 | import { generateText } from "ai";
4 |
5 | const openai = createOpenAI({
6 | apiKey: process.env.NEBIUS_API_KEY,
7 | baseURL: process.env.NEBIUS_BASE_URL,
8 | })
9 |
10 | export async function POST(req: NextRequest) {
11 | const { prompt, language, modelName } = await req.json()
12 |
13 | try {
14 | const model = openai(modelName);
15 |
16 | const { text } = await generateText({
17 | model,
18 | prompt: `Generate ${language} code for the following prompt: ${prompt}.`,
19 | });
20 |
21 | return NextResponse.json({ code: text })
22 | } catch (error) {
23 | console.error('Error generating code:', error)
24 | return NextResponse.json({ error: 'Failed to generate code' }, { status: 500 })
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/app/favicon.ico
--------------------------------------------------------------------------------
/app/fonts/GeistMonoVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/app/fonts/GeistMonoVF.woff
--------------------------------------------------------------------------------
/app/fonts/GeistVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/app/fonts/GeistVF.woff
--------------------------------------------------------------------------------
/app/generate/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState } from 'react'
4 | import PromptForm from '@/components/promptForm'
5 | import CodeDisplay from '@/components/codeDisplay'
6 | import { Toaster } from "@/components/ui/toaster"
7 | import { Spinner } from "@/components/spinner"
8 | import Link from 'next/link';
9 | import { CircleIcon } from 'lucide-react';
10 |
11 | function Header() {
12 | return (
13 |
37 | );
38 | }
39 |
40 | export default function GeneratePage() {
41 | const [code, setCode] = useState('')
42 | const [isLoading, setIsLoading] = useState(false)
43 |
44 | const handleSubmit = async (prompt: string, language: string, model: string) => {
45 | setIsLoading(true)
46 | try {
47 | const response = await fetch('/api/generate-code', {
48 | method: 'POST',
49 | headers: {
50 | 'Content-Type': 'application/json',
51 | },
52 | body: JSON.stringify({ prompt, language, modelName: model }),
53 | })
54 |
55 | if (!response.ok) {
56 | throw new Error('Failed to generate code')
57 | }
58 |
59 | const data = await response.json()
60 | setCode(data.code)
61 | } catch (error) {
62 | console.error('Error generating code:', error)
63 | } finally {
64 | setIsLoading(false)
65 | }
66 | }
67 |
68 | return (
69 |
70 |
71 |
72 |
73 |
76 |
77 | {isLoading ? (
78 |
79 | ) : (
80 |
81 | )}
82 |
83 |
84 |
85 |
86 |
87 | )
88 | }
89 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | body {
6 | font-family: Arial, Helvetica, sans-serif;
7 | }
8 |
9 | @layer utilities {
10 | .text-balance {
11 | text-wrap: balance;
12 | }
13 | }
14 |
15 | @layer base {
16 | :root {
17 | --background: 0 0% 100%;
18 | --foreground: 0 0% 3.9%;
19 | --card: 0 0% 100%;
20 | --card-foreground: 0 0% 3.9%;
21 | --popover: 0 0% 100%;
22 | --popover-foreground: 0 0% 3.9%;
23 | --primary: 0 0% 9%;
24 | --primary-foreground: 0 0% 98%;
25 | --secondary: 0 0% 96.1%;
26 | --secondary-foreground: 0 0% 9%;
27 | --muted: 0 0% 96.1%;
28 | --muted-foreground: 0 0% 45.1%;
29 | --accent: 0 0% 96.1%;
30 | --accent-foreground: 0 0% 9%;
31 | --destructive: 0 84.2% 60.2%;
32 | --destructive-foreground: 0 0% 98%;
33 | --border: 0 0% 89.8%;
34 | --input: 0 0% 89.8%;
35 | --ring: 0 0% 3.9%;
36 | --chart-1: 12 76% 61%;
37 | --chart-2: 173 58% 39%;
38 | --chart-3: 197 37% 24%;
39 | --chart-4: 43 74% 66%;
40 | --chart-5: 27 87% 67%;
41 | --radius: 0.5rem;
42 | }
43 | .dark {
44 | --background: 0 0% 3.9%;
45 | --foreground: 0 0% 98%;
46 | --card: 0 0% 3.9%;
47 | --card-foreground: 0 0% 98%;
48 | --popover: 0 0% 3.9%;
49 | --popover-foreground: 0 0% 98%;
50 | --primary: 0 0% 98%;
51 | --primary-foreground: 0 0% 9%;
52 | --secondary: 0 0% 14.9%;
53 | --secondary-foreground: 0 0% 98%;
54 | --muted: 0 0% 14.9%;
55 | --muted-foreground: 0 0% 63.9%;
56 | --accent: 0 0% 14.9%;
57 | --accent-foreground: 0 0% 98%;
58 | --destructive: 0 62.8% 30.6%;
59 | --destructive-foreground: 0 0% 98%;
60 | --border: 0 0% 14.9%;
61 | --input: 0 0% 14.9%;
62 | --ring: 0 0% 83.1%;
63 | --chart-1: 220 70% 50%;
64 | --chart-2: 160 60% 45%;
65 | --chart-3: 30 80% 55%;
66 | --chart-4: 280 65% 60%;
67 | --chart-5: 340 75% 55%;
68 | }
69 | }
70 |
71 | @layer base {
72 | * {
73 | @apply border-border;
74 | }
75 | body {
76 | @apply bg-background text-foreground;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import './globals.css';
2 | import type { Metadata, Viewport } from 'next';
3 | import { Manrope } from 'next/font/google';
4 | import { Analytics } from "@vercel/analytics/react"
5 |
6 | export const metadata: Metadata = {
7 | title: 'Crazy Coder',
8 | description: 'An AI Coder Powered by Powerful Open Source Models',
9 | metadataBase: new URL('https://code.lycee.ai'),
10 | };
11 |
12 | export const viewport: Viewport = {
13 | maximumScale: 1,
14 | };
15 |
16 | const manrope = Manrope({ subsets: ['latin'] });
17 |
18 | export default function RootLayout({
19 | children,
20 | }: {
21 | children: React.ReactNode;
22 | }) {
23 |
24 | return (
25 |
29 |
30 | {children}
31 |
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/app/opengraph-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/app/opengraph-image.png
--------------------------------------------------------------------------------
/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": "app/globals.css",
9 | "baseColor": "neutral",
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 | }
--------------------------------------------------------------------------------
/components/codeDisplay.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import ReactMarkdown from 'react-markdown'
4 | import rehypeRaw from 'rehype-raw'
5 | import remarkGfm from 'remark-gfm'
6 | import { ScrollArea } from "@/components/ui/scroll-area"
7 |
8 | interface CodeDisplayProps {
9 | code: string
10 | }
11 |
12 | export default function CodeDisplay({ code }: CodeDisplayProps) {
13 | return (
14 |
15 |
16 |
24 |
25 | {children}
26 |
27 |
28 | ) : (
29 |
30 | {children}
31 |
32 | )
33 | },
34 | }}
35 | >
36 | {code}
37 |
38 |
39 |
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/components/promptForm.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState } from 'react'
4 | import { Button } from "@/components/ui/button"
5 | import { Textarea } from "@/components/ui/textarea"
6 | import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
7 | import { useToast } from "@/hooks/use-toast"
8 |
9 | const languages = [
10 | 'Python',
11 | 'JavaScript',
12 | 'TypeScript',
13 | 'C',
14 | 'C++',
15 | 'Java',
16 | 'Go',
17 | 'Ruby',
18 | 'VBA',
19 | 'DAX',
20 | 'PowerShell'
21 | ];
22 |
23 |
24 | const models = [
25 |
26 | 'Qwen/Qwen2.5-Coder-32B-Instruct',
27 | 'Qwen/Qwen2.5-72B-Instruct',
28 | 'meta-llama/Meta-Llama-3.1-405B-Instruct',
29 | 'deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct',
30 | 'meta-llama/Meta-Llama-3.1-70B-Instruct',
31 | 'Qwen/Qwen2.5-Coder-7B',
32 | ]
33 |
34 | interface PromptFormProps {
35 | onSubmit: (prompt: string, language: string, model: string) => Promise
36 | isLoading: boolean
37 | }
38 |
39 | export default function PromptForm({ onSubmit, isLoading }: PromptFormProps) {
40 | const [prompt, setPrompt] = useState('')
41 | const [language, setLanguage] = useState(languages[0])
42 | const [model, setModel] = useState(models[0])
43 | const { toast } = useToast()
44 |
45 | const handleSubmit = async (e: React.FormEvent) => {
46 | e.preventDefault()
47 | if (!prompt) {
48 | toast({
49 | title: "Error",
50 | description: "Please enter a prompt.",
51 | variant: "destructive",
52 | })
53 | return
54 | }
55 | try {
56 | await onSubmit(prompt, language, model)
57 | } catch (error) {
58 | console.error('Error generating code:', error)
59 | toast({
60 | title: "Error",
61 | description: "Failed to generate code. Please try again.",
62 | variant: "destructive",
63 | })
64 | }
65 | }
66 |
67 | return (
68 |
103 | )
104 | }
105 |
--------------------------------------------------------------------------------
/components/spinner.tsx:
--------------------------------------------------------------------------------
1 | import { Loader2 } from 'lucide-react'
2 |
3 | export function Spinner() {
4 | return (
5 |
6 |
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { Slot } from "@radix-ui/react-slot"
3 | import { cva, type VariantProps } from "class-variance-authority"
4 |
5 | import { cn } from "@/lib/utils"
6 |
7 | const buttonVariants = cva(
8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
9 | {
10 | variants: {
11 | variant: {
12 | default:
13 | "bg-primary text-primary-foreground shadow hover:bg-primary/90",
14 | destructive:
15 | "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
16 | outline:
17 | "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
18 | secondary:
19 | "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
20 | ghost: "hover:bg-accent hover:text-accent-foreground",
21 | link: "text-primary underline-offset-4 hover:underline",
22 | },
23 | size: {
24 | default: "h-9 px-4 py-2",
25 | sm: "h-8 rounded-md px-3 text-xs",
26 | lg: "h-10 rounded-md px-8",
27 | icon: "h-9 w-9",
28 | },
29 | },
30 | defaultVariants: {
31 | variant: "default",
32 | size: "default",
33 | },
34 | }
35 | )
36 |
37 | export interface ButtonProps
38 | extends React.ButtonHTMLAttributes,
39 | VariantProps {
40 | asChild?: boolean
41 | }
42 |
43 | const Button = React.forwardRef(
44 | ({ className, variant, size, asChild = false, ...props }, ref) => {
45 | const Comp = asChild ? Slot : "button"
46 | return (
47 |
52 | )
53 | }
54 | )
55 | Button.displayName = "Button"
56 |
57 | export { Button, buttonVariants }
58 |
--------------------------------------------------------------------------------
/components/ui/scroll-area.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const ScrollArea = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
17 |
18 | {children}
19 |
20 |
21 |
22 |
23 | ))
24 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25 |
26 | const ScrollBar = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, orientation = "vertical", ...props }, ref) => (
30 |
43 |
44 |
45 | ))
46 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47 |
48 | export { ScrollArea, ScrollBar }
49 |
--------------------------------------------------------------------------------
/components/ui/select.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SelectPrimitive from "@radix-ui/react-select"
5 | import { Check, ChevronDown, ChevronUp } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Select = SelectPrimitive.Root
10 |
11 | const SelectGroup = SelectPrimitive.Group
12 |
13 | const SelectValue = SelectPrimitive.Value
14 |
15 | const SelectTrigger = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, children, ...props }, ref) => (
19 | span]:line-clamp-1",
23 | className
24 | )}
25 | {...props}
26 | >
27 | {children}
28 |
29 |
30 |
31 |
32 | ))
33 | SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
34 |
35 | const SelectScrollUpButton = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 |
48 |
49 | ))
50 | SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
51 |
52 | const SelectScrollDownButton = React.forwardRef<
53 | React.ElementRef,
54 | React.ComponentPropsWithoutRef
55 | >(({ className, ...props }, ref) => (
56 |
64 |
65 |
66 | ))
67 | SelectScrollDownButton.displayName =
68 | SelectPrimitive.ScrollDownButton.displayName
69 |
70 | const SelectContent = React.forwardRef<
71 | React.ElementRef,
72 | React.ComponentPropsWithoutRef
73 | >(({ className, children, position = "popper", ...props }, ref) => (
74 |
75 |
86 |
87 |
94 | {children}
95 |
96 |
97 |
98 |
99 | ))
100 | SelectContent.displayName = SelectPrimitive.Content.displayName
101 |
102 | const SelectLabel = React.forwardRef<
103 | React.ElementRef,
104 | React.ComponentPropsWithoutRef
105 | >(({ className, ...props }, ref) => (
106 |
111 | ))
112 | SelectLabel.displayName = SelectPrimitive.Label.displayName
113 |
114 | const SelectItem = React.forwardRef<
115 | React.ElementRef,
116 | React.ComponentPropsWithoutRef
117 | >(({ className, children, ...props }, ref) => (
118 |
126 |
127 |
128 |
129 |
130 |
131 | {children}
132 |
133 | ))
134 | SelectItem.displayName = SelectPrimitive.Item.displayName
135 |
136 | const SelectSeparator = React.forwardRef<
137 | React.ElementRef,
138 | React.ComponentPropsWithoutRef
139 | >(({ className, ...props }, ref) => (
140 |
145 | ))
146 | SelectSeparator.displayName = SelectPrimitive.Separator.displayName
147 |
148 | export {
149 | Select,
150 | SelectGroup,
151 | SelectValue,
152 | SelectTrigger,
153 | SelectContent,
154 | SelectLabel,
155 | SelectItem,
156 | SelectSeparator,
157 | SelectScrollUpButton,
158 | SelectScrollDownButton,
159 | }
160 |
--------------------------------------------------------------------------------
/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 |
18 | )
19 | })
20 | Textarea.displayName = "Textarea"
21 |
22 | export { Textarea }
23 |
--------------------------------------------------------------------------------
/components/ui/toast.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ToastPrimitives from "@radix-ui/react-toast"
5 | import { cva, type VariantProps } from "class-variance-authority"
6 | import { X } from "lucide-react"
7 |
8 | import { cn } from "@/lib/utils"
9 |
10 | const ToastProvider = ToastPrimitives.Provider
11 |
12 | const ToastViewport = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, ...props }, ref) => (
16 |
24 | ))
25 | ToastViewport.displayName = ToastPrimitives.Viewport.displayName
26 |
27 | const toastVariants = cva(
28 | "group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
29 | {
30 | variants: {
31 | variant: {
32 | default: "border bg-background text-foreground",
33 | destructive:
34 | "destructive group border-destructive bg-destructive text-destructive-foreground",
35 | },
36 | },
37 | defaultVariants: {
38 | variant: "default",
39 | },
40 | }
41 | )
42 |
43 | const Toast = React.forwardRef<
44 | React.ElementRef,
45 | React.ComponentPropsWithoutRef &
46 | VariantProps
47 | >(({ className, variant, ...props }, ref) => {
48 | return (
49 |
54 | )
55 | })
56 | Toast.displayName = ToastPrimitives.Root.displayName
57 |
58 | const ToastAction = React.forwardRef<
59 | React.ElementRef,
60 | React.ComponentPropsWithoutRef
61 | >(({ className, ...props }, ref) => (
62 |
70 | ))
71 | ToastAction.displayName = ToastPrimitives.Action.displayName
72 |
73 | const ToastClose = React.forwardRef<
74 | React.ElementRef,
75 | React.ComponentPropsWithoutRef
76 | >(({ className, ...props }, ref) => (
77 |
86 |
87 |
88 | ))
89 | ToastClose.displayName = ToastPrimitives.Close.displayName
90 |
91 | const ToastTitle = React.forwardRef<
92 | React.ElementRef,
93 | React.ComponentPropsWithoutRef
94 | >(({ className, ...props }, ref) => (
95 |
100 | ))
101 | ToastTitle.displayName = ToastPrimitives.Title.displayName
102 |
103 | const ToastDescription = React.forwardRef<
104 | React.ElementRef,
105 | React.ComponentPropsWithoutRef
106 | >(({ className, ...props }, ref) => (
107 |
112 | ))
113 | ToastDescription.displayName = ToastPrimitives.Description.displayName
114 |
115 | type ToastProps = React.ComponentPropsWithoutRef
116 |
117 | type ToastActionElement = React.ReactElement
118 |
119 | export {
120 | type ToastProps,
121 | type ToastActionElement,
122 | ToastProvider,
123 | ToastViewport,
124 | Toast,
125 | ToastTitle,
126 | ToastDescription,
127 | ToastClose,
128 | ToastAction,
129 | }
130 |
--------------------------------------------------------------------------------
/components/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { useToast } from "@/hooks/use-toast"
4 | import {
5 | Toast,
6 | ToastClose,
7 | ToastDescription,
8 | ToastProvider,
9 | ToastTitle,
10 | ToastViewport,
11 | } from "@/components/ui/toast"
12 |
13 | export function Toaster() {
14 | const { toasts } = useToast()
15 |
16 | return (
17 |
18 | {toasts.map(function ({ id, title, description, action, ...props }) {
19 | return (
20 |
21 |
22 | {title && {title}}
23 | {description && (
24 | {description}
25 | )}
26 |
27 | {action}
28 |
29 |
30 | )
31 | })}
32 |
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/hooks/use-toast.ts:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | // Inspired by react-hot-toast library
4 | import * as React from "react"
5 |
6 | import type {
7 | ToastActionElement,
8 | ToastProps,
9 | } from "@/components/ui/toast"
10 |
11 | const TOAST_LIMIT = 1
12 | const TOAST_REMOVE_DELAY = 1000000
13 |
14 | type ToasterToast = ToastProps & {
15 | id: string
16 | title?: React.ReactNode
17 | description?: React.ReactNode
18 | action?: ToastActionElement
19 | }
20 |
21 | const actionTypes = {
22 | ADD_TOAST: "ADD_TOAST",
23 | UPDATE_TOAST: "UPDATE_TOAST",
24 | DISMISS_TOAST: "DISMISS_TOAST",
25 | REMOVE_TOAST: "REMOVE_TOAST",
26 | } as const
27 |
28 | let count = 0
29 |
30 | function genId() {
31 | count = (count + 1) % Number.MAX_SAFE_INTEGER
32 | return count.toString()
33 | }
34 |
35 | type ActionType = typeof actionTypes
36 |
37 | type Action =
38 | | {
39 | type: ActionType["ADD_TOAST"]
40 | toast: ToasterToast
41 | }
42 | | {
43 | type: ActionType["UPDATE_TOAST"]
44 | toast: Partial
45 | }
46 | | {
47 | type: ActionType["DISMISS_TOAST"]
48 | toastId?: ToasterToast["id"]
49 | }
50 | | {
51 | type: ActionType["REMOVE_TOAST"]
52 | toastId?: ToasterToast["id"]
53 | }
54 |
55 | interface State {
56 | toasts: ToasterToast[]
57 | }
58 |
59 | const toastTimeouts = new Map>()
60 |
61 | const addToRemoveQueue = (toastId: string) => {
62 | if (toastTimeouts.has(toastId)) {
63 | return
64 | }
65 |
66 | const timeout = setTimeout(() => {
67 | toastTimeouts.delete(toastId)
68 | dispatch({
69 | type: "REMOVE_TOAST",
70 | toastId: toastId,
71 | })
72 | }, TOAST_REMOVE_DELAY)
73 |
74 | toastTimeouts.set(toastId, timeout)
75 | }
76 |
77 | export const reducer = (state: State, action: Action): State => {
78 | switch (action.type) {
79 | case "ADD_TOAST":
80 | return {
81 | ...state,
82 | toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
83 | }
84 |
85 | case "UPDATE_TOAST":
86 | return {
87 | ...state,
88 | toasts: state.toasts.map((t) =>
89 | t.id === action.toast.id ? { ...t, ...action.toast } : t
90 | ),
91 | }
92 |
93 | case "DISMISS_TOAST": {
94 | const { toastId } = action
95 |
96 | // ! Side effects ! - This could be extracted into a dismissToast() action,
97 | // but I'll keep it here for simplicity
98 | if (toastId) {
99 | addToRemoveQueue(toastId)
100 | } else {
101 | state.toasts.forEach((toast) => {
102 | addToRemoveQueue(toast.id)
103 | })
104 | }
105 |
106 | return {
107 | ...state,
108 | toasts: state.toasts.map((t) =>
109 | t.id === toastId || toastId === undefined
110 | ? {
111 | ...t,
112 | open: false,
113 | }
114 | : t
115 | ),
116 | }
117 | }
118 | case "REMOVE_TOAST":
119 | if (action.toastId === undefined) {
120 | return {
121 | ...state,
122 | toasts: [],
123 | }
124 | }
125 | return {
126 | ...state,
127 | toasts: state.toasts.filter((t) => t.id !== action.toastId),
128 | }
129 | }
130 | }
131 |
132 | const listeners: Array<(state: State) => void> = []
133 |
134 | let memoryState: State = { toasts: [] }
135 |
136 | function dispatch(action: Action) {
137 | memoryState = reducer(memoryState, action)
138 | listeners.forEach((listener) => {
139 | listener(memoryState)
140 | })
141 | }
142 |
143 | type Toast = Omit
144 |
145 | function toast({ ...props }: Toast) {
146 | const id = genId()
147 |
148 | const update = (props: ToasterToast) =>
149 | dispatch({
150 | type: "UPDATE_TOAST",
151 | toast: { ...props, id },
152 | })
153 | const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
154 |
155 | dispatch({
156 | type: "ADD_TOAST",
157 | toast: {
158 | ...props,
159 | id,
160 | open: true,
161 | onOpenChange: (open) => {
162 | if (!open) dismiss()
163 | },
164 | },
165 | })
166 |
167 | return {
168 | id: id,
169 | dismiss,
170 | update,
171 | }
172 | }
173 |
174 | function useToast() {
175 | const [state, setState] = React.useState(memoryState)
176 |
177 | React.useEffect(() => {
178 | listeners.push(setState)
179 | return () => {
180 | const index = listeners.indexOf(setState)
181 | if (index > -1) {
182 | listeners.splice(index, 1)
183 | }
184 | }
185 | }, [state])
186 |
187 | return {
188 | ...state,
189 | toast,
190 | dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
191 | }
192 | }
193 |
194 | export { useToast, toast }
195 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {};
3 |
4 | export default nextConfig;
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "crazy-coder",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@ai-sdk/openai": "^1.0.4",
13 | "@nanostores/react": "github:ai/react",
14 | "@radix-ui/react-scroll-area": "^1.2.1",
15 | "@radix-ui/react-select": "^2.1.2",
16 | "@radix-ui/react-slot": "^1.1.0",
17 | "@radix-ui/react-toast": "^1.2.2",
18 | "@vercel/analytics": "^1.4.1",
19 | "ai": "^4.0.4",
20 | "class-variance-authority": "^0.7.0",
21 | "clsx": "^2.1.1",
22 | "lucide-react": "^0.460.0",
23 | "next": "14.2.16",
24 | "react": "^18",
25 | "react-dom": "^18",
26 | "react-markdown": "^9.0.1",
27 | "rehype-raw": "^7.0.0",
28 | "remark-gfm": "^4.0.0",
29 | "tailwind-merge": "^2.5.5",
30 | "tailwindcss-animate": "^1.0.7"
31 | },
32 | "devDependencies": {
33 | "@types/node": "^20",
34 | "@types/react": "^18",
35 | "@types/react-dom": "^18",
36 | "eslint": "^8",
37 | "eslint-config-next": "14.2.16",
38 | "postcss": "^8",
39 | "tailwindcss": "^3.4.1",
40 | "typescript": "^5"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/public/agicode-vf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/public/agicode-vf.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/public/favicon.ico
--------------------------------------------------------------------------------
/public/hero.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/public/hero.webp
--------------------------------------------------------------------------------
/public/nebius logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/public/nebius logo.png
--------------------------------------------------------------------------------
/public/opengraph-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fsndzomga/crazy-coder/8890b7fa9102e87eb20468be3f4c14946e0994dd/public/opengraph-image.png
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: Config = {
4 | darkMode: ["class"],
5 | content: [
6 | "./pages/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./components/**/*.{js,ts,jsx,tsx,mdx}",
8 | "./app/**/*.{js,ts,jsx,tsx,mdx}",
9 | ],
10 | theme: {
11 | extend: {
12 | colors: {
13 | background: 'hsl(var(--background))',
14 | foreground: 'hsl(var(--foreground))',
15 | card: {
16 | DEFAULT: 'hsl(var(--card))',
17 | foreground: 'hsl(var(--card-foreground))'
18 | },
19 | popover: {
20 | DEFAULT: 'hsl(var(--popover))',
21 | foreground: 'hsl(var(--popover-foreground))'
22 | },
23 | primary: {
24 | DEFAULT: 'hsl(var(--primary))',
25 | foreground: 'hsl(var(--primary-foreground))'
26 | },
27 | secondary: {
28 | DEFAULT: 'hsl(var(--secondary))',
29 | foreground: 'hsl(var(--secondary-foreground))'
30 | },
31 | muted: {
32 | DEFAULT: 'hsl(var(--muted))',
33 | foreground: 'hsl(var(--muted-foreground))'
34 | },
35 | accent: {
36 | DEFAULT: 'hsl(var(--accent))',
37 | foreground: 'hsl(var(--accent-foreground))'
38 | },
39 | destructive: {
40 | DEFAULT: 'hsl(var(--destructive))',
41 | foreground: 'hsl(var(--destructive-foreground))'
42 | },
43 | border: 'hsl(var(--border))',
44 | input: 'hsl(var(--input))',
45 | ring: 'hsl(var(--ring))',
46 | chart: {
47 | '1': 'hsl(var(--chart-1))',
48 | '2': 'hsl(var(--chart-2))',
49 | '3': 'hsl(var(--chart-3))',
50 | '4': 'hsl(var(--chart-4))',
51 | '5': 'hsl(var(--chart-5))'
52 | }
53 | },
54 | borderRadius: {
55 | lg: 'var(--radius)',
56 | md: 'calc(var(--radius) - 2px)',
57 | sm: 'calc(var(--radius) - 4px)'
58 | }
59 | }
60 | },
61 | plugins: [require("tailwindcss-animate")],
62 | };
63 | export default config;
64 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "noEmit": true,
8 | "esModuleInterop": true,
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "resolveJsonModule": true,
12 | "isolatedModules": true,
13 | "jsx": "preserve",
14 | "incremental": true,
15 | "plugins": [
16 | {
17 | "name": "next"
18 | }
19 | ],
20 | "paths": {
21 | "@/*": ["./*"]
22 | }
23 | },
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25 | "exclude": ["node_modules"]
26 | }
27 |
--------------------------------------------------------------------------------