Skip to content

Commit c9db845

Browse files
committed
feat: Enhance job listings with company details, add post job functionality, and automate README updates.
1 parent 7dfc425 commit c9db845

File tree

12 files changed

+661
-467
lines changed

12 files changed

+661
-467
lines changed

.claude/settings.local.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(node fix-company-info.js:*)",
5+
"Bash(node -e:*)",
6+
"Bash(node fix-real-companies.js:*)",
7+
"Bash(cut -d',' -f1-2 echo \"\" echo \"Prometheus 生态系统:\" grep \"^prometheus/\\|^thanos-io/\\|^cortexproject/\" repos.csv)",
8+
"Bash(cut -d',' -f1-2 echo \"\" echo \"其他重要项目:\" grep \"^jaegertracing/\\|^open-telemetry/\\|^helm/\" repos.csv)"
9+
],
10+
"deny": [],
11+
"ask": []
12+
}
13+
}

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: 📝 Edit CSV Directly
4+
url: https://github.com/timqian/open-source-jobs/blob/main/repos.csv
5+
about: Experienced users can directly edit the repos.csv file
6+
- name: 💬 Discussions
7+
url: https://github.com/timqian/open-source-jobs/discussions
8+
about: Ask questions and discuss with the community
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Add New Repository
2+
description: Submit a new open source repository with job opportunities
3+
title: "[New Repo]: "
4+
labels: ["new-repository"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Thanks for taking the time to add a new repository! Please fill out the form below.
10+
11+
- type: input
12+
id: repository
13+
attributes:
14+
label: Repository
15+
description: GitHub repository (e.g., facebook/react)
16+
placeholder: "organization/repository"
17+
validations:
18+
required: true
19+
20+
- type: input
21+
id: company-name
22+
attributes:
23+
label: Company Name
24+
description: Name of the company hiring for this project
25+
placeholder: "e.g., Meta"
26+
validations:
27+
required: true
28+
29+
- type: input
30+
id: company-url
31+
attributes:
32+
label: Company URL
33+
description: Official company website
34+
placeholder: "https://www.company.com"
35+
validations:
36+
required: true
37+
38+
- type: input
39+
id: career-url
40+
attributes:
41+
label: Career/Job Page URL
42+
description: Direct link to the company's careers page or job listings
43+
placeholder: "https://www.company.com/careers"
44+
validations:
45+
required: true
46+
47+
- type: textarea
48+
id: description
49+
attributes:
50+
label: Repository Description
51+
description: Brief description of the repository
52+
placeholder: "A declarative, efficient, and flexible JavaScript library for building user interfaces."
53+
validations:
54+
required: true
55+
56+
- type: input
57+
id: language
58+
attributes:
59+
label: Primary Language
60+
description: Main programming language used in the repository
61+
placeholder: "JavaScript"
62+
validations:
63+
required: true
64+
65+
- type: input
66+
id: tags
67+
attributes:
68+
label: Tags
69+
description: Comma-separated tags (e.g., frontend, react, ui, library)
70+
placeholder: "frontend, react, ui, library"
71+
validations:
72+
required: true
73+
74+
- type: checkboxes
75+
id: verification
76+
attributes:
77+
label: Verification
78+
description: Please confirm the following
79+
options:
80+
- label: This repository is actively maintained and the company is currently hiring
81+
required: true
82+
- label: I have verified that the career/job page URL is correct and active
83+
required: true
84+
- label: This repository is not already in the list
85+
required: true
86+
87+
- type: markdown
88+
attributes:
89+
value: |
90+
---
91+
92+
### What happens next?
93+
94+
Once you submit this issue, a maintainer will review your submission and add the repository to the CSV file if it meets the criteria. Thank you for contributing!
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Update README
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- master
8+
paths:
9+
- 'repos.csv'
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
update-readme:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
with:
22+
token: ${{ secrets.GITHUB_TOKEN }}
23+
24+
- name: Setup Node.js
25+
uses: actions/setup-node@v4
26+
with:
27+
node-version: '18'
28+
29+
- name: Run update README script
30+
run: node scripts/update-readme.js
31+
32+
- name: Commit and push if changed
33+
run: |
34+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
35+
git config --local user.name "github-actions[bot]"
36+
git add README.md
37+
git diff --staged --quiet || git commit -m "chore: auto-update README from repos.csv"
38+
git push

README.md

Lines changed: 145 additions & 210 deletions
Large diffs are not rendered by default.

app/page.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getJobs } from "@/lib/csv";
22
import { JobList } from "@/components/job-list";
3+
import { PostJobModal } from "@/components/post-job-modal";
34
import Image from "next/image";
45

56
export default async function Home() {
@@ -22,26 +23,34 @@ export default async function Home() {
2223
<Image src="/favicon.ico" alt="Logo" width={32} height={32} className="w-8 h-8" unoptimized />
2324
{/* Open Source Jobs */}
2425
</a>
26+
2527
</div>
2628
<a
27-
href="https://github.com/timqian/open-source-jobs/blob/main/repos.csv"
28-
className="inline-flex items-center justify-center rounded-md bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 hover:bg-zinc-700 dark:hover:bg-zinc-300 text-sm font-medium px-4 py-2 transition-colors"
29+
href="https://github.com/timqian/open-source-jobs"
2930
>
30-
Post a job
31+
<img
32+
src="https://img.shields.io/github/stars/timqian/open-source-jobs?style=social&label=Star"
33+
alt="GitHub stars"
34+
className="h-6"
35+
/>
3136
</a>
3237
</div>
3338
</div>
3439
</nav>
3540

3641
{/* Hero Section */}
3742
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 pt-16 pb-8">
38-
<div className="text-center mb-12">
39-
<h1 className="text-5xl sm:text-6xl font-bold tracking-tight bg-gradient-to-r from-zinc-900 via-zinc-700 to-zinc-900 dark:from-zinc-100 dark:via-zinc-400 dark:to-zinc-100 bg-clip-text text-transparent mb-4 animate-fade-in">
43+
<div className="text-center mb-6 flex flex-col gap-4">
44+
<h1 className="text-5xl sm:text-6xl font-bold tracking-tight bg-gradient-to-r from-zinc-900 via-zinc-700 to-zinc-900 dark:from-zinc-100 dark:via-zinc-400 dark:to-zinc-100 bg-clip-text text-transparent animate-fade-in">
4045
Open Source Jobs
4146
</h1>
4247
<p className="text-xl text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto animate-fade-in">
4348
List of Open Source projects offering jobs.
4449
</p>
50+
51+
<div className="flex justify-center">
52+
<PostJobModal />
53+
</div>
4554
</div>
4655
</div>
4756

components/job-list.tsx

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ export function JobList({ jobs }: JobListProps) {
4848
}
4949

5050
result.sort((a, b) => {
51-
const repoA = a.repository.split("/")[1] || a.repository;
52-
const repoB = b.repository.split("/")[1] || b.repository;
53-
return repoA.localeCompare(repoB);
51+
return a.companyName.localeCompare(b.companyName);
5452
});
5553

5654
return result;
@@ -107,11 +105,11 @@ export function JobList({ jobs }: JobListProps) {
107105
<Table>
108106
<TableHeader>
109107
<TableRow>
110-
<TableHead className="w-[300px]">Repository</TableHead>
111-
<TableHead>Description</TableHead>
112-
<TableHead>Language</TableHead>
113-
<TableHead>Tags</TableHead>
114-
<TableHead className="text-right">Job Page</TableHead>
108+
<TableHead className="w-[200px] font-semibold text-zinc-900 dark:text-zinc-100">Company</TableHead>
109+
<TableHead className="w-[350px] font-semibold text-zinc-900 dark:text-zinc-100">Repository</TableHead>
110+
<TableHead className="font-semibold text-zinc-900 dark:text-zinc-100">Language</TableHead>
111+
<TableHead className="font-semibold text-zinc-900 dark:text-zinc-100">Tags</TableHead>
112+
<TableHead className="text-right font-semibold text-zinc-900 dark:text-zinc-100">Job Page</TableHead>
115113
</TableRow>
116114
</TableHeader>
117115
<TableBody>
@@ -120,26 +118,48 @@ export function JobList({ jobs }: JobListProps) {
120118
return (
121119
<TableRow key={job.repository}>
122120
<TableCell className="font-medium">
123-
<div className="flex items-center gap-2 flex-wrap">
124-
<a
125-
href={`https://github.com/${job.repository}`}
126-
target="_blank"
127-
rel="noopener noreferrer"
128-
className="text-base hover:underline"
129-
>
130-
<span className="text-zinc-500 dark:text-zinc-400">
131-
{org}/
132-
</span>
133-
<span className="font-semibold">{repo}</span>
134-
</a>
121+
<a
122+
href={job.companyUrl}
123+
target="_blank"
124+
rel="noopener noreferrer"
125+
className="flex items-center gap-2 text-base font-semibold hover:underline text-zinc-900 dark:text-zinc-100"
126+
>
135127
<img
136-
src={`https://img.shields.io/github/stars/${job.repository}.svg?style=social&label=%20`}
137-
alt={`${job.repository} stars`}
138-
className="h-5"
128+
src={`https://www.google.com/s2/favicons?domain=${job.companyUrl}&sz=32`}
129+
alt={`${job.companyName} favicon`}
130+
className="w-4 h-4 rounded-sm"
131+
onError={(e) => {
132+
e.currentTarget.style.display = 'none';
133+
}}
139134
/>
135+
{job.companyName}
136+
</a>
137+
</TableCell>
138+
<TableCell>
139+
<div className="flex flex-col gap-2">
140+
<div className="flex items-center gap-2 flex-wrap">
141+
<a
142+
href={`https://github.com/${job.repository}`}
143+
target="_blank"
144+
rel="noopener noreferrer"
145+
className="text-base hover:underline"
146+
>
147+
<span className="text-zinc-500 dark:text-zinc-400 font-normal">
148+
149+
</span>
150+
<span className="font-semibold text-zinc-900 dark:text-zinc-100">{org}/{repo}</span>
151+
</a>
152+
<img
153+
src={`https://img.shields.io/github/stars/${job.repository}.svg?style=social&label=%20`}
154+
alt={`${job.repository} stars`}
155+
className="h-5"
156+
/>
157+
</div>
158+
<div className="text-sm text-zinc-600 dark:text-zinc-400 font-normal leading-relaxed">
159+
{job.description}
160+
</div>
140161
</div>
141162
</TableCell>
142-
<TableCell>{job.description}</TableCell>
143163
<TableCell>
144164
{job.language && (
145165
<span className="inline-flex items-center rounded-md bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10 dark:bg-blue-900/30 dark:text-blue-400 dark:ring-blue-400/30">
@@ -164,7 +184,7 @@ export function JobList({ jobs }: JobListProps) {
164184
href={job.jobPage}
165185
target="_blank"
166186
rel="noopener noreferrer"
167-
className="text-blue-600 hover:underline dark:text-blue-400"
187+
className="inline-flex items-center justify-center rounded-md bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 text-white text-sm font-medium px-4 py-1.5 transition-colors"
168188
>
169189
Apply
170190
</a>

0 commit comments

Comments
 (0)