├── 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 | 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 | 2 | 12 | 13 | 14 | 15 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /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 |
7 |
8 |
9 |
10 |

关于 OSPO

11 |

12 | 开源项目办公室(OSPO)是企业管理开源战略、合规性和社区参与的核心机构。 13 |

14 |
15 | 16 |
17 |

快速链接

18 |
    19 |
  • 20 | 21 | OSPO 简介 22 | 23 |
  • 24 |
  • 25 | 26 | 组织形式 27 | 28 |
  • 29 |
  • 30 | 31 | 职责与运营 32 | 33 |
  • 34 |
  • 35 | 36 | 案例研究 37 | 38 |
  • 39 |
40 |
41 | 42 |
43 |

资源

44 |
    45 |
  • 46 | 47 | 项目与图书报告 48 | 49 |
  • 50 |
  • 51 | 52 | 社区与组织 53 | 54 |
  • 55 |
  • 56 | 57 | 友情链接 58 | 59 |
  • 60 |
61 |
62 | 63 |
64 |

联系我们

65 | 73 |
74 |
75 | 76 |
77 |

© 2025 OSPO 中文社区. 保留所有权利.

78 |
79 |
80 |
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 |
159 | 166 | 167 |
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 |
63 | 64 |
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 |
  1. 92 | 1. 93 | 开发者提交开源软件使用申请 94 |
  2. 95 |
  3. 96 | 2. 97 | OSPO 审查许可证兼容性和安全风险 98 |
  4. 99 |
  5. 100 | 3. 101 | 评估项目活跃度和社区健康度 102 |
  6. 103 |
  7. 104 | 4. 105 | 批准使用并记录到软件清单 106 |
  8. 107 |
  9. 108 | 5. 109 | 持续监控更新和安全漏洞 110 |
  10. 111 |
112 |
113 | 114 |
115 |

开源项目发布流程

116 |
    117 |
  1. 118 | 1. 119 | 团队提交开源发布申请 120 |
  2. 121 |
  3. 122 | 2. 123 | OSPO 评估商业价值和风险 124 |
  4. 125 |
  5. 126 | 3. 127 | 法务审查知识产权和许可证选择 128 |
  6. 129 |
  7. 130 | 4. 131 | 准备项目文档和社区基础设施 132 |
  8. 133 |
  9. 134 | 5. 135 | 正式发布并进行社区推广 136 |
  10. 137 |
  11. 138 | 6. 139 | 持续维护和社区运营 140 |
  12. 141 |
142 |
143 | 144 |
145 |

员工贡献支持流程

146 |
    147 |
  1. 148 | 1. 149 | 员工申请参与外部开源项目 150 |
  2. 151 |
  3. 152 | 2. 153 | OSPO 评估项目相关性和影响 154 |
  4. 155 |
  5. 156 | 3. 157 | 签署贡献者协议(CLA) 158 |
  6. 159 |
  7. 160 | 4. 161 | 提供技术指导和资源支持 162 |
  8. 163 |
  9. 164 | 5. 165 | 跟踪贡献并给予认可 166 |
  10. 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 | --------------------------------------------------------------------------------