Skip to content

Commit 54017d6

Browse files
Merge branch 'main' into fix/cors-allowlist-session-cookie-hardening
2 parents 4d5fc14 + 6f83e96 commit 54017d6

19 files changed

Lines changed: 1910 additions & 759 deletions

File tree

README.md

Lines changed: 166 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,66 @@ Welcome to **GitHub Tracker**, a web app designed to help you monitor and analyz
4141
---
4242

4343
## 🚀 Setup Guide
44-
1. Clone the repository to your local machine:
44+
45+
### 📋 Prerequisites
46+
47+
Before setting up the project locally, ensure the following tools are installed on your system:
48+
49+
- Node.js (v18 or later recommended)
50+
- npm
51+
- Docker
52+
- Docker Compose
53+
- MongoDB (required for backend services and testing)
54+
55+
---
56+
57+
## 📥 Clone the Repository
58+
4559
```bash
46-
$ git clone https://github.com/yourusername/github-tracker.git
60+
git clone https://github.com/GitMetricsLab/github_tracker.git
61+
cd github-tracker
4762
```
4863

49-
2. Navigate to the project directory:
64+
---
65+
66+
# 💻 Local Development Setup
67+
68+
This project contains both frontend and backend services.
69+
70+
## ▶️ Frontend Setup
71+
72+
Install frontend dependencies:
73+
74+
```bash
75+
npm install
76+
```
77+
78+
Start the frontend development server:
79+
5080
```bash
51-
$ cd github-tracker
81+
npm run dev
82+
```
83+
84+
The frontend will run on:
85+
86+
```txt
87+
http://localhost:5173
88+
```
89+
90+
---
91+
92+
## ⚙️ Backend Setup
93+
94+
Move into the backend directory:
95+
96+
```bash
97+
cd backend
98+
```
99+
100+
Install backend dependencies:
101+
102+
```bash
103+
npm install
52104
```
53105

54106
3. Configure environment variables
@@ -73,8 +125,13 @@ $ cd github-tracker
73125

74126
4. Run the frontend
75127
```bash
76-
$ npm i
77-
$ npm run dev
128+
npm run dev
129+
```
130+
131+
The backend server will run on:
132+
133+
```txt
134+
http://localhost:5000
78135
```
79136

80137
5. Run the backend
@@ -84,6 +141,106 @@ $ npm i
84141
$ npm start
85142
```
86143

144+
This command:
145+
146+
- Builds frontend and backend containers
147+
- Starts development services
148+
- Enables live file changes using Docker volumes
149+
- Runs frontend and backend simultaneously
150+
151+
### Development Services
152+
153+
| Service | Port |
154+
|----------|------|
155+
| Frontend | 5173 |
156+
| Backend | 5000 |
157+
158+
---
159+
160+
## 🚀 Production Environment
161+
162+
Run the production Docker setup:
163+
164+
```bash
165+
npm run docker:prod
166+
```
167+
168+
This command:
169+
170+
- Creates optimized production builds
171+
- Runs frontend using Nginx
172+
- Starts backend production services
173+
174+
### Production Services
175+
176+
| Service | Port |
177+
|----------|------|
178+
| Frontend | 3000 |
179+
| Backend | 5000 |
180+
181+
---
182+
183+
# 📂 Docker Configuration Overview
184+
185+
| File | Purpose |
186+
|------|----------|
187+
| `Dockerfile.dev` | Development container setup |
188+
| `Dockerfile.prod` | Production container setup |
189+
| `docker-compose.yml` | Multi-service container orchestration |
190+
191+
---
192+
193+
# 🔄 Local Development Workflow
194+
195+
Recommended contributor workflow:
196+
197+
1. Fork the repository
198+
2. Clone your fork locally
199+
3. Create a new branch
200+
4. Install dependencies
201+
5. Run frontend/backend locally or using Docker
202+
6. Make changes
203+
7. Test your implementation
204+
8. Commit and push changes
205+
9. Open a Pull Request
206+
207+
---
208+
209+
# 🌱 Environment Configuration
210+
211+
The project uses environment variables for configuration.
212+
213+
Frontend environment variables:
214+
215+
```env
216+
VITE_BACKEND_URL=http://localhost:5000
217+
```
218+
219+
Backend environment variables:
220+
221+
```env
222+
PORT=5000
223+
MONGO_URI=your_mongodb_connection
224+
SESSION_SECRET=your_secret
225+
```
226+
227+
Create corresponding `.env` files before running the application.
228+
229+
---
230+
231+
# 🛠️ Useful Commands
232+
233+
| Command | Description |
234+
|----------|-------------|
235+
| `npm run dev` | Start frontend locally |
236+
| `npm run build` | Create production build |
237+
| `npm run docker:dev` | Run Docker development environment |
238+
| `npm run docker:prod` | Run Docker production environment |
239+
| `npm run test` | Run frontend tests |
240+
| `npm run test:backend` | Run backend tests |
241+
242+
---
243+
87244
## 🧪 Backend Unit & Integration Testing with Jasmine
88245

89246
This project uses the Jasmine framework for backend unit and integration tests. The tests cover:
@@ -161,3 +318,6 @@ spec_files: [
161318
⬆️ Back to Top
162319
</a>
163320
</p>
321+
322+
323+

index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/crl-icon.png" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<link rel="preconnect" href="https://fonts.googleapis.com" />
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9+
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet" />
710
<title>Github Tracker</title>
811
</head>
912
<body>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "GitHub Tracker",
2+
"name": "github-tracker",
33
"private": true,
44
"version": "0.0.0",
55
"type": "module",

src/components/Features.tsx

Lines changed: 141 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,91 @@
11
import { BarChart3, Users, Search, Zap, Shield, Globe } from 'lucide-react';
2+
import type { CSSProperties, ReactNode } from 'react';
3+
4+
type TerminalHeadingProps = {
5+
title: string;
6+
as?: 'h2' | 'h3' | 'h4';
7+
className?: string;
8+
promptClassName?: string;
9+
titleClassName?: string;
10+
animated?: boolean;
11+
};
12+
13+
type TerminalCardProps = {
14+
label: string;
15+
children: ReactNode;
16+
className?: string;
17+
contentClassName?: string;
18+
accent?: 'blue' | 'green';
19+
};
20+
21+
const headingSizes: Record<NonNullable<TerminalHeadingProps['as']>, string> = {
22+
h2: 'text-3xl md:text-4xl',
23+
h3: 'text-xl md:text-2xl',
24+
h4: 'text-lg md:text-xl',
25+
};
26+
27+
const TerminalHeading = ({
28+
title,
29+
as: HeadingTag = 'h2',
30+
className = '',
31+
promptClassName = '',
32+
titleClassName = '',
33+
animated = false,
34+
}: TerminalHeadingProps) => {
35+
const chars = title.length + 2;
36+
37+
return (
38+
<HeadingTag
39+
className={`inline-flex items-center gap-2 text-balance text-[#c9d1d9] ${headingSizes[HeadingTag]} ${className}`}
40+
style={animated ? ({ '--terminal-chars': chars } as CSSProperties) : undefined}
41+
>
42+
<span
43+
className={`font-["VT323"] text-[#58a6ff] ${animated ? 'terminal-typewriter inline-block' : ''} ${promptClassName}`}
44+
>
45+
&gt;
46+
</span>
47+
<span
48+
className={`font-["VT323"] tracking-[0.03em] ${animated ? 'terminal-typewriter inline-block' : ''} ${titleClassName}`}
49+
>
50+
{title}
51+
</span>
52+
</HeadingTag>
53+
);
54+
};
55+
56+
const TerminalCard = ({
57+
label,
58+
children,
59+
className = '',
60+
contentClassName = '',
61+
accent = 'blue',
62+
}: TerminalCardProps) => {
63+
const accentClasses = accent === 'green' ? 'text-[#3fb950] border-[#3fb950]/30' : 'text-[#58a6ff] border-[#58a6ff]/30';
64+
65+
return (
66+
<article
67+
className={`group relative overflow-hidden rounded-2xl border border-[#30363d] bg-[#161b22] shadow-[0_12px_30px_rgba(1,4,9,0.22)] transition-all duration-300 ease-out hover:-translate-y-1 hover:border-[#58a6ff]/40 hover:shadow-[0_18px_38px_rgba(1,4,9,0.35)] ${className}`}
68+
>
69+
<div className="flex items-center justify-between gap-4 border-b border-[#30363d] bg-[#0d1117]/90 px-4 py-3">
70+
<div className="flex items-center gap-1.5" aria-hidden="true">
71+
<span className="h-2.5 w-2.5 rounded-full bg-[#f85149]/80" />
72+
<span className="h-2.5 w-2.5 rounded-full bg-[#d29922]/80" />
73+
<span className="h-2.5 w-2.5 rounded-full bg-[#3fb950]/80" />
74+
</div>
75+
76+
<div className={`flex items-center gap-2 font-["VT323"] text-sm uppercase tracking-[0.22em] ${accentClasses}`}>
77+
<span>{label}</span>
78+
<span className="terminal-card-cursor opacity-0 transition-opacity duration-200 group-hover:opacity-100">_</span>
79+
</div>
80+
</div>
81+
82+
<div className={`relative px-5 py-5 sm:px-6 sm:py-6 ${contentClassName}`}>
83+
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/5 to-transparent" />
84+
{children}
85+
</div>
86+
</article>
87+
);
88+
};
289

390
const Features = () => {
491
const features = [
@@ -59,28 +146,67 @@ const Features = () => {
59146
];
60147

61148
return (
62-
<section id="features" className="px-6 py-6 bg-white dark:bg-gray-900 transition-colors duration-300">
63-
<div className="mx-auto">
64-
<div className="text-center mb-16">
65-
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">Powerful Features</h2>
66-
<p className="text-xl text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
67-
Everything you need to track, analyze, and understand GitHub activity patterns
149+
<section
150+
id="features"
151+
className="relative left-1/2 right-1/2 w-screen -mx-[50vw] overflow-hidden bg-[linear-gradient(to_bottom,#f8fafc_0%,#dbe7f5_20%,#0d1117_100%)] px-6 py-16 text-[#c9d1d9] transition-colors duration-300 sm:py-20"
152+
style={{
153+
boxShadow: '0 -40px 80px rgba(88,166,255,0.08), 0 40px 80px rgba(88,166,255,0.05)',
154+
}}
155+
>
156+
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(88,166,255,0.08),_transparent_32%),radial-gradient(circle_at_bottom_right,_rgba(63,185,80,0.05),_transparent_28%)] pointer-events-none" />
157+
<div className="absolute inset-x-0 top-0 h-28 bg-gradient-to-b from-[#f8fafc]/75 via-[#dbe7f5]/20 to-transparent pointer-events-none" />
158+
<div className="absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-[#0d1117] via-[#0d1117]/70 to-transparent pointer-events-none" />
159+
<div className="mx-auto max-w-7xl relative">
160+
<div className="mx-auto mb-10 max-w-3xl text-center sm:mb-12">
161+
<p className="font-['VT323'] text-sm uppercase tracking-[0.32em] text-[#58a6ff] sm:text-base">
162+
&gt; initialize tracking capabilities
163+
</p>
164+
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-black md:text-4xl">
165+
Powerful Features
166+
</h2>
167+
<p className="mx-auto mt-4 max-w-2xl text-sm leading-relaxed text-[#8b949e] sm:text-base">
168+
Everything you need to track, analyze, and understand GitHub activity patterns.
68169
</p>
69170
</div>
70171

71-
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
172+
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
72173
{features.map((feature, index) => {
73174
const IconComponent = feature.icon;
175+
const promptLabel = `feature-${String(index + 1).padStart(2, '0')}`;
176+
const titleTone = index % 2 === 0 ? 'blue' : 'green';
74177
return (
75-
<div key={index} className={`group h-72 w-full bg-gray-100 dark:bg-gray-800 ${feature.hoverColor} ${feature.borderColor} rounded-2xl shadow-md hover:shadow-2xl hover:shadow-blue-500/20 border dark:border-gray-800 transform hover:-translate-y-3 hover:scale-105 backdrop-blur-sm transition-all duration-300 ease-linear p-6`}>
76-
<div className={`${feature.bgColor} w-12 h-12 rounded-lg flex items-center justify-center mb-6 transition-transform duration-300 group-hover:rotate-6 group-hover:scale-110`}>
77-
<IconComponent className={`h-6 w-6 ${feature.iconColor}`} />
178+
<TerminalCard key={index} label={promptLabel} accent={titleTone} className="h-full">
179+
<div className="flex h-full flex-col gap-4">
180+
<div className="flex items-start gap-4">
181+
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl border border-[#30363d] bg-[#0d1117] text-[#58a6ff] transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:scale-105">
182+
<IconComponent className="h-5 w-5" />
183+
</div>
184+
<div className="min-w-0 flex-1 space-y-2">
185+
<TerminalHeading
186+
title={feature.title}
187+
as="h3"
188+
className="items-start"
189+
titleClassName="text-[#f0f6fc]"
190+
/>
191+
<div className="flex flex-wrap items-center gap-2 text-[11px] uppercase tracking-[0.24em] text-[#8b949e]">
192+
<span className="rounded-full border border-[#30363d] bg-[#0d1117] px-2.5 py-1 font-['VT323'] text-[#58a6ff]">
193+
cmd
194+
</span>
195+
<span className="font-['VT323']">gh tracker --feature</span>
196+
</div>
197+
</div>
198+
</div>
199+
200+
<p className="text-sm leading-relaxed text-[#8b949e] sm:text-[0.95rem]">
201+
{feature.description}
202+
</p>
203+
204+
<div className="mt-auto flex items-center justify-between border-t border-[#30363d] pt-4 text-xs text-[#8b949e]">
205+
<span className="font-['VT323'] uppercase tracking-[0.2em] text-[#3fb950]">ready</span>
206+
<span className="font-['VT323'] text-[#58a6ff]">{feature.title.toLowerCase().replace(/\s+/g, '-')}</span>
207+
</div>
78208
</div>
79-
<h3 className=" text-2xl font-bold text-gray-900 dark:text-gray-100 group-hover:text-black dark:group-hover:text-white transition-colors duration-300">{feature.title}</h3>
80-
<p className="text-gray-600 dark:text-gray-300 text-base font-semibold leading-relaxed group-hover:text-gray-700 dark:group-hover:text-gray-200 transition-colors duration-300">
81-
{feature.description}
82-
</p>
83-
</div>
209+
</TerminalCard>
84210
);
85211
})}
86212
</div>

0 commit comments

Comments
 (0)