├── public
├── apple-icon.png
├── placeholder.jpg
├── icon-dark-32x32.png
├── icon-light-32x32.png
├── placeholder-logo.png
├── placeholder-user.jpg
├── diverse-open-source-community-collaboration-global.jpg
├── icon.svg
├── placeholder-logo.svg
└── placeholder.svg
├── postcss.config.mjs
├── lib
└── utils.ts
├── next.config.mjs
├── components
├── theme-provider.tsx
├── ui
│ ├── avatar.tsx
│ ├── badge.tsx
│ ├── button.tsx
│ └── card.tsx
├── site-header.tsx
└── site-footer.tsx
├── components.json
├── tsconfig.json
├── app
├── layout.tsx
├── introduction
│ └── page.tsx
├── links
│ └── page.tsx
├── globals.css
├── cases
│ └── page.tsx
├── page.tsx
├── community
│ └── page.tsx
├── organization
│ └── page.tsx
├── contributors
│ └── page.tsx
├── operations
│ └── page.tsx
└── resources
│ └── page.tsx
├── data
├── introduction.ts
├── contributors.ts
├── cases.ts
├── community.ts
├── links.ts
└── resources.ts
├── README.md
├── package.json
└── styles
└── globals.css
/public/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/apple-icon.png
--------------------------------------------------------------------------------
/public/placeholder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/placeholder.jpg
--------------------------------------------------------------------------------
/public/icon-dark-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/icon-dark-32x32.png
--------------------------------------------------------------------------------
/public/icon-light-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/icon-light-32x32.png
--------------------------------------------------------------------------------
/public/placeholder-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/placeholder-logo.png
--------------------------------------------------------------------------------
/public/placeholder-user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/placeholder-user.jpg
--------------------------------------------------------------------------------
/public/diverse-open-source-community-collaboration-global.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/node/v0-ospo-comm/main/public/diverse-open-source-community-collaboration-global.jpg
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | '@tailwindcss/postcss': {},
5 | },
6 | }
7 |
8 | export default config
9 |
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { clsx, type ClassValue } from 'clsx'
2 | import { twMerge } from 'tailwind-merge'
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | typescript: {
4 | ignoreBuildErrors: true,
5 | },
6 | images: {
7 | unoptimized: true,
8 | },
9 |
10 | }
11 |
12 | export default nextConfig
--------------------------------------------------------------------------------
/components/theme-provider.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import {
5 | ThemeProvider as NextThemesProvider,
6 | type ThemeProviderProps,
7 | } from 'next-themes'
8 |
9 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
10 | return {children}
11 | }
12 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "new-york",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "",
8 | "css": "app/globals.css",
9 | "baseColor": "neutral",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils",
16 | "ui": "@/components/ui",
17 | "lib": "@/lib",
18 | "hooks": "@/hooks"
19 | },
20 | "iconLibrary": "lucide"
21 | }
22 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "target": "ES6",
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------
/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type React from "react"
2 | import type { Metadata } from "next"
3 | import { Geist, Geist_Mono } from "next/font/google"
4 | import { Analytics } from "@vercel/analytics/next"
5 | import Script from "next/script"
6 | import "./globals.css"
7 |
8 | const _geist = Geist({ subsets: ["latin"] })
9 | const _geistMono = Geist_Mono({ subsets: ["latin"] })
10 |
11 | export const metadata: Metadata = {
12 | title: "OSPO 中文社区 - 开源项目办公室",
13 | description: "探索 OSPO(开源项目办公室)的组织形式、职责运营、国内外案例及相关资源",
14 | generator: "v0.app",
15 | }
16 |
17 | export default function RootLayout({
18 | children,
19 | }: Readonly<{
20 | children: React.ReactNode
21 | }>) {
22 | return (
23 |
24 |
25 | {children}
26 |
27 |
28 |
29 |
37 |
38 |
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/components/ui/avatar.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import * as React from 'react'
4 | import * as AvatarPrimitive from '@radix-ui/react-avatar'
5 |
6 | import { cn } from '@/lib/utils'
7 |
8 | function Avatar({
9 | className,
10 | ...props
11 | }: React.ComponentProps) {
12 | return (
13 |
21 | )
22 | }
23 |
24 | function AvatarImage({
25 | className,
26 | ...props
27 | }: React.ComponentProps) {
28 | return (
29 |
34 | )
35 | }
36 |
37 | function AvatarFallback({
38 | className,
39 | ...props
40 | }: React.ComponentProps) {
41 | return (
42 |
50 | )
51 | }
52 |
53 | export { Avatar, AvatarImage, AvatarFallback }
54 |
--------------------------------------------------------------------------------
/public/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/data/introduction.ts:
--------------------------------------------------------------------------------
1 | export const introductionData = {
2 | benefits: [
3 | "建立系统化的开源战略和治理框架",
4 | "降低开源合规风险和法律问题",
5 | "提升企业在开源社区的影响力",
6 | "吸引和培养开源技术人才",
7 | "促进内外部技术创新和协作",
8 | "优化开源软件的使用和贡献",
9 | ],
10 | sections: {
11 | whatIsOSPO: {
12 | title: "什么是 OSPO?",
13 | content: [
14 | "开源项目办公室(Open Source Program Office,简称 OSPO)是企业内部负责管理和协调开源战略的专门机构。它作为企业与开源社区之间的桥梁,确保企业能够有效地使用、贡献和管理开源软件。",
15 | "OSPO 的核心使命是帮助企业建立健康的开源文化,制定清晰的开源政策,并通过系统化的方法管理开源项目的使用、贡献和发布。",
16 | ],
17 | },
18 | whyNeedOSPO: {
19 | title: "为什么需要 OSPO?",
20 | content:
21 | "随着开源软件在企业中的广泛应用,企业面临着越来越多的挑战:如何确保开源软件的合规使用?如何有效地参与开源社区?如何培养开源文化?OSPO 正是为了解决这些问题而诞生的。",
22 | },
23 | coreValues: {
24 | title: "OSPO 的核心价值",
25 | items: [
26 | {
27 | title: "战略协调",
28 | description: "OSPO 帮助企业制定统一的开源战略,协调各部门的开源活动,确保企业的开源实践与业务目标保持一致。",
29 | },
30 | {
31 | title: "风险管理",
32 | description: "通过建立开源合规流程和工具,OSPO 帮助企业识别和管理开源软件使用中的法律、安全和技术风险。",
33 | },
34 | {
35 | title: "社区参与",
36 | description: "OSPO 促进企业与开源社区的良性互动,帮助员工参与开源项目,提升企业在开源生态中的影响力。",
37 | },
38 | {
39 | title: "文化建设",
40 | description: "通过培训、宣传和激励机制,OSPO 在企业内部培养开源文化,鼓励开放、协作和创新的工作方式。",
41 | },
42 | ],
43 | },
44 | history: {
45 | title: "OSPO 的发展历程",
46 | content: [
47 | "OSPO 的概念最早出现在 2000 年代初期,当时一些科技巨头如 Google、Facebook 和 Microsoft 开始意识到需要专门的团队来管理日益复杂的开源活动。",
48 | "近年来,随着开源软件成为企业数字化转型的关键驱动力,越来越多的企业开始建立自己的 OSPO。从最初的合规管理,到现在的战略协调和社区参与,OSPO 的职能也在不断演进和扩展。",
49 | "今天,OSPO 已经成为企业开源战略的核心组成部分,在全球范围内得到了广泛的认可和实践。",
50 | ],
51 | },
52 | },
53 | }
54 |
--------------------------------------------------------------------------------
/components/ui/badge.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { Slot } from '@radix-ui/react-slot'
3 | import { cva, type VariantProps } from 'class-variance-authority'
4 |
5 | import { cn } from '@/lib/utils'
6 |
7 | const badgeVariants = cva(
8 | 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',
9 | {
10 | variants: {
11 | variant: {
12 | default:
13 | 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
14 | secondary:
15 | 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
16 | destructive:
17 | 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
18 | outline:
19 | 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
20 | },
21 | },
22 | defaultVariants: {
23 | variant: 'default',
24 | },
25 | },
26 | )
27 |
28 | function Badge({
29 | className,
30 | variant,
31 | asChild = false,
32 | ...props
33 | }: React.ComponentProps<'span'> &
34 | VariantProps & { asChild?: boolean }) {
35 | const Comp = asChild ? Slot : 'span'
36 |
37 | return (
38 |
43 | )
44 | }
45 |
46 | export { Badge, badgeVariants }
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OSPO 中文社区网站
2 |
3 | 这是一个关于开源项目办公室(OSPO)的中文社区网站,旨在为国内的 OSPO 从业者提供学习资源和交流平台。
4 |
5 | ## 项目结构
6 |
7 | \`\`\`
8 | ├── app/ # Next.js 应用页面
9 | │ ├── introduction/ # OSPO 简介
10 | │ ├── organization/ # 组织形式
11 | │ ├── operations/ # 职责与运营
12 | │ ├── cases/ # 国内外案例
13 | │ ├── resources/ # 图书与报告
14 | │ ├── community/ # 社区与组织
15 | │ ├── links/ # 友情链接
16 | │ └── contributors/ # 社区贡献榜
17 | ├── data/ # 数据文件(可直接编辑)
18 | │ ├── introduction.ts # 简介页面数据
19 | │ ├── cases.ts # 案例数据
20 | │ ├── resources.ts # 资源数据
21 | │ ├── community.ts # 社区数据
22 | │ ├── links.ts # 链接数据
23 | │ └── contributors.ts # 贡献者数据
24 | └── components/ # React 组件
25 | \`\`\`
26 |
27 | ## 如何贡献
28 |
29 | ### 更新内容
30 |
31 | 所有网站内容都存储在 `data/` 目录下的 TypeScript 文件中。你可以直接编辑这些文件来更新内容:
32 |
33 | 1. **更新案例研究**:编辑 `data/cases.ts`
34 | 2. **添加资源链接**:编辑 `data/resources.ts` 或 `data/links.ts`
35 | 3. **更新社区信息**:编辑 `data/community.ts`
36 | 4. **修改简介内容**:编辑 `data/introduction.ts`
37 |
38 | ### 贡献流程
39 |
40 | 1. Fork 本仓库
41 | 2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`)
42 | 3. 编辑 `data/` 目录下的相关文件
43 | 4. 提交你的修改 (`git commit -m 'Add some AmazingFeature'`)
44 | 5. 推送到分支 (`git push origin feature/AmazingFeature`)
45 | 6. 开启一个 Pull Request
46 |
47 | ### 数据文件说明
48 |
49 | - **TypeScript 类型安全**:所有数据文件都使用 TypeScript,提供类型检查
50 | - **易于维护**:数据和展示逻辑分离,修改内容无需了解 React
51 | - **版本控制友好**:纯文本格式,便于 Git 追踪变更
52 |
53 | ## 本地开发
54 |
55 | \`\`\`bash
56 | # 安装依赖
57 | npm install
58 |
59 | # 启动开发服务器
60 | npm run dev
61 |
62 | # 构建生产版本
63 | npm run build
64 | \`\`\`
65 |
66 | ## 技术栈
67 |
68 | - **框架**:Next.js 16
69 | - **样式**:Tailwind CSS v4
70 | - **组件**:shadcn/ui
71 | - **语言**:TypeScript
72 |
73 | ## 许可证
74 |
75 | MIT License
76 |
77 | ## 联系我们
78 |
79 | 如有任何问题或建议,欢迎通过 GitHub Issues 联系我们。
80 |
--------------------------------------------------------------------------------
/data/contributors.ts:
--------------------------------------------------------------------------------
1 | export interface Contributor {
2 | name: string
3 | avatar?: string
4 | contributions: number
5 | role: string
6 | github?: string
7 | description: string
8 | }
9 |
10 | export const contributorsData: Contributor[] = [
11 | {
12 | name: "张三",
13 | contributions: 156,
14 | role: "核心维护者",
15 | github: "zhangsan",
16 | description: "负责网站架构设计和核心功能开发",
17 | },
18 | {
19 | name: "李四",
20 | contributions: 98,
21 | role: "内容贡献者",
22 | github: "lisi",
23 | description: "撰写和维护 OSPO 案例研究内容",
24 | },
25 | {
26 | name: "王五",
27 | contributions: 87,
28 | role: "技术顾问",
29 | github: "wangwu",
30 | description: "提供技术咨询和代码审查",
31 | },
32 | {
33 | name: "赵六",
34 | contributions: 65,
35 | role: "文档维护者",
36 | github: "zhaoliu",
37 | description: "维护和更新技术文档",
38 | },
39 | {
40 | name: "钱七",
41 | contributions: 54,
42 | role: "设计师",
43 | github: "qianqi",
44 | description: "负责网站 UI/UX 设计",
45 | },
46 | {
47 | name: "孙八",
48 | contributions: 43,
49 | role: "内容贡献者",
50 | github: "sunba",
51 | description: "贡献国际案例和资源链接",
52 | },
53 | {
54 | name: "周九",
55 | contributions: 38,
56 | role: "社区管理",
57 | github: "zhoujiu",
58 | description: "管理社区互动和用户反馈",
59 | },
60 | {
61 | name: "吴十",
62 | contributions: 29,
63 | role: "翻译志愿者",
64 | github: "wushi",
65 | description: "翻译国际资源和文档",
66 | },
67 | {
68 | name: "郑十一",
69 | contributions: 21,
70 | role: "测试工程师",
71 | github: "zhengshiyi",
72 | description: "进行功能测试和问题反馈",
73 | },
74 | {
75 | name: "陈十二",
76 | contributions: 15,
77 | role: "内容贡献者",
78 | github: "chenshier",
79 | description: "贡献工具和资源推荐",
80 | },
81 | ]
82 |
83 | export const contributionStats = {
84 | totalContributors: contributorsData.length,
85 | totalContributions: contributorsData.reduce((sum, c) => sum + c.contributions, 0),
86 | activeContributors: contributorsData.filter((c) => c.contributions > 30).length,
87 | }
88 |
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { Slot } from '@radix-ui/react-slot'
3 | import { cva, type VariantProps } from 'class-variance-authority'
4 |
5 | import { cn } from '@/lib/utils'
6 |
7 | const buttonVariants = cva(
8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9 | {
10 | variants: {
11 | variant: {
12 | default: 'bg-primary text-primary-foreground hover:bg-primary/90',
13 | destructive:
14 | 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
15 | outline:
16 | 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
17 | secondary:
18 | 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
19 | ghost:
20 | 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
21 | link: 'text-primary underline-offset-4 hover:underline',
22 | },
23 | size: {
24 | default: 'h-9 px-4 py-2 has-[>svg]:px-3',
25 | sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
26 | lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
27 | icon: 'size-9',
28 | 'icon-sm': 'size-8',
29 | 'icon-lg': 'size-10',
30 | },
31 | },
32 | defaultVariants: {
33 | variant: 'default',
34 | size: 'default',
35 | },
36 | },
37 | )
38 |
39 | function Button({
40 | className,
41 | variant,
42 | size,
43 | asChild = false,
44 | ...props
45 | }: React.ComponentProps<'button'> &
46 | VariantProps & {
47 | asChild?: boolean
48 | }) {
49 | const Comp = asChild ? Slot : 'button'
50 |
51 | return (
52 |
57 | )
58 | }
59 |
60 | export { Button, buttonVariants }
61 |
--------------------------------------------------------------------------------
/components/ui/card.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | import { cn } from '@/lib/utils'
4 |
5 | function Card({ className, ...props }: React.ComponentProps<'div'>) {
6 | return (
7 |
15 | )
16 | }
17 |
18 | function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
19 | return (
20 |
28 | )
29 | }
30 |
31 | function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
32 | return (
33 |
38 | )
39 | }
40 |
41 | function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
42 | return (
43 |
48 | )
49 | }
50 |
51 | function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
52 | return (
53 |
61 | )
62 | }
63 |
64 | function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
65 | return (
66 |
71 | )
72 | }
73 |
74 | function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
75 | return (
76 |
81 | )
82 | }
83 |
84 | export {
85 | Card,
86 | CardHeader,
87 | CardFooter,
88 | CardTitle,
89 | CardAction,
90 | CardDescription,
91 | CardContent,
92 | }
93 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-v0-project",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "build": "next build",
7 | "dev": "next dev",
8 | "lint": "eslint .",
9 | "start": "next start"
10 | },
11 | "dependencies": {
12 | "@hookform/resolvers": "^3.10.0",
13 | "@radix-ui/react-accordion": "1.2.2",
14 | "@radix-ui/react-alert-dialog": "1.1.4",
15 | "@radix-ui/react-aspect-ratio": "1.1.1",
16 | "@radix-ui/react-avatar": "1.1.2",
17 | "@radix-ui/react-checkbox": "1.1.3",
18 | "@radix-ui/react-collapsible": "1.1.2",
19 | "@radix-ui/react-context-menu": "2.2.4",
20 | "@radix-ui/react-dialog": "1.1.4",
21 | "@radix-ui/react-dropdown-menu": "2.1.4",
22 | "@radix-ui/react-hover-card": "1.1.4",
23 | "@radix-ui/react-label": "2.1.1",
24 | "@radix-ui/react-menubar": "1.1.4",
25 | "@radix-ui/react-navigation-menu": "1.2.3",
26 | "@radix-ui/react-popover": "1.1.4",
27 | "@radix-ui/react-progress": "1.1.1",
28 | "@radix-ui/react-radio-group": "1.2.2",
29 | "@radix-ui/react-scroll-area": "1.2.2",
30 | "@radix-ui/react-select": "2.1.4",
31 | "@radix-ui/react-separator": "1.1.1",
32 | "@radix-ui/react-slider": "1.2.2",
33 | "@radix-ui/react-slot": "1.1.1",
34 | "@radix-ui/react-switch": "1.1.2",
35 | "@radix-ui/react-tabs": "1.1.2",
36 | "@radix-ui/react-toast": "1.2.4",
37 | "@radix-ui/react-toggle": "1.1.1",
38 | "@radix-ui/react-toggle-group": "1.1.1",
39 | "@radix-ui/react-tooltip": "1.1.6",
40 | "@vercel/analytics": "1.3.1",
41 | "autoprefixer": "^10.4.20",
42 | "class-variance-authority": "^0.7.1",
43 | "clsx": "^2.1.1",
44 | "cmdk": "1.0.4",
45 | "date-fns": "4.1.0",
46 | "embla-carousel-react": "8.5.1",
47 | "input-otp": "1.4.1",
48 | "lucide-react": "^0.454.0",
49 | "next": "16.0.10",
50 | "next-themes": "^0.4.6",
51 | "react": "19.2.0",
52 | "react-day-picker": "9.8.0",
53 | "react-dom": "19.2.0",
54 | "react-hook-form": "^7.60.0",
55 | "react-resizable-panels": "^2.1.7",
56 | "recharts": "2.15.4",
57 | "sonner": "^1.7.4",
58 | "tailwind-merge": "^3.3.1",
59 | "tailwindcss-animate": "^1.0.7",
60 | "vaul": "^0.9.9",
61 | "zod": "3.25.76"
62 | },
63 | "devDependencies": {
64 | "@tailwindcss/postcss": "^4.1.9",
65 | "@types/node": "^22",
66 | "@types/react": "^19",
67 | "@types/react-dom": "^19",
68 | "postcss": "^8.5",
69 | "tailwindcss": "^4.1.9",
70 | "tw-animate-css": "1.3.3",
71 | "typescript": "^5"
72 | }
73 | }
--------------------------------------------------------------------------------
/components/site-header.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import Link from "next/link"
4 | import { Button } from "@/components/ui/button"
5 | import { Menu, X } from "lucide-react"
6 | import { useState } from "react"
7 |
8 | export function SiteHeader() {
9 | const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
10 |
11 | const navItems = [
12 | { href: "/", label: "首页" },
13 | { href: "/introduction", label: "OSPO 简介" },
14 | { href: "/organization", label: "组织形式" },
15 | { href: "/operations", label: "职责与运营" },
16 | { href: "/cases", label: "案例研究" },
17 | { href: "/resources", label: "资源中心" },
18 | { href: "/community", label: "社区与组织" },
19 | { href: "/links", label: "友情链接" },
20 | { href: "/contributors", label: "贡献榜" },
21 | ]
22 |
23 | return (
24 |
25 |
26 |
27 |
28 | O
29 |
30 |
OSPO 中文社区
31 |
32 |
33 | {/* Desktop Navigation */}
34 |
45 |
46 | {/* Mobile Menu Button */}
47 |
50 |
51 |
52 | {/* Mobile Navigation */}
53 | {mobileMenuOpen && (
54 |
55 |
67 |
68 | )}
69 |
70 | )
71 | }
72 |
--------------------------------------------------------------------------------
/public/placeholder-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/placeholder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/site-footer.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link"
2 | import { Github, Twitter } from "lucide-react"
3 |
4 | export function SiteFooter() {
5 | return (
6 |
81 | )
82 | }
83 |
--------------------------------------------------------------------------------
/app/introduction/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { CheckCircle2 } from "lucide-react"
5 | import { introductionData } from "@/data/introduction"
6 |
7 | export default function IntroductionPage() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
OSPO 简介
16 |
了解开源项目办公室的定义、价值和核心理念
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {introductionData.sections.whatIsOSPO.title}
25 |
26 |
27 | {introductionData.sections.whatIsOSPO.content.map((paragraph, index) => (
28 | {paragraph}
29 | ))}
30 |
31 |
32 |
33 |
34 |
35 | {introductionData.sections.whyNeedOSPO.title}
36 |
37 |
38 | {introductionData.sections.whyNeedOSPO.content}
39 |
40 | {introductionData.benefits.map((benefit, index) => (
41 |
42 |
43 | {benefit}
44 |
45 | ))}
46 |
47 |
48 |
49 |
50 |
51 |
52 | {introductionData.sections.coreValues.title}
53 |
54 |
55 | {introductionData.sections.coreValues.items.map((item, index) => (
56 |
57 |
{item.title}
58 |
{item.description}
59 |
60 | ))}
61 |
62 |
63 |
64 |
65 |
66 | {introductionData.sections.history.title}
67 |
68 |
69 | {introductionData.sections.history.content.map((paragraph, index) => (
70 | {paragraph}
71 | ))}
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | )
81 | }
82 |
--------------------------------------------------------------------------------
/data/cases.ts:
--------------------------------------------------------------------------------
1 | export const casesData = {
2 | international: [
3 | {
4 | company: "Google",
5 | country: "美国",
6 | description: "Google 的 OSPO 是业界最早和最成熟的之一,管理着数千个开源项目的使用和贡献。",
7 | highlights: ["发布了 Kubernetes、TensorFlow 等重要项目", "建立了完善的开源合规流程", "积极参与开源基金会治理"],
8 | scale: "大型",
9 | },
10 | {
11 | company: "Microsoft",
12 | country: "美国",
13 | description: "Microsoft 从闭源转向拥抱开源,OSPO 在这一转型中发挥了关键作用。",
14 | highlights: ["收购 GitHub 并保持其开放性", "将 .NET 和 VS Code 开源", "成为 Linux 基金会白金会员"],
15 | scale: "大型",
16 | },
17 | {
18 | company: "Meta",
19 | country: "美国",
20 | description: "Meta 的 OSPO 专注于推动前端技术创新和社区建设。",
21 | highlights: ["创建并维护 React 生态系统", "发布 PyTorch 深度学习框架", "建立活跃的开发者社区"],
22 | scale: "大型",
23 | },
24 | {
25 | company: "Red Hat",
26 | country: "美国",
27 | description: "作为开源商业化的先驱,Red Hat 的整个商业模式建立在开源之上。",
28 | highlights: ["主导 Linux 企业级发行版", "贡献 Kubernetes 和容器技术", "培养开源商业生态"],
29 | scale: "大型",
30 | },
31 | {
32 | company: "SAP",
33 | country: "德国",
34 | description: "SAP 通过 OSPO 推动企业软件的开源转型。",
35 | highlights: ["开源 ABAP 开发工具", "参与云原生技术发展", "建立内部开源文化"],
36 | scale: "大型",
37 | },
38 | {
39 | company: "Spotify",
40 | country: "瑞典",
41 | description: "Spotify 的 OSPO 专注于开发者工具和平台建设。",
42 | highlights: ["开源 Backstage 开发者门户", "分享音乐推荐算法", "推动开源最佳实践"],
43 | scale: "中型",
44 | },
45 | ],
46 | domestic: [
47 | {
48 | company: "华为",
49 | description: "华为建立了完善的开源治理体系,是国内开源贡献的领军企业。",
50 | highlights: ["发起 openEuler 和 openGauss 项目", "在 Linux 内核贡献排名前列", "成立开源能力中心"],
51 | scale: "大型",
52 | },
53 | {
54 | company: "阿里巴巴",
55 | description: "阿里巴巴通过开源推动云计算和大数据技术创新。",
56 | highlights: ["开源 Dubbo、RocketMQ 等项目", "捐赠项目给 Apache 基金会", "建立开源协同办公室"],
57 | scale: "大型",
58 | },
59 | {
60 | company: "腾讯",
61 | description: "腾讯积极参与开源社区,推动游戏和社交技术开源。",
62 | highlights: ["开源 TARS 微服务框架", "发布 TencentOS 操作系统", "成立开源联盟"],
63 | scale: "大型",
64 | },
65 | {
66 | company: "百度",
67 | description: "百度专注于 AI 和自动驾驶领域的开源贡献。",
68 | highlights: ["开源 PaddlePaddle 深度学习平台", "发布 Apollo 自动驾驶平台", "推动 AI 技术普及"],
69 | scale: "大型",
70 | },
71 | {
72 | company: "字节跳动",
73 | description: "字节跳动在前端和基础设施领域积极开源。",
74 | highlights: ["开源 Semi Design 设计系统", "贡献云原生技术", "建立开源文化"],
75 | scale: "大型",
76 | },
77 | {
78 | company: "蚂蚁集团",
79 | description: "蚂蚁集团在金融科技和分布式系统领域开源创新。",
80 | highlights: ["开源 SOFAStack 金融级云原生架构", "推动区块链技术开源", "建立开源治理体系"],
81 | scale: "大型",
82 | },
83 | ],
84 | insights: {
85 | commonFeatures: [
86 | {
87 | title: "高层战略支持",
88 | description: "成功的 OSPO 都获得了 CEO 和高管团队的明确支持,开源战略被视为企业整体战略的重要组成部分。",
89 | },
90 | {
91 | title: "专业团队建设",
92 | description: "这些企业都组建了专业的 OSPO 团队,成员具备深厚的技术背景和丰富的社区经验。",
93 | },
94 | {
95 | title: "系统化流程",
96 | description: "建立了完善的开源使用、贡献和发布流程,确保合规性和效率。",
97 | },
98 | {
99 | title: "积极社区参与",
100 | description: "不仅使用开源软件,更积极回馈社区,发布高质量的开源项目。",
101 | },
102 | {
103 | title: "文化培养",
104 | description: "通过培训、激励和宣传,在企业内部建立了浓厚的开源文化。",
105 | },
106 | ],
107 | lessons: [
108 | "从这些成功案例中,我们可以看到 OSPO 的价值不仅在于风险管理和合规控制,更在于推动技术创新、提升企业影响力和培养人才。",
109 | "无论是国际巨头还是国内领军企业,都将开源视为战略投资而非成本中心。他们通过 OSPO 建立了与全球开发者社区的连接,在开源生态中占据了重要位置。",
110 | "对于正在考虑建立 OSPO 的企业,这些案例提供了宝贵的参考。关键是要根据自身的规模、行业特点和战略目标,设计适合的 OSPO 模式,并持续投入和优化。",
111 | ],
112 | },
113 | }
114 |
--------------------------------------------------------------------------------
/app/links/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Button } from "@/components/ui/button"
5 | import { ExternalLink } from "lucide-react"
6 | import { linksData } from "@/data/links"
7 |
8 | export default function LinksPage() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
友情链接
17 |
精选的 OSPO 和开源相关资源链接
18 |
19 |
20 |
21 |
22 |
23 | {linksData.categories.map((category) => (
24 |
25 | {category.title}
26 |
27 | {category.links.map((link) => (
28 |
29 |
30 | {link.name}
31 | {link.url}
32 |
33 |
34 | {link.description}
35 |
41 |
42 |
43 | ))}
44 |
45 |
46 | ))}
47 |
48 |
49 |
50 |
51 | 申请友情链接
52 |
53 | 如果您的网站或组织与 OSPO 和开源相关,欢迎申请加入我们的友情链接。我们会定期审核并更新链接列表。
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 链接说明
67 |
68 |
69 | 以上链接均为外部网站,我们会定期检查和更新。如果您发现任何失效链接或有新的推荐,请联系我们。
70 |
71 | 这些资源涵盖了 OSPO 建设和运营的各个方面,从基础知识到高级实践,从工具平台到社区组织。
72 | 我们建议根据您的需求和兴趣,有选择地探索这些资源。
73 |
74 |
75 | 免责声明:外部链接的内容由各自网站负责,不代表本站观点。
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | )
87 | }
88 |
--------------------------------------------------------------------------------
/data/community.ts:
--------------------------------------------------------------------------------
1 | import { Users, Globe, Building } from "lucide-react"
2 |
3 | export const communityData = {
4 | global: [
5 | {
6 | name: "TODO Group",
7 | description: "全球 OSPO 从业者的开放社区,分享最佳实践和工具",
8 | type: "社区",
9 | icon: "Users",
10 | url: "https://todogroup.org/",
11 | },
12 | {
13 | name: "Linux Foundation",
14 | description: "全球最大的开源基金会,支持众多重要开源项目",
15 | type: "基金会",
16 | icon: "Building",
17 | url: "https://www.linuxfoundation.org/",
18 | },
19 | {
20 | name: "Apache Software Foundation",
21 | description: "支持 Apache 系列开源项目的非营利组织",
22 | type: "基金会",
23 | icon: "Building",
24 | url: "https://www.apache.org/",
25 | },
26 | {
27 | name: "Cloud Native Computing Foundation",
28 | description: "推动云原生技术发展的开源基金会",
29 | type: "基金会",
30 | icon: "Building",
31 | url: "https://www.cncf.io/",
32 | },
33 | {
34 | name: "OpenSSF",
35 | description: "专注于开源软件安全的跨行业组织",
36 | type: "组织",
37 | icon: "Globe",
38 | url: "https://openssf.org/",
39 | },
40 | {
41 | name: "InnerSource Commons",
42 | description: "推广企业内部开源实践的全球社区",
43 | type: "社区",
44 | icon: "Users",
45 | url: "https://innersourcecommons.org/",
46 | },
47 | ],
48 | domestic: [
49 | {
50 | name: "中国开源软件推进联盟",
51 | description: "推动中国开源软件发展的行业联盟",
52 | type: "联盟",
53 | url: "http://www.copu.org.cn/",
54 | },
55 | {
56 | name: "开放原子开源基金会",
57 | description: "中国首个开源基金会,孵化多个重要项目",
58 | type: "基金会",
59 | url: "https://www.openatom.org/",
60 | },
61 | {
62 | name: "LFOSSA Linux软件学园",
63 | description: "Linux 基金会亚太 教育服务,推动区域开源发展",
64 | type: "组织",
65 | url: "https://training.linuxfoundation.cn/",
66 | },
67 | {
68 | name: "OSPO Group",
69 | description: "中国 OSPO 从业者交流社区",
70 | type: "社区",
71 | url: "https://ospo.event/",
72 | },
73 | {
74 | name: "开源之道",
75 | description: "开源之道 共读·对话·连接·参与",
76 | type: "社区",
77 | url: "https://opensourceway.community/",
78 | },
79 | {
80 | name: "OSPO.CC OSPO中文社区",
81 | description: "中国 OSPO 主题的开放知识社区",
82 | type: "社区",
83 | url: "https://ospo.cc/",
84 | },
85 | ],
86 | events: [
87 | {
88 | name: "Open Source Summit",
89 | description: "Linux 基金会主办的全球开源峰会",
90 | frequency: "每年多场",
91 | url: "https://events.linuxfoundation.org/open-source-summit-north-america/",
92 | },
93 | {
94 | name: "OSPOCon",
95 | description: "专注于 OSPO 的国际会议",
96 | frequency: "每年一次",
97 | url: "https://events.linuxfoundation.org/ospocon/",
98 | },
99 | {
100 | name: "KubeCon + CloudNativeCon",
101 | description: "云原生技术的旗舰会议",
102 | frequency: "每年多场",
103 | url: "https://www.cncf.io/kubecon-cloudnativecon-events/",
104 | },
105 | {
106 | name: "OSPO Summit中国",
107 | description: "中国最大的OSPO主题会议",
108 | frequency: "每年一次",
109 | url: "https://www.bagevent.com/event/ospo-summit-2025",
110 | },
111 | {
112 | name: "GOTC 全球开源技术峰会",
113 | description: "开放原子基金会主办的开源峰会",
114 | frequency: "每年一次",
115 | url: "https://gotc.oschina.net/",
116 | },
117 | {
118 | name: "COSCon 中国开源年会",
119 | description: "由开源社主办的社区驱动会议",
120 | frequency: "每年一次",
121 | url: "https://www.coscon.cn/",
122 | },
123 | ],
124 | participation: [
125 | {
126 | title: "加入在线社区",
127 | description: "大多数 OSPO 社区都有 Slack、Discord 或邮件列表。加入这些平台,与全球的 OSPO 从业者交流经验。",
128 | },
129 | {
130 | title: "参加线下活动",
131 | description: "参加开源峰会和 OSPO 专题会议,面对面交流,建立人脉网络。许多会议都有专门的 OSPO 分会场。",
132 | },
133 | {
134 | title: "贡献内容",
135 | description: "分享你的 OSPO 实践经验,撰写博客文章,在会议上演讲。帮助其他企业建立和改进他们的 OSPO。",
136 | },
137 | {
138 | title: "参与项目",
139 | description: "TODO Group 等社区有许多开源项目,如 OSPO 工具和指南。参与这些项目的开发和维护。",
140 | },
141 | ],
142 | }
143 |
144 | export const iconMap = {
145 | Users,
146 | Globe,
147 | Building,
148 | }
149 |
--------------------------------------------------------------------------------
/data/links.ts:
--------------------------------------------------------------------------------
1 | export const linksData = {
2 | categories: [
3 | {
4 | title: "OSPO 资源",
5 | links: [
6 | {
7 | name: "TODO Group",
8 | url: "https://todogroup.org",
9 | description: "OSPO 最佳实践和工具",
10 | },
11 | {
12 | name: "OSPO 101",
13 | url: "https://ospo101.org",
14 | description: "OSPO 入门课程",
15 | },
16 | {
17 | name: "OSPO Book",
18 | url: "https://ospobook.org",
19 | description: "OSPO 实践指南",
20 | },
21 | {
22 | name: "CHAOSS",
23 | url: "https://chaoss.community",
24 | description: "开源项目健康度指标",
25 | },
26 | ],
27 | },
28 | {
29 | title: "开源基金会",
30 | links: [
31 | {
32 | name: "Linux Foundation",
33 | url: "https://linuxfoundation.org",
34 | description: "全球最大的开源基金会",
35 | },
36 | {
37 | name: "Apache Software Foundation",
38 | url: "https://apache.org",
39 | description: "Apache 项目基金会",
40 | },
41 | {
42 | name: "Cloud Native Computing Foundation",
43 | url: "https://cncf.io",
44 | description: "云原生技术基金会",
45 | },
46 | {
47 | name: "开放原子开源基金会",
48 | url: "https://openatom.org",
49 | description: "中国首个开源基金会",
50 | },
51 | ],
52 | },
53 | {
54 | title: "合规与安全",
55 | links: [
56 | {
57 | name: "OpenChain",
58 | url: "https://openchainproject.org",
59 | description: "开源合规标准",
60 | },
61 | {
62 | name: "SPDX",
63 | url: "https://spdx.dev",
64 | description: "软件包数据交换标准",
65 | },
66 | {
67 | name: "OpenSSF",
68 | url: "https://openssf.org",
69 | description: "开源安全基金会",
70 | },
71 | {
72 | name: "ClearlyDefined",
73 | url: "https://clearlydefined.io",
74 | description: "开源组件元数据",
75 | },
76 | ],
77 | },
78 | {
79 | title: "开源社区",
80 | links: [
81 | {
82 | name: "GitHub",
83 | url: "https://github.com",
84 | description: "全球最大的代码托管平台",
85 | },
86 | {
87 | name: "GitLab",
88 | url: "https://gitlab.com",
89 | description: "DevOps 平台",
90 | },
91 | {
92 | name: "Gitee",
93 | url: "https://gitee.com",
94 | description: "中国领先的代码托管平台",
95 | },
96 | {
97 | name: "Stack Overflow",
98 | url: "https://stackoverflow.com",
99 | description: "开发者问答社区",
100 | },
101 | ],
102 | },
103 | {
104 | title: "学习资源",
105 | links: [
106 | {
107 | name: "Open Source Guides",
108 | url: "https://opensource.guide",
109 | description: "GitHub 开源指南",
110 | },
111 | {
112 | name: "The Linux Foundation Training",
113 | url: "https://training.linuxfoundation.org",
114 | description: "Linux 基金会培训",
115 | },
116 | {
117 | name: "InnerSource Commons",
118 | url: "https://innersourcecommons.org",
119 | description: "企业内部开源实践",
120 | },
121 | {
122 | name: "Open Source Initiative",
123 | url: "https://opensource.org",
124 | description: "开源定义和许可证",
125 | },
126 | ],
127 | },
128 | {
129 | title: "工具与平台",
130 | links: [
131 | {
132 | name: "FOSSology",
133 | url: "https://fossology.org",
134 | description: "开源许可证扫描",
135 | },
136 | {
137 | name: "Backstage",
138 | url: "https://backstage.io",
139 | description: "开发者门户平台",
140 | },
141 | {
142 | name: "Renovate",
143 | url: "https://renovatebot.com",
144 | description: "依赖更新自动化",
145 | },
146 | {
147 | name: "Snyk",
148 | url: "https://snyk.io",
149 | description: "开源安全扫描",
150 | },
151 | ],
152 | },
153 | ],
154 | }
155 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @import 'tailwindcss';
2 | @import 'tw-animate-css';
3 |
4 | @custom-variant dark (&:is(.dark *));
5 |
6 | :root {
7 | --background: oklch(1 0 0);
8 | --foreground: oklch(0.145 0 0);
9 | --card: oklch(1 0 0);
10 | --card-foreground: oklch(0.145 0 0);
11 | --popover: oklch(1 0 0);
12 | --popover-foreground: oklch(0.145 0 0);
13 | --primary: oklch(0.205 0 0);
14 | --primary-foreground: oklch(0.985 0 0);
15 | --secondary: oklch(0.97 0 0);
16 | --secondary-foreground: oklch(0.205 0 0);
17 | --muted: oklch(0.97 0 0);
18 | --muted-foreground: oklch(0.556 0 0);
19 | --accent: oklch(0.97 0 0);
20 | --accent-foreground: oklch(0.205 0 0);
21 | --destructive: oklch(0.577 0.245 27.325);
22 | --destructive-foreground: oklch(0.577 0.245 27.325);
23 | --border: oklch(0.922 0 0);
24 | --input: oklch(0.922 0 0);
25 | --ring: oklch(0.708 0 0);
26 | --chart-1: oklch(0.646 0.222 41.116);
27 | --chart-2: oklch(0.6 0.118 184.704);
28 | --chart-3: oklch(0.398 0.07 227.392);
29 | --chart-4: oklch(0.828 0.189 84.429);
30 | --chart-5: oklch(0.769 0.188 70.08);
31 | --radius: 0.625rem;
32 | --sidebar: oklch(0.985 0 0);
33 | --sidebar-foreground: oklch(0.145 0 0);
34 | --sidebar-primary: oklch(0.205 0 0);
35 | --sidebar-primary-foreground: oklch(0.985 0 0);
36 | --sidebar-accent: oklch(0.97 0 0);
37 | --sidebar-accent-foreground: oklch(0.205 0 0);
38 | --sidebar-border: oklch(0.922 0 0);
39 | --sidebar-ring: oklch(0.708 0 0);
40 | }
41 |
42 | .dark {
43 | --background: oklch(0.145 0 0);
44 | --foreground: oklch(0.985 0 0);
45 | --card: oklch(0.145 0 0);
46 | --card-foreground: oklch(0.985 0 0);
47 | --popover: oklch(0.145 0 0);
48 | --popover-foreground: oklch(0.985 0 0);
49 | --primary: oklch(0.985 0 0);
50 | --primary-foreground: oklch(0.205 0 0);
51 | --secondary: oklch(0.269 0 0);
52 | --secondary-foreground: oklch(0.985 0 0);
53 | --muted: oklch(0.269 0 0);
54 | --muted-foreground: oklch(0.708 0 0);
55 | --accent: oklch(0.269 0 0);
56 | --accent-foreground: oklch(0.985 0 0);
57 | --destructive: oklch(0.396 0.141 25.723);
58 | --destructive-foreground: oklch(0.637 0.237 25.331);
59 | --border: oklch(0.269 0 0);
60 | --input: oklch(0.269 0 0);
61 | --ring: oklch(0.439 0 0);
62 | --chart-1: oklch(0.488 0.243 264.376);
63 | --chart-2: oklch(0.696 0.17 162.48);
64 | --chart-3: oklch(0.769 0.188 70.08);
65 | --chart-4: oklch(0.627 0.265 303.9);
66 | --chart-5: oklch(0.645 0.246 16.439);
67 | --sidebar: oklch(0.205 0 0);
68 | --sidebar-foreground: oklch(0.985 0 0);
69 | --sidebar-primary: oklch(0.488 0.243 264.376);
70 | --sidebar-primary-foreground: oklch(0.985 0 0);
71 | --sidebar-accent: oklch(0.269 0 0);
72 | --sidebar-accent-foreground: oklch(0.985 0 0);
73 | --sidebar-border: oklch(0.269 0 0);
74 | --sidebar-ring: oklch(0.439 0 0);
75 | }
76 |
77 | @theme inline {
78 | --font-sans: 'Geist', 'Geist Fallback';
79 | --font-mono: 'Geist Mono', 'Geist Mono Fallback';
80 | --color-background: var(--background);
81 | --color-foreground: var(--foreground);
82 | --color-card: var(--card);
83 | --color-card-foreground: var(--card-foreground);
84 | --color-popover: var(--popover);
85 | --color-popover-foreground: var(--popover-foreground);
86 | --color-primary: var(--primary);
87 | --color-primary-foreground: var(--primary-foreground);
88 | --color-secondary: var(--secondary);
89 | --color-secondary-foreground: var(--secondary-foreground);
90 | --color-muted: var(--muted);
91 | --color-muted-foreground: var(--muted-foreground);
92 | --color-accent: var(--accent);
93 | --color-accent-foreground: var(--accent-foreground);
94 | --color-destructive: var(--destructive);
95 | --color-destructive-foreground: var(--destructive-foreground);
96 | --color-border: var(--border);
97 | --color-input: var(--input);
98 | --color-ring: var(--ring);
99 | --color-chart-1: var(--chart-1);
100 | --color-chart-2: var(--chart-2);
101 | --color-chart-3: var(--chart-3);
102 | --color-chart-4: var(--chart-4);
103 | --color-chart-5: var(--chart-5);
104 | --radius-sm: calc(var(--radius) - 4px);
105 | --radius-md: calc(var(--radius) - 2px);
106 | --radius-lg: var(--radius);
107 | --radius-xl: calc(var(--radius) + 4px);
108 | --color-sidebar: var(--sidebar);
109 | --color-sidebar-foreground: var(--sidebar-foreground);
110 | --color-sidebar-primary: var(--sidebar-primary);
111 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
112 | --color-sidebar-accent: var(--sidebar-accent);
113 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
114 | --color-sidebar-border: var(--sidebar-border);
115 | --color-sidebar-ring: var(--sidebar-ring);
116 | }
117 |
118 | @layer base {
119 | * {
120 | @apply border-border outline-ring/50;
121 | }
122 | body {
123 | @apply bg-background text-foreground;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/app/globals.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 | @import "tw-animate-css";
3 |
4 | @custom-variant dark (&:is(.dark *));
5 |
6 | :root {
7 | --background: oklch(0.98 0.005 120);
8 | --foreground: oklch(0.15 0.01 180);
9 | --card: oklch(1 0 0);
10 | --card-foreground: oklch(0.15 0.01 180);
11 | --popover: oklch(1 0 0);
12 | --popover-foreground: oklch(0.15 0.01 180);
13 | --primary: oklch(0.45 0.15 160);
14 | --primary-foreground: oklch(0.98 0.005 120);
15 | --secondary: oklch(0.92 0.01 120);
16 | --secondary-foreground: oklch(0.15 0.01 180);
17 | --muted: oklch(0.95 0.005 120);
18 | --muted-foreground: oklch(0.5 0.01 180);
19 | --accent: oklch(0.45 0.15 160);
20 | --accent-foreground: oklch(0.98 0.005 120);
21 | --destructive: oklch(0.577 0.245 27.325);
22 | --destructive-foreground: oklch(0.98 0.005 120);
23 | --border: oklch(0.88 0.01 120);
24 | --input: oklch(0.88 0.01 120);
25 | --ring: oklch(0.45 0.15 160);
26 | --chart-1: oklch(0.646 0.222 41.116);
27 | --chart-2: oklch(0.6 0.118 184.704);
28 | --chart-3: oklch(0.398 0.07 227.392);
29 | --chart-4: oklch(0.828 0.189 84.429);
30 | --chart-5: oklch(0.769 0.188 70.08);
31 | --radius: 0.625rem;
32 | --sidebar: oklch(0.985 0 0);
33 | --sidebar-foreground: oklch(0.145 0 0);
34 | --sidebar-primary: oklch(0.205 0 0);
35 | --sidebar-primary-foreground: oklch(0.985 0 0);
36 | --sidebar-accent: oklch(0.97 0 0);
37 | --sidebar-accent-foreground: oklch(0.205 0 0);
38 | --sidebar-border: oklch(0.922 0 0);
39 | --sidebar-ring: oklch(0.708 0 0);
40 | }
41 |
42 | .dark {
43 | --background: oklch(0.12 0.01 180);
44 | --foreground: oklch(0.95 0.005 120);
45 | --card: oklch(0.16 0.01 180);
46 | --card-foreground: oklch(0.95 0.005 120);
47 | --popover: oklch(0.16 0.01 180);
48 | --popover-foreground: oklch(0.95 0.005 120);
49 | --primary: oklch(0.55 0.18 160);
50 | --primary-foreground: oklch(0.12 0.01 180);
51 | --secondary: oklch(0.2 0.01 180);
52 | --secondary-foreground: oklch(0.95 0.005 120);
53 | --muted: oklch(0.2 0.01 180);
54 | --muted-foreground: oklch(0.65 0.01 180);
55 | --accent: oklch(0.55 0.18 160);
56 | --accent-foreground: oklch(0.12 0.01 180);
57 | --destructive: oklch(0.396 0.141 25.723);
58 | --destructive-foreground: oklch(0.95 0.005 120);
59 | --border: oklch(0.24 0.01 180);
60 | --input: oklch(0.24 0.01 180);
61 | --ring: oklch(0.55 0.18 160);
62 | --chart-1: oklch(0.488 0.243 264.376);
63 | --chart-2: oklch(0.696 0.17 162.48);
64 | --chart-3: oklch(0.769 0.188 70.08);
65 | --chart-4: oklch(0.627 0.265 303.9);
66 | --chart-5: oklch(0.645 0.246 16.439);
67 | --sidebar: oklch(0.205 0 0);
68 | --sidebar-foreground: oklch(0.985 0 0);
69 | --sidebar-primary: oklch(0.488 0.243 264.376);
70 | --sidebar-primary-foreground: oklch(0.985 0 0);
71 | --sidebar-accent: oklch(0.269 0 0);
72 | --sidebar-accent-foreground: oklch(0.985 0 0);
73 | --sidebar-border: oklch(0.269 0 0);
74 | --sidebar-ring: oklch(0.439 0 0);
75 | }
76 |
77 | @theme inline {
78 | /* optional: --font-sans, --font-serif, --font-mono if they are applied in the layout.tsx */
79 | --color-background: var(--background);
80 | --color-foreground: var(--foreground);
81 | --color-card: var(--card);
82 | --color-card-foreground: var(--card-foreground);
83 | --color-popover: var(--popover);
84 | --color-popover-foreground: var(--popover-foreground);
85 | --color-primary: var(--primary);
86 | --color-primary-foreground: var(--primary-foreground);
87 | --color-secondary: var(--secondary);
88 | --color-secondary-foreground: var(--secondary-foreground);
89 | --color-muted: var(--muted);
90 | --color-muted-foreground: var(--muted-foreground);
91 | --color-accent: var(--accent);
92 | --color-accent-foreground: var(--accent-foreground);
93 | --color-destructive: var(--destructive);
94 | --color-destructive-foreground: var(--destructive-foreground);
95 | --color-border: var(--border);
96 | --color-input: var(--input);
97 | --color-ring: var(--ring);
98 | --color-chart-1: var(--chart-1);
99 | --color-chart-2: var(--chart-2);
100 | --color-chart-3: var(--chart-3);
101 | --color-chart-4: var(--chart-4);
102 | --color-chart-5: var(--chart-5);
103 | --radius-sm: calc(var(--radius) - 4px);
104 | --radius-md: calc(var(--radius) - 2px);
105 | --radius-lg: var(--radius);
106 | --radius-xl: calc(var(--radius) + 4px);
107 | --color-sidebar: var(--sidebar);
108 | --color-sidebar-foreground: var(--sidebar-foreground);
109 | --color-sidebar-primary: var(--sidebar-primary);
110 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
111 | --color-sidebar-accent: var(--sidebar-accent);
112 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
113 | --color-sidebar-border: var(--sidebar-border);
114 | --color-sidebar-ring: var(--sidebar-ring);
115 | }
116 |
117 | @layer base {
118 | * {
119 | @apply border-border outline-ring/50;
120 | }
121 | body {
122 | @apply bg-background text-foreground;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/data/resources.ts:
--------------------------------------------------------------------------------
1 | export const resourcesData = {
2 | projects: [
3 | {
4 | name: "OSPO 网站开源项目",
5 | description:
6 | "为新兴 OSPO 团队提供网站参考模板,帮助其快速启动 OSPO 门户网站建设。基于 Next.js 构建,支持数据与展示分离,便于社区协作维护。",
7 | url: "https://github.com/ospocc/v0-ospo",
8 | category: "网站模板",
9 | features: ["开箱即用", "数据分离", "响应式设计", "社区驱动"],
10 | },
11 | {
12 | name: "OSPO 微信表情包",
13 | description: "一组 OSPO 与开源主题的微信表情包,为开源社区交流增添趣味。适用于日常沟通、社区活动宣传等场景。",
14 | url: "#",
15 | category: "社区资源",
16 | versions: [
17 | {
18 | name: "基础版",
19 | description: "通用表情包,适合日常交流",
20 | url: "https://w.url.cn/s/AVJL7JY",
21 | note: "请在手机微信中打开",
22 | },
23 | {
24 | name: "开源版",
25 | description: "开源文化主题表情",
26 | url: "https://w.url.cn/s/AsgIXzk",
27 | note: "请在手机微信中打开",
28 | },
29 | {
30 | name: "OSPO版",
31 | description: "OSPO 工作场景专属表情",
32 | url: "https://w.url.cn/s/AlckGiA",
33 | note: "请在手机微信中打开",
34 | },
35 | {
36 | name: "OSPO英文版",
37 | description: "面向国际社区的英文版本",
38 | url: "https://w.url.cn/s/AXPlvIo",
39 | note: "请在手机微信中打开",
40 | },
41 | ],
42 | },
43 | ],
44 | books: [
45 | {
46 | title: "OSPO Book | OSPO 指南",
47 | author: "TODO Group",
48 | description: "为各类型的组织提供了一份OSPO知识参考",
49 | type: "在线书籍",
50 | url: "https://ospobook.todogroup.org/zh/",
51 | },
52 | {
53 | title: "The Good Governance Handbook | 开源治理良策",
54 | author: "GGI",
55 | description: "OSPO 联盟开发并维护的 OSS 良好治理倡议(或 GGI)蓝图",
56 | type: "在线书籍",
57 | url: "https://ospo-alliance.org/ggi/zh_hans/",
58 | },
59 | {
60 | title: "The Open Source Way",
61 | author: "Red Hat",
62 | description: "全面介绍开源社区的运作方式和最佳实践",
63 | type: "在线书籍",
64 | url: "https://www.theopensourceway.org/",
65 | },
66 | {
67 | title: "Open Source Program Office Guide",
68 | author: "TODO Group",
69 | description: "OSPO 建设和运营的权威指南",
70 | type: "指南",
71 | url: "https://todogroup.org/resources/guides/",
72 | },
73 | {
74 | title: "Managing Open Source Projects",
75 | author: "Linux Foundation",
76 | description: "开源项目管理的实用手册",
77 | type: "手册",
78 | url: "https://www.linuxfoundation.org/resources/open-source-guides",
79 | },
80 | {
81 | title: "Open Source Compliance in the Enterprise",
82 | author: "Ibrahim Haddad",
83 | description: "企业开源合规管理的深度解析",
84 | type: "专著",
85 | url: "https://www.linuxfoundation.org/research/open-source-compliance-in-the-enterprise",
86 | },
87 | ],
88 | reports: [
89 | {
90 | title: "2024 年开源状态报告",
91 | organization: "Linux Foundation",
92 | year: "2024",
93 | description: "全球开源发展趋势和统计数据",
94 | url: "https://www.linuxfoundation.org/research/2024-state-of-open-source",
95 | },
96 | {
97 | title: "OSPO 调查报告",
98 | organization: "TODO Group",
99 | year: "2024",
100 | description: "全球 OSPO 现状和发展趋势调查",
101 | url: "https://todogroup.org/resources/survey/",
102 | },
103 | {
104 | title: "企业开源战略白皮书",
105 | organization: "CNCF",
106 | year: "2024",
107 | description: "云原生时代的企业开源战略",
108 | url: "https://www.cncf.io/reports/",
109 | },
110 | {
111 | title: "开源安全与风险管理",
112 | organization: "OpenSSF",
113 | year: "2024",
114 | description: "开源软件供应链安全最佳实践",
115 | url: "https://openssf.org/resources/",
116 | },
117 | {
118 | title: "中国开源发展蓝皮书",
119 | organization: "中国开源软件推进联盟",
120 | year: "2024",
121 | description: "中国开源生态发展现状和趋势",
122 | url: "https://www.copu.org.cn/",
123 | },
124 | {
125 | title: "InnerSource 实践指南",
126 | organization: "InnerSource Commons",
127 | year: "2023",
128 | description: "企业内部开源协作模式",
129 | url: "https://innersourcecommons.org/learn/",
130 | },
131 | ],
132 | tools: [
133 | {
134 | name: "FOSSology",
135 | description: "开源许可证合规扫描工具",
136 | category: "合规工具",
137 | url: "https://www.fossology.org/",
138 | },
139 | {
140 | name: "ClearlyDefined",
141 | description: "开源组件元数据和许可证信息",
142 | category: "合规工具",
143 | url: "https://clearlydefined.io/",
144 | },
145 | {
146 | name: "SPDX",
147 | description: "软件包数据交换标准",
148 | category: "标准",
149 | url: "https://spdx.dev/",
150 | },
151 | {
152 | name: "Renovate",
153 | description: "自动化依赖更新工具",
154 | category: "管理工具",
155 | url: "https://www.mend.io/renovate/",
156 | },
157 | {
158 | name: "Backstage",
159 | description: "开发者门户平台",
160 | category: "平台",
161 | url: "https://backstage.io/",
162 | },
163 | {
164 | name: "OpenChain",
165 | description: "开源合规认证标准",
166 | category: "标准",
167 | url: "https://www.openchainproject.org/",
168 | },
169 | ],
170 | learningPaths: [
171 | {
172 | level: "初学者",
173 | description:
174 | "建议从《The Open Source Way》开始,了解开源的基本理念和文化。然后阅读《Open Source Program Office Guide》,掌握 OSPO 的基础知识。",
175 | },
176 | {
177 | level: "实践者",
178 | description:
179 | "深入学习《Open Source Compliance in the Enterprise》,掌握合规管理的实践方法。同时关注最新的调查报告和白皮书,了解行业趋势和最佳实践。",
180 | },
181 | {
182 | level: "管理者",
183 | description:
184 | "重点阅读各类战略白皮书和调查报告,了解 OSPO 的商业价值和投资回报。学习成功案例,为企业制定合适的开源战略。",
185 | },
186 | ],
187 | }
188 |
--------------------------------------------------------------------------------
/app/cases/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Badge } from "@/components/ui/badge"
5 | import { casesData } from "@/data/cases"
6 |
7 | export default function CasesPage() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
OSPO 国内外案例
16 |
学习全球领先企业的 OSPO 实践经验和成功案例
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
国际案例
25 | {casesData.international.length} 个案例
26 |
27 |
28 | {casesData.international.map((case_) => (
29 |
30 |
31 |
32 | {case_.company}
33 | {case_.scale}
34 |
35 |
36 | {case_.country} · {case_.description}
37 |
38 |
39 |
40 | 主要成就:
41 |
42 | {case_.highlights.map((highlight, index) => (
43 | -
44 |
45 | {highlight}
46 |
47 | ))}
48 |
49 |
50 |
51 | ))}
52 |
53 |
54 |
55 |
56 |
57 |
国内案例
58 | {casesData.domestic.length} 个案例
59 |
60 |
61 | {casesData.domestic.map((case_) => (
62 |
63 |
64 |
65 | {case_.company}
66 | {case_.scale}
67 |
68 | {case_.description}
69 |
70 |
71 | 主要成就:
72 |
73 | {case_.highlights.map((highlight, index) => (
74 | -
75 |
76 | {highlight}
77 |
78 | ))}
79 |
80 |
81 |
82 | ))}
83 |
84 |
85 |
86 |
87 |
88 |
89 | 案例分析:共同特点
90 |
91 |
92 | {casesData.insights.commonFeatures.map((feature, index) => (
93 |
94 |
95 | {index + 1}. {feature.title}
96 |
97 |
{feature.description}
98 |
99 | ))}
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | 经验启示
108 |
109 |
110 | {casesData.insights.lessons.map((lesson, index) => (
111 | {lesson}
112 | ))}
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | )
123 | }
124 |
--------------------------------------------------------------------------------
/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Button } from "@/components/ui/button"
4 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
5 | import { ArrowRight, BookOpen, Building2, Users, FileText, Globe, LinkIcon } from "lucide-react"
6 | import Link from "next/link"
7 |
8 | export default function HomePage() {
9 | const features = [
10 | {
11 | icon: BookOpen,
12 | title: "OSPO 简介",
13 | description: "了解开源项目办公室的定义、价值和核心理念",
14 | href: "/introduction",
15 | },
16 | {
17 | icon: Building2,
18 | title: "组织形式",
19 | description: "探索不同规模企业的 OSPO 组织架构和团队配置",
20 | href: "/organization",
21 | },
22 | {
23 | icon: Users,
24 | title: "职责与运营",
25 | description: "深入了解 OSPO 的日常职责、工作流程和最佳实践",
26 | href: "/operations",
27 | },
28 | {
29 | icon: Globe,
30 | title: "国内外案例",
31 | description: "学习全球领先企业的 OSPO 实践经验和成功案例",
32 | href: "/cases",
33 | },
34 | {
35 | icon: FileText,
36 | title: "图书与报告",
37 | description: "获取权威的 OSPO 相关书籍、研究报告和白皮书",
38 | href: "/resources",
39 | },
40 | {
41 | icon: LinkIcon,
42 | title: "社区与组织",
43 | description: "连接全球 OSPO 社区和相关开源组织",
44 | href: "/community",
45 | },
46 | ]
47 |
48 | return (
49 |
50 |
51 |
52 |
53 | {/* Hero Section */}
54 |
55 | {/* 背景图层 */}
56 |
62 | {/* 渐变叠加层确保文字可读性 */}
63 |
64 |
65 |
66 |
67 |
68 | 开源项目办公室
69 | OSPO 中文社区
70 |
71 |
72 | 探索企业开源战略的核心机构,连接全球 OSPO 实践者,推动开源生态健康发展
73 |
74 |
75 |
81 |
84 |
85 |
86 |
87 |
88 |
89 | {/* Features Grid */}
90 |
91 |
92 |
93 |
探索 OSPO 的各个方面
94 |
全面了解开源项目办公室的组织、运营和最佳实践
95 |
96 |
97 |
98 | {features.map((feature) => (
99 |
100 |
101 |
102 |
103 |
104 |
105 | {feature.title}
106 | {feature.description}
107 |
108 |
109 |
110 | ))}
111 |
112 |
113 |
114 |
115 | {/* Stats Section */}
116 |
117 |
118 |
119 |
120 |
500+
121 |
全球 OSPO 组织
122 |
123 |
124 |
1000+
125 |
开源项目管理
126 |
127 |
128 |
50+
129 |
国内外案例
130 |
131 |
132 |
133 |
134 |
135 | {/* CTA Section */}
136 |
137 |
138 |
139 |
140 | 准备建立您的 OSPO?
141 |
142 | 从全球领先企业的实践中学习,获取专业指导和资源支持,开启您的开源战略之旅
143 |
144 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | )
159 | }
160 |
--------------------------------------------------------------------------------
/app/community/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Button } from "@/components/ui/button"
5 | import { ExternalLink, Users } from "lucide-react"
6 | import { communityData, iconMap } from "@/data/community"
7 |
8 | export default function CommunityPage() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
OSPO 相关社区与组织
17 |
连接全球 OSPO 社区和相关开源组织
18 |
19 |
20 |
21 |
22 |
23 |
24 | 国际社区与组织
25 |
26 | {communityData.global.map((community) => {
27 | const IconComponent = iconMap[community.icon as keyof typeof iconMap]
28 | return (
29 |
30 |
31 |
32 |
33 |
34 | {community.name}
35 | {community.type}
36 |
37 |
38 | {community.description}
39 |
45 |
46 |
47 | )
48 | })}
49 |
50 |
51 |
52 |
53 | 国内社区与组织
54 |
55 | {communityData.domestic.map((community) => (
56 |
57 |
58 | {community.name}
59 | {community.type}
60 |
61 |
62 | {community.description}
63 |
69 |
70 |
71 | ))}
72 |
73 |
74 |
75 |
76 | 重要活动与会议
77 |
78 | {communityData.events.map((event) => (
79 |
80 |
81 |
82 | {event.name}
83 |
84 | {event.frequency}
85 |
86 |
87 |
88 |
89 | {event.description}
90 |
96 |
97 |
98 | ))}
99 |
100 |
101 |
102 |
103 |
104 |
105 | 如何参与社区
106 |
107 |
108 | {communityData.participation.map((item, index) => (
109 |
110 |
{item.title}
111 |
{item.description}
112 |
113 | ))}
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | 加入我们的社区
123 |
124 | OSPO 中文社区致力于连接国内的 OSPO
125 | 从业者,分享实践经验,推动开源生态健康发展。欢迎加入我们的微信群和邮件列表。
126 |
127 |
128 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | )
144 | }
145 |
--------------------------------------------------------------------------------
/app/organization/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Users, Building, Briefcase } from "lucide-react"
5 |
6 | export default function OrganizationPage() {
7 | const models = [
8 | {
9 | icon: Users,
10 | title: "虚拟团队模式",
11 | description: "适合初创企业和小型组织",
12 | details: ["由不同部门的成员兼职组成", "灵活的协作方式", "较低的运营成本", "适合开源活动较少的企业"],
13 | },
14 | {
15 | icon: Briefcase,
16 | title: "专职团队模式",
17 | description: "适合中型企业",
18 | details: ["3-5 人的专职团队", "明确的职责分工", "系统化的流程管理", "平衡成本与效率"],
19 | },
20 | {
21 | icon: Building,
22 | title: "独立部门模式",
23 | description: "适合大型企业和科技公司",
24 | details: ["10+ 人的完整组织架构", "多个专业化子团队", "战略级别的决策权", "全面的开源生态管理"],
25 | },
26 | ]
27 |
28 | const roles = [
29 | {
30 | title: "OSPO 负责人",
31 | description: "制定开源战略,协调各方资源,对外代表企业",
32 | },
33 | {
34 | title: "开源合规专家",
35 | description: "管理开源许可证合规,审查代码使用,降低法律风险",
36 | },
37 | {
38 | title: "社区关系经理",
39 | description: "维护社区关系,组织活动,提升企业影响力",
40 | },
41 | {
42 | title: "技术顾问",
43 | description: "提供技术指导,评估开源项目,支持内部开发",
44 | },
45 | {
46 | title: "培训与推广",
47 | description: "开展内部培训,推广开源文化,分享最佳实践",
48 | },
49 | ]
50 |
51 | return (
52 |
53 |
54 |
55 |
56 |
57 |
58 |
OSPO 组织形式
59 |
探索不同规模企业的 OSPO 组织架构和团队配置
60 |
61 |
62 |
63 |
64 |
65 |
66 | 三种主要组织模式
67 |
68 | {models.map((model) => (
69 |
70 |
71 |
72 |
73 |
74 | {model.title}
75 | {model.description}
76 |
77 |
78 |
79 | {model.details.map((detail, index) => (
80 | -
81 |
82 | {detail}
83 |
84 | ))}
85 |
86 |
87 |
88 | ))}
89 |
90 |
91 |
92 |
93 | 核心团队角色
94 |
95 | {roles.map((role) => (
96 |
97 |
98 | {role.title}
99 |
100 |
101 | {role.description}
102 |
103 |
104 | ))}
105 |
106 |
107 |
108 |
109 |
110 |
111 | 组织架构设计原则
112 |
113 |
114 |
115 |
1. 与企业规模匹配
116 |
117 | OSPO 的规模和结构应该与企业的整体规模、开源活动的复杂度相匹配。
118 | 初创企业可以从虚拟团队开始,随着业务发展逐步扩展。
119 |
120 |
121 |
122 |
2. 明确汇报关系
123 |
124 | OSPO 通常向 CTO、工程副总裁或法务部门汇报。 汇报关系应该确保 OSPO 有足够的权威和资源来执行其职责。
125 |
126 |
127 |
128 |
3. 跨部门协作
129 |
130 | OSPO 需要与工程、法务、市场、人力资源等多个部门密切合作。 建立有效的沟通机制和协作流程至关重要。
131 |
132 |
133 |
134 |
4. 灵活性与可扩展性
135 |
136 | 组织架构应该具有足够的灵活性,能够随着企业开源战略的演进而调整和扩展。
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | 不同阶段的组织演进
147 |
148 |
149 |
150 |
初创阶段(0-6 个月)
151 |
152 | 1-2 人的虚拟团队,专注于建立基本的开源政策和合规流程。
153 | 主要任务是评估现状、制定策略、建立基础设施。
154 |
155 |
156 |
157 |
成长阶段(6-18 个月)
158 |
159 | 3-5 人的专职团队,开始系统化地管理开源活动。 扩展职能包括社区参与、内部培训、工具建设等。
160 |
161 |
162 |
163 |
成熟阶段(18 个月以上)
164 |
165 | 10+ 人的完整组织,具备战略规划、合规管理、社区运营、技术支持等全方位能力。
166 | 成为企业开源战略的核心驱动力。
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | )
179 | }
180 |
--------------------------------------------------------------------------------
/app/contributors/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Badge } from "@/components/ui/badge"
5 | import { Button } from "@/components/ui/button"
6 | import { Avatar, AvatarFallback } from "@/components/ui/avatar"
7 | import { Github, Award, Users, GitPullRequest, ExternalLink } from "lucide-react"
8 | import { contributorsData, contributionStats } from "@/data/contributors"
9 |
10 | export default function ContributorsPage() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
社区贡献榜
19 |
感谢所有为 OSPO 中文社区做出贡献的伙伴们
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 总贡献者
30 |
31 |
32 |
33 | {contributionStats.totalContributors}
34 | 来自社区的贡献者
35 |
36 |
37 |
38 |
39 | 总贡献数
40 |
41 |
42 |
43 | {contributionStats.totalContributions}
44 | 包括代码、文档和内容
45 |
46 |
47 |
48 |
49 | 活跃贡献者
50 |
51 |
52 |
53 | {contributionStats.activeContributors}
54 | 贡献超过 30 次
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
贡献者列表
63 | 按贡献数排序
64 |
65 |
66 | {contributorsData.map((contributor, index) => (
67 |
68 |
69 |
70 |
71 |
72 | {contributor.name.slice(0, 2)}
73 |
74 |
75 |
76 |
77 |
{contributor.name}
78 | {index < 3 && (
79 |
80 |
81 | Top {index + 1}
82 |
83 | )}
84 |
85 |
86 |
87 | {contributor.role}
88 |
89 | ·
90 | {contributor.contributions} 次贡献
91 |
92 |
93 |
94 |
95 |
96 | {contributor.description}
97 | {contributor.github && (
98 |
108 | )}
109 |
110 |
111 | ))}
112 |
113 |
114 |
115 |
116 |
117 |
118 | 贡献类型
119 |
120 |
121 |
122 |
代码贡献
123 |
124 | 包括网站功能开发、Bug 修复、性能优化等技术贡献。
125 |
126 |
127 |
128 |
内容贡献
129 |
130 | 包括案例研究、技术文章、资源推荐、翻译等内容创作。
131 |
132 |
133 |
134 |
设计贡献
135 |
136 | 包括 UI/UX 设计、视觉优化、用户体验改进等设计工作。
137 |
138 |
139 |
140 |
社区管理
141 |
142 | 包括社区运营、用户支持、活动组织等社区建设工作。
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | 成为贡献者
154 |
155 | OSPO 中文社区是一个开放的社区项目,我们欢迎所有形式的贡献。
156 | 无论是代码、文档、设计还是内容,每一份贡献都让社区变得更好。
157 |
158 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | 贡献指南
176 |
177 |
178 |
179 | 1. Fork 仓库:访问我们的 GitHub 仓库,点击 Fork 按钮创建你自己的副本。
180 |
181 |
182 | 2. 编辑数据文件:所有内容数据都存储在 data/{" "}
183 | 目录下的 TypeScript 文件中,你可以直接编辑这些文件来更新内容。
184 |
185 |
186 | 3. 提交 Pull Request:完成修改后,提交 Pull Request
187 | 到主仓库,我们会尽快审核你的贡献。
188 |
189 |
190 | 4. 参与讨论:在 GitHub Issues 中参与讨论,提出建议或报告问题。
191 |
192 | 注意:所有贡献都需要遵守我们的行为准则和贡献协议。
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | )
203 | }
204 |
--------------------------------------------------------------------------------
/app/operations/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Shield, GitBranch, Users2, BookOpen, Wrench, TrendingUp } from "lucide-react"
5 |
6 | export default function OperationsPage() {
7 | const responsibilities = [
8 | {
9 | icon: Shield,
10 | title: "开源合规管理",
11 | items: ["制定和维护开源使用政策", "审查开源许可证合规性", "管理开源软件清单(SBOM)", "处理许可证冲突和风险"],
12 | },
13 | {
14 | icon: GitBranch,
15 | title: "开源项目管理",
16 | items: ["评估和选择开源项目", "管理企业开源项目发布", "监控项目健康度和安全性", "协调内部开源贡献"],
17 | },
18 | {
19 | icon: Users2,
20 | title: "社区参与与关系",
21 | items: ["建立和维护社区关系", "组织和参与开源活动", "管理企业开源品牌", "支持员工社区贡献"],
22 | },
23 | {
24 | icon: BookOpen,
25 | title: "培训与文化建设",
26 | items: ["开展开源知识培训", "推广开源最佳实践", "建立内部开源社区", "激励开源贡献行为"],
27 | },
28 | {
29 | icon: Wrench,
30 | title: "工具与基础设施",
31 | items: ["部署开源管理工具", "建立自动化流程", "提供技术支持服务", "维护知识库和文档"],
32 | },
33 | {
34 | icon: TrendingUp,
35 | title: "战略规划与度量",
36 | items: ["制定开源战略路线图", "设定 KPI 和度量指标", "分析开源投资回报", "向管理层汇报进展"],
37 | },
38 | ]
39 |
40 | return (
41 |
42 |
43 |
44 |
45 |
46 |
47 |
OSPO 职责与运营
48 |
49 | 深入了解 OSPO 的日常职责、工作流程和最佳实践
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | 核心职责领域
58 |
59 | {responsibilities.map((area) => (
60 |
61 |
62 |
65 | {area.title}
66 |
67 |
68 |
69 | {area.items.map((item, index) => (
70 | -
71 |
72 | {item}
73 |
74 | ))}
75 |
76 |
77 |
78 | ))}
79 |
80 |
81 |
82 |
83 |
84 |
85 | 典型工作流程
86 |
87 |
88 |
89 |
开源软件引入流程
90 |
91 | -
92 | 1.
93 | 开发者提交开源软件使用申请
94 |
95 | -
96 | 2.
97 | OSPO 审查许可证兼容性和安全风险
98 |
99 | -
100 | 3.
101 | 评估项目活跃度和社区健康度
102 |
103 | -
104 | 4.
105 | 批准使用并记录到软件清单
106 |
107 | -
108 | 5.
109 | 持续监控更新和安全漏洞
110 |
111 |
112 |
113 |
114 |
115 |
开源项目发布流程
116 |
117 | -
118 | 1.
119 | 团队提交开源发布申请
120 |
121 | -
122 | 2.
123 | OSPO 评估商业价值和风险
124 |
125 | -
126 | 3.
127 | 法务审查知识产权和许可证选择
128 |
129 | -
130 | 4.
131 | 准备项目文档和社区基础设施
132 |
133 | -
134 | 5.
135 | 正式发布并进行社区推广
136 |
137 | -
138 | 6.
139 | 持续维护和社区运营
140 |
141 |
142 |
143 |
144 |
145 |
员工贡献支持流程
146 |
147 | -
148 | 1.
149 | 员工申请参与外部开源项目
150 |
151 | -
152 | 2.
153 | OSPO 评估项目相关性和影响
154 |
155 | -
156 | 3.
157 | 签署贡献者协议(CLA)
158 |
159 | -
160 | 4.
161 | 提供技术指导和资源支持
162 |
163 | -
164 | 5.
165 | 跟踪贡献并给予认可
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | 运营最佳实践
177 |
178 |
179 |
180 |
建立清晰的政策和流程
181 |
182 | 制定明确的开源使用政策、贡献指南和发布标准。 确保流程简单易懂,避免成为开发者的障碍。
183 |
184 |
185 |
186 |
自动化工具和流程
187 |
188 | 使用自动化工具进行许可证扫描、安全检查和合规审查。 减少人工工作量,提高效率和准确性。
189 |
190 |
191 |
192 |
持续教育和沟通
193 |
194 | 定期开展培训活动,分享开源知识和最佳实践。 建立多渠道沟通机制,及时回应团队需求。
195 |
196 |
197 |
198 |
度量和持续改进
199 |
200 | 建立关键指标体系,定期评估 OSPO 的效果。 根据反馈和数据持续优化流程和服务。
201 |
202 |
203 |
204 |
平衡控制与赋能
205 |
206 | 在风险管理和开发者自由之间找到平衡。 OSPO 应该是赋能者而非阻碍者。
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | 关键成功因素
217 |
218 |
219 |
220 |
221 |
高层支持
222 |
223 | 获得管理层的认可和资源支持,确保 OSPO 有足够的权威执行职责。
224 |
225 |
226 |
227 |
跨部门协作
228 |
229 | 与工程、法务、市场等部门建立良好的合作关系。
230 |
231 |
232 |
233 |
技术能力
234 |
235 | 团队成员需要具备深厚的技术背景和开源社区经验。
236 |
237 |
238 |
239 |
社区信誉
240 |
241 | 在开源社区建立良好的声誉,成为受尊重的参与者。
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | )
255 | }
256 |
--------------------------------------------------------------------------------
/app/resources/page.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 | import { SiteFooter } from "@/components/site-footer"
3 | import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
4 | import { Button } from "@/components/ui/button"
5 | import { BookOpen, FileText, ExternalLink, Rocket, Smile, Github, Check } from "lucide-react"
6 | import { resourcesData } from "@/data/resources"
7 |
8 | export default function ResourcesPage() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
OSPO 资源中心
17 |
18 | 获取 OSPO 社区开源项目、权威书籍、研究报告和实用工具,助力您的开源之旅
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
社区开源项目
29 |
30 |
31 | {resourcesData.projects.map((project) => (
32 |
36 |
37 |
38 | {project.name}
39 |
40 | {project.category}
41 |
42 |
43 |
44 |
45 | {project.description}
46 |
47 | {/* 显示项目特性 */}
48 | {project.features && (
49 |
50 | {project.features.map((feature) => (
51 |
55 |
56 | {feature}
57 |
58 | ))}
59 |
60 | )}
61 |
62 | {project.versions && (
63 |
64 |
可用版本:
65 |
66 | {project.versions.map((version) => (
67 |
68 |
69 |
70 | {version.name}
71 |
72 |
{version.description}
73 | {version.url ? (
74 |
80 | 立即获取
81 |
82 |
83 | ) : (
84 |
85 | {version.status || "待上架"}
86 |
87 | )}
88 | {version.note &&
{version.note}
}
89 |
90 | ))}
91 |
92 |
93 | )}
94 |
95 | {project.url !== "#" ? (
96 |
102 | ) : (
103 |
106 | )}
107 |
108 |
109 | ))}
110 |
111 |
112 |
113 | {/* 推荐书籍 */}
114 |
115 |
116 |
117 |
推荐书籍
118 |
119 |
120 | {resourcesData.books.map((book) => (
121 |
122 |
123 |
124 | {book.title}
125 |
126 | {book.type}
127 |
128 |
129 | 作者:{book.author}
130 |
131 |
132 | {book.description}
133 |
139 |
140 |
141 | ))}
142 |
143 |
144 |
145 | {/* 报告 */}
146 |
147 |
148 |
149 |
研究报告
150 |
151 |
152 | {resourcesData.reports.map((report) => (
153 |
154 |
155 |
156 | {report.title}
157 |
158 | {report.year}
159 |
160 |
161 | {report.organization}
162 |
163 |
164 | {report.description}
165 |
171 |
172 |
173 | ))}
174 |
175 |
176 |
177 | {/* 实用工具 */}
178 |
179 | 实用工具
180 |
181 | {resourcesData.tools.map((tool) => (
182 |
183 |
184 | {tool.name}
185 | {tool.category}
186 |
187 |
188 | {tool.description}
189 |
195 |
196 |
197 | ))}
198 |
199 |
200 |
201 | {/* 学习路径建议 */}
202 |
203 |
204 |
205 | 学习路径建议
206 |
207 |
208 | {resourcesData.learningPaths.map((path, index) => (
209 |
210 |
{path.level}
211 |
{path.description}
212 |
213 | ))}
214 |
215 |
216 |
217 |
218 | {/* 持续更新中 */}
219 |
220 |
221 |
222 | 持续更新中
223 |
224 | 我们会持续收集和更新 OSPO 相关的优质资源。如果您有推荐的书籍、报告或工具,欢迎与我们分享。
225 |
226 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 | )
240 | }
241 |
--------------------------------------------------------------------------------