Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/app/docs/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"use client";
import React from 'react';
import { Navbar } from '@/components/layout/Navbar';
import { Footer } from '@/components/layout/Footer';
import { ChevronRight, Terminal } from 'lucide-react';

Check warning on line 5 in src/app/docs/page.tsx

View workflow job for this annotation

GitHub Actions / build-and-lint

'ChevronRight' is defined but never used
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unused import ChevronRight.

Static analysis confirms ChevronRight is imported but never used.

🧹 Proposed fix
-import { ChevronRight, Terminal } from 'lucide-react';
+import { Terminal } from 'lucide-react';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { ChevronRight, Terminal } from 'lucide-react';
import { Terminal } from 'lucide-react';
🧰 Tools
🪛 GitHub Check: build-and-lint

[warning] 5-5:
'ChevronRight' is defined but never used

🤖 Prompt for AI Agents
In `@src/app/docs/page.tsx` at line 5, Remove the unused import symbol
ChevronRight from the import statement that currently reads "import {
ChevronRight, Terminal } from 'lucide-react';" so only the used symbol Terminal
is imported; update the import to remove the unused identifier and keep
formatting consistent.


export default function DocsPage() {
const navLinks = [
{ name: 'Home', href: '/' },
{ name: 'Features', href: '/features' },
{ name: 'Examples', href: '/examples' },
{ name: 'Docs', href: '/docs' },
];

return (
<div className="min-h-screen bg-black text-white">
<Navbar links={navLinks} />
<main className="pt-32 pb-20 max-w-7xl mx-auto px-4 flex flex-col md:flex-row gap-12">

{/* Sidebar Nav */}
<aside className="w-full md:w-64 space-y-8">
<div>
<h4 className="text-xs font-bold uppercase tracking-widest text-blue-500 mb-4">Introduction</h4>
<ul className="space-y-3 text-sm text-gray-400">
<li className="text-white font-medium cursor-pointer">Getting Started</li>
<li className="hover:text-white cursor-pointer">Core Concepts</li>
<li className="hover:text-white cursor-pointer">Security</li>
</ul>
</div>
<div>
<h4 className="text-xs font-bold uppercase tracking-widest text-gray-500 mb-4">Configuration</h4>
<ul className="space-y-3 text-sm text-gray-400">
<li className="hover:text-white cursor-pointer">Custom Prompts</li>
<li className="hover:text-white cursor-pointer">Template Styles</li>
</ul>
</div>
</aside>

{/* Main Content */}
<div className="flex-1 max-w-3xl">
<h1 className="text-4xl font-bold mb-6">Getting Started</h1>
<p className="text-gray-400 text-lg mb-8 leading-relaxed">
ReadmeGenAI is designed to be plug-and-play. Our goal is to remove the friction
of writing documentation so you can focus on writing code.
</p>

<div className="space-y-12">
<section>
<h2 className="text-2xl font-bold mb-4 flex items-center gap-2">
1. Provide your URL
</h2>
<p className="text-gray-400 mb-4">
Enter your public GitHub repository URL into the generator. Ensure the repo
contains at least a main entry point (like `index.js` or `main.py`).
</p>
</section>

<section className="p-6 rounded-2xl bg-zinc-900 border border-white/5">
<div className="flex items-center gap-2 mb-4 text-blue-400 font-mono text-sm">
<Terminal size={16} />
<span>Quick Start Command</span>
</div>
<code className="text-sm bg-black p-4 rounded-lg block border border-white/10 text-zinc-300">
npx readmegenai@latest --repo [your-url]
</code>
</section>

<section>
<h2 className="text-2xl font-bold mb-4">2. AI Analysis</h2>
<p className="text-gray-400 mb-4">
Our engine uses Octokit to build a virtual file tree. This tree is passed to
Gemini 2.5 Flash with a specific context window optimized for software architecture.
</p>
</section>
</div>
</div>
</main>
<Footer />
</div>
);
}
121 changes: 121 additions & 0 deletions src/app/examples/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"use client";
import React from 'react';
import { Navbar } from '@/components/layout/Navbar';
import { Footer } from '@/components/layout/Footer';
import { Button } from '@/components/ui/Button';
import { ExternalLink, Star, Box, Cpu, Globe } from 'lucide-react';
import Link from 'next/link';

const examples = [
{
title: "Modern Web App",
repo: "nextjs-saas-template",
icon: <Globe className="text-blue-400" />,
tags: ["Next.js 16", "Tailwind", "Prisma"],
stars: "1.2k",
description: "A comprehensive README featuring deployment guides, environment variable tables, and architecture diagrams."
},
{
title: "Utility Library",
repo: "ts-utils-core",
icon: <Box className="text-emerald-400" />,
tags: ["TypeScript", "Rollup", "Vitest"],
stars: "850",
description: "Technical-heavy documentation with API references, installation via multiple package managers, and usage snippets."
},
{
title: "Backend Engine",
repo: "go-stream-processor",
icon: <Cpu className="text-purple-400" />,
tags: ["Go", "Docker", "Redis"],
stars: "2.4k",
description: "High-performance oriented README focusing on benchmark results, configuration flags, and horizontal scaling."
}
];

export default function ExamplesPage() {
const navLinks = [
{ name: 'Home', href: '/' },
{ name: 'Features', href: '/#features' },
{ name: 'Examples', href: '/examples' },
{ name: 'Docs', href: '#docs' },
];
Comment on lines +37 to +42
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Inconsistent nav links across pages and #docs vs /docs.

The navLinks array is duplicated in each page component (here and in generate/page.tsx), and the values differ: this file uses { href: '#docs' } (Line 41) while generate/page.tsx uses { href: '/docs' }. Extract a shared constant to avoid drift.

Proposed fix — shared nav links

Create a shared file, e.g. src/constants/navLinks.ts:

export const navLinks = [
  { name: 'Home', href: '/' },
  { name: 'Features', href: '/features' },
  { name: 'Examples', href: '/examples' },
  { name: 'Docs', href: '/docs' },
];

Then import it in each page instead of redefining locally.

🤖 Prompt for AI Agents
In `@src/app/examples/page.tsx` around lines 37 - 42, Replace the duplicated local
navLinks arrays with a single shared constant and fix the Docs href to '/docs':
create a new exported constant named navLinks (array of objects with name/href)
in a common module, ensure the Docs entry uses '/docs' (not '#docs'), then
import and use this navLinks constant in the page components that currently
define navLinks (e.g., the Examples and Generate page components) instead of
redefining it locally so all pages share the same source of truth.


return (
<div className="min-h-screen bg-black text-white selection:bg-white/30">
<Navbar links={navLinks} />

<main className="pt-32 pb-20 px-4">
{/* Header Section */}
<div className="max-w-5xl mx-auto text-center mb-20">
<h1 className="text-4xl md:text-6xl font-extrabold tracking-tighter mb-6">
Trusted by developers <br />
<span className="bg-clip-text text-transparent bg-linear-to-b from-white to-white/40">
to tell their story.
</span>
</h1>
<p className="text-gray-400 text-lg max-w-2xl mx-auto">
Explore how ReadmeGenAI adapts to different tech stacks and project scales to create documentation that converts visitors into users.
</p>
</div>

{/* Examples Grid */}
<div className="max-w-7xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-8">
{examples.map((example, idx) => (
<div
key={idx}
className="group relative p-8 rounded-3xl bg-zinc-950 border border-white/5 hover:border-white/20 transition-all duration-300"
>
<div className="flex justify-between items-start mb-6">
<div className="p-3 rounded-2xl bg-white/5 group-hover:bg-white/10 transition-colors">
{example.icon}
</div>
<div className="flex items-center gap-1 text-xs font-medium text-gray-500">
<Star size={12} className="fill-current text-amber-500/50" />
{example.stars}
</div>
</div>

<h3 className="text-xl font-bold mb-2 group-hover:text-blue-400 transition-colors">
{example.title}
</h3>
<p className="text-sm text-gray-500 font-mono mb-4">
{example.repo}
</p>
<p className="text-gray-400 text-sm leading-relaxed mb-6">
{example.description}
</p>

<div className="flex flex-wrap gap-2 mb-8">
{example.tags.map(tag => (
<span key={tag} className="px-2 py-1 rounded-md bg-white/5 text-[10px] font-semibold tracking-wider uppercase text-gray-400">
{tag}
</span>
))}
</div>

<Link href="/#search-input">
<Button variant="outline" className="w-full text-sm py-2">
Try this style
<ExternalLink size={14} />
</Button>
</Link>
Comment on lines +97 to +102
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Invalid HTML: <button> nested inside <a>.

Link renders an <a> tag and Button renders a <button>. Nesting interactive elements is invalid HTML and causes unpredictable behavior across browsers and assistive technologies. Either make the Button render as an anchor (e.g., pass asChild or use a styled <a>) or use router.push on the button's onClick.

🤖 Prompt for AI Agents
In `@src/app/examples/page.tsx` around lines 97 - 102, The Button is nested inside
Link (Link -> Button), which produces invalid HTML because Link renders an <a>
and Button renders a <button>; fix by making the Button render as an anchor or
by handling navigation in the Button's onClick: either update the Button
(component prop like asChild or prop to render an <a>) so it outputs an <a> and
keep it wrapped by Link, or remove Link and call router.push('/#search-input')
from an onClick handler on Button (while keeping ExternalLink icon inside).
Adjust usage around the Link, Button, and ExternalLink symbols accordingly to
avoid nesting interactive tags.

</div>
))}
</div>

{/* Bottom CTA */}
<div className="mt-32 max-w-4xl mx-auto p-12 rounded-[3rem] bg-linear-to-b from-zinc-900 to-black border border-white/5 text-center">
<h2 className="text-3xl font-bold mb-6">Ready to document your project?</h2>
<Link href="/generate">
<Button className="px-12 py-6 text-lg">
Start Generating for Free
</Button>
</Link>
</div>
</main>

<Footer />
</div>
);
}
76 changes: 76 additions & 0 deletions src/app/features/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use client";
import React from 'react';
import { Navbar } from '@/components/layout/Navbar';
import { Footer } from '@/components/layout/Footer';
import { Cpu, Globe, ShieldCheck, Sparkles, Zap, Code2 } from 'lucide-react';

const features = [
{
icon: <Sparkles className="text-blue-400" />,
title: "Gemini 2.5 Intelligence",
desc: "Leverages the latest LLM to understand not just your files, but the intent behind your code."
},
{
icon: <Globe className="text-emerald-400" />,
title: "Octokit Integration",
desc: "Seamlessly pulls repository metadata, stars, and real-time structure directly from GitHub."
},
{
icon: <ShieldCheck className="text-purple-400" />,
title: "Security First",
desc: "We never store your code. We only analyze structure and public metadata to ensure your IP stays yours."
},
{
icon: <Zap className="text-amber-400" />,
title: "Instant Generation",
desc: "Generate a complete, production-ready README in under 5 seconds—saving hours of manual writing."
},
{
icon: <Code2 className="text-pink-400" />,
title: "Framework Aware",
desc: "Automatically detects Next.js, Go, Python, and more to provide relevant setup instructions."
},
{
icon: <Cpu className="text-indigo-400" />,
title: "Custom Logic",
desc: "Uses custom-tuned prompts to ensure your documentation sounds human, professional, and clear."
}
];

export default function FeaturesPage() {
const navLinks = [
{ name: 'Home', href: '/' },
{ name: 'Features', href: '/features' },
{ name: 'Examples', href: '/examples' },
{ name: 'Docs', href: '/docs' },
];

return (
<div className="min-h-screen bg-black text-white">
<Navbar links={navLinks} />
<main className="pt-32 pb-20 px-4">
<div className="max-w-5xl mx-auto text-center mb-20">
<h1 className="text-5xl md:text-7xl font-extrabold tracking-tighter mb-6">
Documentation <br />
<span className="bg-clip-text text-transparent bg-gradient-to-b from-white to-white/40">
reimagined.
</span>
</h1>
</div>

<div className="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6">
{features.map((f, i) => (
<div key={i} className="p-8 rounded-3xl bg-zinc-950 border border-white/5 hover:border-blue-500/30 transition-all group">
<div className="mb-6 p-3 rounded-xl bg-white/5 w-fit group-hover:scale-110 transition-transform">
{f.icon}
</div>
<h3 className="text-xl font-bold mb-3">{f.title}</h3>
<p className="text-gray-400 text-sm leading-relaxed">{f.desc}</p>
</div>
))}
</div>
</main>
<Footer />
</div>
);
}
69 changes: 69 additions & 0 deletions src/app/generate/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use client";
import React, { useState } from 'react';
import { Navbar } from '@/components/layout/Navbar';
import { Footer } from '@/components/layout/Footer';
import { SearchInput } from '@/components/Generator/SearchInput';
import { MarkdownPreview } from '@/components/Generator/MarkdownPreview';

export default function GeneratePage() {
const [markdown, setMarkdown] = useState('');
const [isLoading, setIsLoading] = useState(false);

const handleGenerate = async (githubUrl: string) => {
setIsLoading(true);
setMarkdown(''); // Clear previous results
try {
const response = await fetch('/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: githubUrl }),
});

const data = await response.json();
if (data.markdown) {
setMarkdown(data.markdown);
} else {
alert(data.error || "Something went wrong");
}
Comment on lines +22 to +27
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Check response.ok before parsing JSON to avoid misleading errors.

If the server returns a non-2xx status with an HTML body (e.g., a 502 gateway error), response.json() will throw a SyntaxError, and the catch block will show "Failed to connect to the server" — which is misleading.

Proposed fix
      const response = await fetch('/api/generate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: githubUrl }),
      });

+     if (!response.ok) {
+       const text = await response.text();
+       let message = "Something went wrong";
+       try { message = JSON.parse(text).error || message; } catch {}
+       alert(message);
+       return;
+     }
+
      const data = await response.json();
      if (data.markdown) {
        setMarkdown(data.markdown);
      } else {
        alert(data.error || "Something went wrong");
      }
🤖 Prompt for AI Agents
In `@src/app/generate/page.tsx` around lines 22 - 27, Before calling
response.json() in the fetch handling inside page.tsx, check response.ok and
handle non-2xx responses first; if !response.ok, read the response text (or use
response.status / statusText) and surface that as the error message instead of
attempting to parse JSON, so setMarkdown is only called after a successful
response and alerts show the real server error; update the block that currently
does const data = await response.json(); if (data.markdown) { setMarkdown(...) }
else { alert(...) } to first verify response.ok and handle fallback text/status
accordingly.

} catch (error) {
console.error("Generation failed:", error);
alert("Failed to connect to the server.");
} finally {
setIsLoading(false);
}
};

const navLinks = [
{ name: 'Home', href: '/' },
{ name: 'Features', href: '/features' },
{ name: 'Examples', href: '/examples' },
{ name: 'Docs', href: '/docs' },
];

return (
<div className="min-h-screen bg-black text-white">
<Navbar links={navLinks} />

<main className="pt-40 pb-20 px-4 max-w-6xl mx-auto">
<div className="text-center mb-16 space-y-4">
<h1 className="text-4xl md:text-5xl font-bold tracking-tight">Generate Documentation</h1>
<p className="text-gray-400">Enter your repository URL and let the AI do the heavy lifting.</p>
</div>

<SearchInput onGenerate={handleGenerate} isLoading={isLoading} />

{/* Results will appear here once generated */}
<MarkdownPreview content={markdown} />

{/* Empty state helper */}
{!markdown && !isLoading && (
<div className="mt-20 text-center border border-dashed border-white/5 rounded-3xl py-20 bg-zinc-950/30">
<p className="text-gray-600 font-mono text-sm">Waiting for repository URL...</p>
</div>
)}
</main>

<Footer />
</div>
);
}
8 changes: 4 additions & 4 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { Code, Layout, FileText } from 'lucide-react';

export default function Home() {
const navLinks = [
{ name: 'Home', href: '#' },
{ name: 'Features', href: '#features' },
{ name: 'Examples', href: '#examples' },
{ name: 'Docs', href: '#docs' },
{ name: 'Home', href: '/' },
{ name: 'Features', href: '/features' },
{ name: 'Examples', href: '/examples' },
{ name: 'Docs', href: '/docs' },
];

const featureList = [
Expand Down
Loading