Skip to content

Commit 674277e

Browse files
committed
chore: reorganize project structure, add About/Docs components, update video format to WebM
1 parent fcdca6f commit 674277e

22 files changed

+240
-734
lines changed

package-lock.json

Lines changed: 17 additions & 687 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
"@octokit/rest": "^21.0.2",
1313
"@radix-ui/react-select": "^2.1.2",
1414
"@radix-ui/react-slot": "^1.1.0",
15-
"@shadcn/ui": "^0.0.4",
1615
"@types/react-syntax-highlighter": "^15.5.13",
1716
"class-variance-authority": "^0.7.0",
1817
"clsx": "^2.1.1",
1918
"file-saver": "^2.0.5",
2019
"framer-motion": "^11.11.17",
20+
"lodash": "^4.17.21",
2121
"lucide-react": "^0.456.0",
2222
"mini-svg-data-uri": "^1.4.4",
2323
"next": "15.0.3",
@@ -31,6 +31,7 @@
3131
},
3232
"devDependencies": {
3333
"@types/file-saver": "^2.0.7",
34+
"@types/lodash": "^4.17.13",
3435
"@types/node": "^20",
3536
"@types/react": "^18",
3637
"@types/react-dom": "^18",

public/file.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/globe.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/next.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/vercel.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/video/demo.mp4

-6.55 MB
Binary file not shown.

public/video/demo.webm

3.96 MB
Binary file not shown.

public/window.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/app/about/page.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use client'
2+
3+
import { useRouter } from 'next/navigation'
4+
import { ArrowLeft } from 'lucide-react'
5+
import { Button } from "@/components/ui/button"
6+
import Link from 'next/link'
7+
8+
const AboutPage = () => {
9+
const router = useRouter()
10+
11+
return (
12+
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white transition-colors duration-300 py-12 px-4 sm:px-6 lg:px-8">
13+
<div className="max-w-3xl mx-auto">
14+
<Button
15+
onClick={() => router.back()}
16+
className="mb-8 flex items-center text-white rounded-full bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-300"
17+
>
18+
<ArrowLeft className="h-4 w-4" />
19+
Go back
20+
</Button>
21+
22+
<h1 className="text-3xl font-bold mb-6">About RepoTree</h1>
23+
24+
<div className="p-6 space-y-4 transition-colors duration-300">
25+
<p>
26+
RepoTree is a simple tool to visualize GitHub repositories. It helps developers and teams easily explore and understand their project structures.
27+
</p>
28+
29+
<h2 className="text-xl font-semibold">Our Vision</h2>
30+
<p>
31+
We want every developer to quickly see the structure of any project, making it easier to collaborate and build efficiently.
32+
</p>
33+
34+
<h2 className="text-xl font-semibold">Features</h2>
35+
<ul className="list-disc pl-6 space-y-2">
36+
<li>Clean ASCII view of GitHub repository structure</li>
37+
<li>Interactive tree view for easy navigation</li>
38+
<li>Download options in various formats</li>
39+
<li>Real-time search to find files or folders quickly</li>
40+
</ul>
41+
42+
<p>
43+
Whether documenting a project or getting a quick overview, RepoTree makes it simple to understand your codebase.
44+
</p>
45+
46+
<div className="mt-8">
47+
<Link
48+
href="/generator"
49+
className="bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-full transition-colors duration-300"
50+
>
51+
Try RepoTree Now
52+
</Link>
53+
</div>
54+
</div>
55+
</div>
56+
</div>
57+
)
58+
}
59+
60+
export default AboutPage

src/app/docs/page.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'use client'
2+
3+
import { useRouter } from 'next/navigation'
4+
import { ArrowLeft } from 'lucide-react'
5+
import { Button } from "@/components/ui/button"
6+
import Link from 'next/link'
7+
8+
const DocsPage = () => {
9+
const router = useRouter()
10+
11+
return (
12+
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white transition-colors duration-300 py-12 px-4 sm:px-6 lg:px-8">
13+
<div className="max-w-3xl mx-auto">
14+
<Button
15+
onClick={() => router.back()}
16+
className="mb-8 flex items-center text-white rounded-full bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-300"
17+
>
18+
<ArrowLeft className="h-4 w-4" />
19+
Go back
20+
</Button>
21+
22+
<h1 className="text-3xl font-bold mb-6">RepoTree Documentation</h1>
23+
24+
<div className="p-6 space-y-4 transition-colors duration-300">
25+
<h2 className="text-xl font-semibold">Introduction</h2>
26+
<p>
27+
RepoTree is a powerful tool that generates a clean ASCII representation of a GitHub repository structure, perfect for documentation and sharing.
28+
</p>
29+
30+
<h2 className="text-xl font-semibold">Features</h2>
31+
<ul className="list-disc pl-6 space-y-2">
32+
<li><strong>Download in Different Formats:</strong> Users can download the directory structure in formats like README.md, .txt, .json, or .html.</li>
33+
<li><strong>Syntax Highlighting:</strong> Enhances readability using prism-react-renderer for syntax highlighting.</li>
34+
<li><strong>Real-time Search Bar:</strong> Quickly filter and highlight specific files or directories within the generated structure.</li>
35+
<li><strong>Persistent State with LocalStorage:</strong> Saves the last fetched repository URL, maintaining input between sessions.</li>
36+
<li><strong>Interactive Tree View:</strong> Allows expansion or collapse of folders for better navigation.</li>
37+
<li><strong>Clipboard Copy Notification:</strong> Provides a toast notification when the directory structure is copied to the clipboard.</li>
38+
<li><strong>View Mode Toggle:</strong> Switch between ASCII view and Interactive view for an enhanced user experience.</li>
39+
<li><strong>Clear Input Functionality:</strong> Includes a button to clear the input field, improving usability.</li>
40+
<li><strong>Loading State Animation:</strong> Displays a spinner during data fetching for a smoother experience.</li>
41+
<li><strong>Error Handling and Validation:</strong> Validates GitHub URLs and shows error messages for invalid inputs.</li>
42+
<li><strong>Expandable ASCII Tree:</strong> Toggle the expansion of the ASCII tree to view a complete or limited structure.</li>
43+
<li><strong>Filtered Structure Generation:</strong> Generates a structure based on search terms for quick file/folder location.</li>
44+
<li><strong>Enhanced UI with Tailwind CSS:</strong> Provides a responsive and visually appealing interface using Tailwind CSS.</li>
45+
<li><strong>Server-Side Fetching with Next.js:</strong> Optimized server-side fetching improves performance and SEO.</li>
46+
<li><strong>Save Last Fetched URL:</strong> Automatically saves and repopulates the last fetched URL for convenience.</li>
47+
</ul>
48+
49+
<h2 className="text-xl font-semibold mt-8">Future Features</h2>
50+
<ul className="list-disc pl-6 space-y-2">
51+
<li><strong>Fetching User Branches:</strong> Allows users to select a specific branch instead of defaulting to the main branch.</li>
52+
</ul>
53+
54+
<div className="mt-8">
55+
<Link
56+
href="/generator"
57+
className="bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-full transition-colors duration-300"
58+
>
59+
Try RepoTree Now
60+
</Link>
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
)
66+
}
67+
68+
export default DocsPage

src/app/fonts/GeistMonoVF.woff

-66.3 KB
Binary file not shown.

src/app/fonts/GeistVF.woff

-64.7 KB
Binary file not shown.

src/app/generator/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

3-
import Header from '@/components/header'
4-
import Footer from '@/components/footer'
3+
import Header from '@/components/layout/header'
4+
import Footer from '@/components/layout/footer'
55
import RepoTree from '@/app/generator/repo-tree-generator'
66

77
export default function RepoStructurePage() {

src/app/layout.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
import type { Metadata } from "next"
2-
import localFont from "next/font/local"
32
import { ThemeProvider } from '@/components/theme-provider'
4-
import "./globals.css"
5-
6-
const geistSans = localFont({
7-
src: "./fonts/GeistVF.woff",
8-
variable: "--font-geist-sans",
9-
weight: "100 900",
10-
})
11-
const geistMono = localFont({
12-
src: "./fonts/GeistMonoVF.woff",
13-
variable: "--font-geist-mono",
14-
weight: "100 900",
15-
})
3+
import "../styles/globals.css";
164

175
export const metadata: Metadata = {
186
title: "RepoTree - ASCII Tree Generator",
@@ -26,9 +14,7 @@ export default function RootLayout({
2614
}>) {
2715
return (
2816
<html lang="en" suppressHydrationWarning>
29-
<body
30-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
31-
>
17+
<body className="antialiased">
3218
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
3319
{children}
3420
</ThemeProvider>

src/app/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import LandingPage from './landing-page'
1+
import LandingPage from '@/components/landing-page'
22

33
export default function Home() {
44
return <LandingPage />

src/app/landing-page.tsx renamed to src/components/landing-page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import { useEffect } from 'react'
44
import { useAnimation } from 'framer-motion'
55
import { useInView } from 'react-intersection-observer'
6-
import Header from '@/components/header'
6+
import Header from '@/components/layout/header'
77
import Hero from '@/components/hero'
88
import About from '@/components/about'
99
import ProductShowcase from '@/components/product-showcase'
1010
import FAQ from '@/components/faq'
11-
import Footer from '@/components/footer'
11+
import Footer from '@/components/layout/footer'
1212

1313
export default function LandingPage() {
1414
const controls = useAnimation()

src/components/footer.tsx renamed to src/components/layout/footer.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,15 @@ const Footer = () => {
2323
<h3 className="text-base sm:text-lg md:text-xl font-semibold mb-4">Quick Links</h3>
2424
<ul className="space-y-2">
2525
<li>
26-
<Link href="/" className="hover:text-blue-400 transition-colors">
27-
Home
26+
<Link href="/docs" className="hover:text-blue-400 transition-colors">
27+
Docs
2828
</Link>
2929
</li>
3030
<li>
31-
<Link href="#about" className="hover:text-blue-400 transition-colors">
31+
<Link href="/about" className="hover:text-blue-400 transition-colors">
3232
About
3333
</Link>
3434
</li>
35-
<li>
36-
<Link href="#faq" className="hover:text-blue-400 transition-colors">
37-
FAQs
38-
</Link>
39-
</li>
4035
</ul>
4136
</div>
4237
<div>

src/components/header.tsx renamed to src/components/layout/header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Github, FolderTreeIcon } from 'lucide-react'
2-
import ThemeToggle from './theme-toggle'
2+
import ThemeToggle from '../theme-toggle';
33
import Link from 'next/link'
44

55
const Header = () => {

src/components/lazy-video.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { useEffect, useRef } from 'react'
2+
3+
interface LazyVideoProps {
4+
src: string
5+
className?: string
6+
}
7+
8+
export default function LazyVideo({ src, className }: LazyVideoProps) {
9+
const videoRef = useRef<HTMLVideoElement>(null)
10+
11+
useEffect(() => {
12+
const options = {
13+
root: null,
14+
rootMargin: '0px',
15+
threshold: 0.1
16+
}
17+
18+
const observer = new IntersectionObserver((entries) => {
19+
entries.forEach(entry => {
20+
if (entry.isIntersecting && videoRef.current) {
21+
videoRef.current.src = src
22+
videoRef.current.load()
23+
24+
// Play the video only once it's ready
25+
videoRef.current.oncanplay = () => {
26+
videoRef.current?.play().catch(error => console.error('Auto-play was prevented:', error))
27+
}
28+
29+
observer.unobserve(entry.target)
30+
}
31+
})
32+
}, options)
33+
34+
// Capture the current ref value at the time the effect runs
35+
const currentVideoRef = videoRef.current;
36+
37+
if (currentVideoRef) {
38+
observer.observe(currentVideoRef)
39+
}
40+
41+
return () => {
42+
// Cleanup by referencing the captured currentVideoRef
43+
if (currentVideoRef) {
44+
observer.unobserve(currentVideoRef)
45+
}
46+
}
47+
}, [src])
48+
49+
return (
50+
<video
51+
ref={videoRef}
52+
loop
53+
muted
54+
playsInline
55+
className={className}
56+
aria-label="Product demo video"
57+
>
58+
<source type="video/webm" />
59+
Your browser does not support the video tag.
60+
</video>
61+
)
62+
}

src/components/product-showcase.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
'use client'
22

3+
import { useState, useEffect } from 'react'
34
import { motion } from 'framer-motion'
45
import { Button } from '@/components/ui/button'
56
import Link from 'next/link'
7+
import LazyVideo from '@/components/lazy-video'
68

79
const ProductShowcase = () => {
10+
const [isClient, setIsClient] = useState(false)
11+
12+
useEffect(() => {
13+
setIsClient(true)
14+
}, [])
15+
816
return (
917
<section className="py-20 bg-white dark:bg-gray-900 overflow-hidden">
1018
<div className="container mx-auto px-4">
1119
<div className="flex flex-col lg:flex-row items-center">
1220
<motion.div
13-
initial={{ opacity: 0, x: -50 }}
14-
animate={{ opacity: 1, x: 0 }}
15-
transition={{ duration: 0.6 }}
21+
initial={{ opacity: 0, y: 20 }}
22+
animate={{ opacity: 1, y: 0 }}
23+
transition={{ duration: 0.5 }}
1624
className="lg:w-1/2 mb-10 lg:mb-0"
1725
>
1826
<h2 className="text-3xl md:text-4xl font-bold mb-6 text-gray-900 dark:text-white">
@@ -26,7 +34,6 @@ const ProductShowcase = () => {
2634
Perfect for documentation and easy sharing with your team.
2735
</p>
2836

29-
{/* "Try it now" Button */}
3037
<Link href="/generator">
3138
<Button
3239
size="lg"
@@ -38,16 +45,18 @@ const ProductShowcase = () => {
3845
</motion.div>
3946

4047
<motion.div
41-
initial={{ opacity: 0, x: 50 }}
42-
animate={{ opacity: 1, x: 0 }}
43-
transition={{ duration: 0.6, delay: 0.2 }}
48+
initial={{ opacity: 0, y: 20 }}
49+
animate={{ opacity: 1, y: 0 }}
50+
transition={{ duration: 0.5, delay: 0.2 }}
4451
className="lg:w-1/2"
4552
>
4653
<div className="rounded-lg shadow-2xl overflow-hidden">
47-
<video autoPlay loop muted playsInline className="w-full h-auto">
48-
<source src="/video/demo.mp4" type="video/mp4" />
49-
Your browser does not support the video tag.
50-
</video>
54+
{isClient && (
55+
<LazyVideo
56+
src="/video/demo.webm"
57+
className="w-full h-auto"
58+
/>
59+
)}
5160
</div>
5261
</motion.div>
5362
</div>
File renamed without changes.

0 commit comments

Comments
 (0)