Skip to content
Open
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
9 changes: 6 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Report from './pages/Report';

import AOS from 'aos';
import 'aos/dist/aos.css';
import { ThemeProvider } from './contexts/ThemeContext';

function AppRoutes() {
const location = useLocation();
Expand Down Expand Up @@ -55,9 +56,11 @@ function AppRoutes() {
function App() {
return (
<AuthProvider>
<Router>
<AppRoutes />
</Router>
<ThemeProvider>
<Router>
<AppRoutes />
</Router>
</ThemeProvider>
</AuthProvider>
);
}
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { BarChart3, User, LogOut, Menu } from "lucide-react";
import { useAuth } from "../contexts/AuthContext";
import { useAuth } from "../../contexts/AuthContext";

export default function Navbar() {
const { user, signOut } = useAuth();
Expand Down
47 changes: 47 additions & 0 deletions src/components/landing/CTASection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react";
import { useTheme } from "../../contexts/ThemeContext";
import { Link } from "react-router-dom";
import { ArrowRight } from "lucide-react";
import { useAuth } from "../../contexts/AuthContext";

export const CTASection: React.FC = () => {
const { t, isDark } = useTheme();
const { user } = useAuth();

return(
<section className="py-20" aria-label="Call to action">
<div className="max-w-7xl mx-auto px-6 w-full">
<div
className={`py-16 text-center rounded-3xl shadow-2xl ${
isDark
? "bg-gray-800/70 border border-white/10"
: "bg-white border border-gray-100"
} transform hover:scale-[1.005] transition`}
>
<h2 className="text-4xl md:text-5xl font-extrabold mb-4">
Ready to discover your developer score?
</h2>
<p className={`${t.sub} text-lg max-w-2xl mx-auto mb-8`}>
Stop guessing where you stand. Get your personalized report and
improvement plan in under 60 seconds.
</p>
{user ? (
<Link
to="/dashboard"
className="inline-flex items-center gap-2 px-8 py-3 bg-gradient-to-r from-teal-400 to-cyan-300 text-black rounded-lg font-bold text-lg shadow-lg hover:shadow-xl hover:scale-[1.02] transition"
>
Go to Dashboard <ArrowRight className="w-5 h-5" />
</Link>
) : (
<Link
to="/auth"
className="inline-flex items-center gap-2 px-8 py-3 bg-gradient-to-r from-teal-400 to-cyan-300 text-black rounded-lg font-bold text-lg shadow-lg hover:shadow-xl hover:scale-[1.02] transition"
>
Get Started Free <ArrowRight className="w-5 h-5" />
</Link>
)}
</div>
</div>
</section>
)
}
36 changes: 36 additions & 0 deletions src/components/landing/FAQItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Helper component for FAQ details (to clean up the main component)
const FAQItem: React.FC<{ question: string; answer: string; isDark: boolean }> = ({
question,
answer,
isDark,
}) => {
const t = { muted: isDark ? "text-gray-400" : "text-gray-500" };

return (
<details
className={`${
isDark
? "glass hover:glass-strong"
: "bg-white border border-gray-100 hover:border-gray-300"
} rounded-lg p-5 transition-all duration-300`}
>
<summary
className={`font-semibold cursor-pointer flex items-center justify-between transition-colors`}
>
<span className="flex-1">{question}</span>
<span className={`ml-3 text-lg ${isDark ? "text-teal-300" : "text-teal-600"}`}>
+
</span>
</summary>
<div
className={`${t.muted} mt-3 pt-3 border-t ${
isDark ? "border-white/5" : "border-gray-100"
} text-sm leading-relaxed`}
>
{answer}
</div>
</details>
);
};

export default FAQItem;
70 changes: 70 additions & 0 deletions src/components/landing/FAQSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from "react";
import { useTheme } from "../../contexts/ThemeContext";
import FAQItem from "./FAQItem";


export const FAQSection: React.FC = () => {
const { t, isDark } = useTheme();

return (
<section
id="faq"
className="py-20 lg:py-24 fade-in"
aria-label="FAQ"
>
<div className="max-w-7xl mx-auto px-6 w-full">
<h2
className={`text-3xl md:text-4xl font-semibold mb-12 text-center ${t.heading}`}
>
Frequently Asked Questions
</h2>
<div className="grid md:grid-cols-2 gap-6">
<div className="space-y-4">
<FAQItem
question="How is the Developer Score calculated?"
answer="The score is a complex, weighted combination of GitHub activity (commits, stars, code quality), LinkedIn presence (experience, endorsements), blogging metrics, and competitive coding performance. The algorithm is proprietary and uses heuristic-augmented AI."
isDark={isDark}
/>
<FAQItem
question="Is my data safe and private?"
answer="Yes — our architecture is designed for security. All sensitive operations, scoring, and third-party API calls run server-side using secure serverless functions and Supabase Row Level Security (RLS). Service role keys are never exposed in the browser."
isDark={isDark}
/>
<FAQItem
question="What platforms do you connect to?"
answer="Currently, we support in-depth analysis for GitHub, LinkedIn, and we offer optional analysis for custom technical blogs/portfolios and major coding platforms (e.g., LeetCode, HackerRank profiles)."
isDark={isDark}
/>
<FAQItem
question="How long does it take to generate a report?"
answer="Initial report generation is instantaneous once you provide your necessary profile links. Subsequent analysis updates typically complete within seconds due to efficient serverless processing."
isDark={isDark}
/>
</div>
<div className="space-y-4">
<FAQItem
question="Is DevScore entirely free to use?"
answer="Basic reports and core score tracking features are completely free. We plan to introduce premium tiers in the future for advanced features like in-depth AI goal setting, personalized technical writing reviews, and priority report generation."
isDark={isDark}
/>
<FAQItem
question="Can I share my DevScore with recruiters or employers?"
answer="Yes, the dashboard includes a feature to generate a shareable, verifiable link to your current Developer Score and key metric summaries. This is perfect for job applications and portfolio sites."
isDark={isDark}
/>
<FAQItem
question="Can I export my reports?"
answer="Currently, reports are viewable and shareable via a link. PDF and CSV export functionality for detailed reports and historical data is planned for the next major release."
isDark={isDark}
/>
<FAQItem
question="I'm a new developer, will my score be low?"
answer="The score is relative to your activity and progress. DevScore provides specific, achievable goals for beginners to increase their score quickly, focusing on fundamental public profile best practices."
isDark={isDark}
/>
</div>
</div>
</div>
</section>
)
}
137 changes: 137 additions & 0 deletions src/components/landing/FeatureSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, { useState } from "react";
import { useTheme } from "../../contexts/ThemeContext";
import { Code, FileText, Github, Linkedin, X } from "lucide-react";

export const FeatureSection: React.FC = () => {
const { isDark, t } = useTheme();
const [showDocPopup, setShowDocPopup] = useState(false);

return (
<>
<section
id="features"
className="py-20 lg:py-24 fade-in"
aria-label="Features"
>
<div className="max-w-7xl mx-auto px-6 w-full">
<div className="flex flex-col sm:flex-row items-center justify-between mb-12 gap-4">
<h2 className={`text-3xl md:text-4xl font-semibold ${t.heading}`}>
What DevScore analyzes
</h2>
<button
onClick={() => setShowDocPopup(true)}
className={`hidden sm:block ${
isDark ? "glass" : "bg-white border border-gray-200"
} px-3 py-2 rounded-lg hover:scale-105 transition`}
>
Documentation
</button>
</div>

{/* Layout: Optimised for all screen sizes */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-4 gap-6">
{[
{
icon: <Github className="h-6 w-6" />,
title: "GitHub Activity",
desc: "Repos, stars, commit patterns, PR cadence and code health.",
},
{
icon: <Linkedin className="h-6 w-6" />,
title: "LinkedIn Network",
desc: "Profile completeness, endorsements, engagement and network growth.",
},
{
icon: <FileText className="h-6 w-6" />,
title: "Technical Blog",
desc: "Post frequency, content depth, readability and reach.",
},
{
icon: <Code className="h-6 w-6" />,
title: "Coding Platforms",
desc: "Problems solved, ranks, contest performance and streaks.",
},
].map((f, i) => (
<article
key={i}
className={`shine-effect card-glow-hover ${
isDark
? "glass border border-white/5"
: "bg-white border border-gray-100"
} rounded-xl p-6 shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition`}
>
<div className="flex flex-col gap-3">
<div
className={`w-12 h-12 rounded-lg flex items-center justify-center ${
isDark
? "bg-gradient-to-br from-teal-400/20 to-cyan-300/10"
: "bg-gradient-to-br from-cyan-200 to-teal-200"
}`}
>
{f.icon}
</div>
<div>
<h3 className={`text-xl font-semibold ${t.heading}`}>
{f.title}
</h3>
</div>
</div>
<p className={`${t.sub} text-sm md:text-base mt-2`}>
{f.desc}
</p>
<div className={`${t.muted} text-xs mt-4`}>
Included in every report • Fast analysis
</div>
</article>
))}
</div>
</div>
</section>
{/* Documentation popup */}
{showDocPopup && (
<div className="fixed inset-0 flex items-center justify-center bg-black/60 z-50 px-4">
<div
className={`${
isDark
? "bg-gradient-to-br from-gray-900 to-gray-800"
: "bg-white"
} rounded-xl p-6 w-full max-w-md shadow-xl ${
isDark ? "glass-strong" : ""
}`}
>
<button
onClick={() => setShowDocPopup(false)}
className="absolute top-6 right-6 text-gray-400 hover:text-gray-700"
>
<X className="h-5 w-5" />
</button>
<h3 className={`text-lg font-semibold ${t.heading}`}>
Documentation — Coming Soon 🚀
</h3>
<p className={`${t.sub} text-sm mt-2`}>
We're building a documentation hub with API references, onboarding
guides and contribution guidelines.
</p>

<div className="mt-4 flex gap-2">
<a
className="px-4 py-2 bg-gradient-to-r from-teal-400 to-cyan-300 text-black rounded-md"
href="/docs"
>
View Docs (Soon)
</a>
<button
onClick={() => setShowDocPopup(false)}
className={`px-4 py-2 rounded-md ${
isDark ? "border border-white/6" : "border border-gray-200"
}`}
>
Close
</button>
</div>
</div>
</div>
)}
</>
)
}
Loading