@zpress/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.mjs +75 -0
  3. package/dist/theme/components/home/feature-card.css +89 -0
  4. package/dist/theme/components/home/feature-card.tsx +75 -0
  5. package/dist/theme/components/home/feature.tsx +53 -0
  6. package/dist/theme/components/home/layout.tsx +36 -0
  7. package/dist/theme/components/home/workspaces.tsx +53 -0
  8. package/dist/theme/components/nav/branch-tag.css +54 -0
  9. package/dist/theme/components/nav/branch-tag.tsx +66 -0
  10. package/dist/theme/components/shared/card.tsx +27 -0
  11. package/dist/theme/components/shared/icon.tsx +27 -0
  12. package/dist/theme/components/shared/section-card.tsx +42 -0
  13. package/dist/theme/components/shared/section-grid.tsx +12 -0
  14. package/dist/theme/components/shared/tech-icon-table.tsx +68 -0
  15. package/dist/theme/components/shared/tech-tag.tsx +28 -0
  16. package/dist/theme/components/workspaces/card.css +141 -0
  17. package/dist/theme/components/workspaces/card.tsx +116 -0
  18. package/dist/theme/components/workspaces/grid.tsx +40 -0
  19. package/dist/theme/css.d.ts +1 -0
  20. package/dist/theme/fonts/GeistMono-Variable.woff2 +0 -0
  21. package/dist/theme/fonts/GeistPixel-Square.woff2 +0 -0
  22. package/dist/theme/fonts/GeistSans-Variable.woff2 +0 -0
  23. package/dist/theme/hooks/use-zpress.ts +57 -0
  24. package/dist/theme/icons/index.ts +2 -0
  25. package/dist/theme/icons/tech-map.ts +221 -0
  26. package/dist/theme/index.tsx +46 -0
  27. package/dist/theme/styles/overrides/details.css +61 -0
  28. package/dist/theme/styles/overrides/fonts.css +27 -0
  29. package/dist/theme/styles/overrides/home-card.css +125 -0
  30. package/dist/theme/styles/overrides/home.css +55 -0
  31. package/dist/theme/styles/overrides/rspress.css +108 -0
  32. package/dist/theme/styles/overrides/scrollbar.css +25 -0
  33. package/dist/theme/styles/overrides/section-card.css +115 -0
  34. package/dist/theme/styles/overrides/sidebar.css +9 -0
  35. package/dist/theme/styles/overrides/tokens.css +48 -0
  36. package/package.json +64 -0
  37. package/src/theme/components/home/feature-card.css +89 -0
  38. package/src/theme/components/home/feature-card.tsx +75 -0
  39. package/src/theme/components/home/feature.tsx +53 -0
  40. package/src/theme/components/home/layout.tsx +36 -0
  41. package/src/theme/components/home/workspaces.tsx +53 -0
  42. package/src/theme/components/nav/branch-tag.css +54 -0
  43. package/src/theme/components/nav/branch-tag.tsx +66 -0
  44. package/src/theme/components/shared/card.tsx +27 -0
  45. package/src/theme/components/shared/icon.tsx +27 -0
  46. package/src/theme/components/shared/section-card.tsx +42 -0
  47. package/src/theme/components/shared/section-grid.tsx +12 -0
  48. package/src/theme/components/shared/tech-icon-table.tsx +68 -0
  49. package/src/theme/components/shared/tech-tag.tsx +28 -0
  50. package/src/theme/components/workspaces/card.css +141 -0
  51. package/src/theme/components/workspaces/card.tsx +116 -0
  52. package/src/theme/components/workspaces/grid.tsx +40 -0
  53. package/src/theme/css.d.ts +1 -0
  54. package/src/theme/fonts/GeistMono-Variable.woff2 +0 -0
  55. package/src/theme/fonts/GeistPixel-Square.woff2 +0 -0
  56. package/src/theme/fonts/GeistSans-Variable.woff2 +0 -0
  57. package/src/theme/hooks/use-zpress.ts +57 -0
  58. package/src/theme/icons/index.ts +2 -0
  59. package/src/theme/icons/tech-map.ts +221 -0
  60. package/src/theme/index.tsx +46 -0
  61. package/src/theme/styles/overrides/details.css +61 -0
  62. package/src/theme/styles/overrides/fonts.css +27 -0
  63. package/src/theme/styles/overrides/home-card.css +125 -0
  64. package/src/theme/styles/overrides/home.css +55 -0
  65. package/src/theme/styles/overrides/rspress.css +108 -0
  66. package/src/theme/styles/overrides/scrollbar.css +25 -0
  67. package/src/theme/styles/overrides/section-card.css +115 -0
  68. package/src/theme/styles/overrides/sidebar.css +9 -0
  69. package/src/theme/styles/overrides/tokens.css +48 -0
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Workspace grid, card layout, deploy badge, and tech tags.
3
+ * Base card styles (container, hover, icons) from home-card.css.
4
+ */
5
+
6
+ /* ── Workspace section ───────────────────────────────────── */
7
+ .workspace-section {
8
+ max-width: 1152px;
9
+ margin: 0 auto;
10
+ padding: 0 0 64px;
11
+ }
12
+
13
+ .workspace-section h2 {
14
+ font-size: 18px;
15
+ font-weight: 600;
16
+ letter-spacing: 0.02em;
17
+ text-transform: uppercase;
18
+ margin-bottom: 4px;
19
+ color: var(--zp-c-text-2);
20
+ }
21
+
22
+ .workspace-group-desc {
23
+ margin: 0 0 16px;
24
+ font-size: 14px;
25
+ color: var(--zp-c-text-3);
26
+ line-height: 1.5;
27
+ }
28
+
29
+ .workspace-grid {
30
+ display: grid;
31
+ grid-template-columns: repeat(2, 1fr);
32
+ gap: 12px;
33
+ margin-bottom: 40px;
34
+ }
35
+
36
+ /* ── Workspace card layout ───────────────────────────────── */
37
+ .workspace-card {
38
+ display: flex;
39
+ flex-direction: column;
40
+ }
41
+
42
+ .workspace-header {
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: space-between;
46
+ margin-bottom: 10px;
47
+ }
48
+
49
+ .workspace-identity {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 10px;
53
+ }
54
+
55
+ .workspace-title {
56
+ display: flex;
57
+ flex-direction: column;
58
+ line-height: 1.2;
59
+ }
60
+
61
+ .workspace-scope {
62
+ font-family: var(--zp-font-family-mono);
63
+ font-size: 11px;
64
+ color: var(--zp-c-text-3);
65
+ }
66
+
67
+ .workspace-name {
68
+ font-family: var(--zp-font-family-mono);
69
+ font-size: 15px;
70
+ font-weight: 700;
71
+ color: var(--zp-c-text-1);
72
+ }
73
+
74
+ .workspace-desc {
75
+ font-size: 13px;
76
+ color: var(--zp-c-text-2);
77
+ line-height: 1.5;
78
+ flex: 1;
79
+ }
80
+
81
+ /* ── Deploy badge ────────────────────────────────────────── */
82
+ .deploy-badge {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ padding: 4px 6px;
87
+ border-radius: 6px;
88
+ background: var(--zp-c-bg);
89
+ border: 1px solid var(--zp-c-divider);
90
+ }
91
+
92
+ .deploy-logo {
93
+ height: 16px;
94
+ width: auto;
95
+ opacity: 0.75;
96
+ transition: opacity 0.2s;
97
+ }
98
+
99
+ .home-card:hover .deploy-logo {
100
+ opacity: 1;
101
+ }
102
+
103
+ /* ── Tech tags ───────────────────────────────────────────── */
104
+ .workspace-tags {
105
+ display: flex;
106
+ flex-wrap: wrap;
107
+ gap: 6px;
108
+ margin-top: 10px;
109
+ }
110
+
111
+ .workspace-tag {
112
+ display: inline-flex;
113
+ align-items: center;
114
+ gap: 4px;
115
+ font-family: var(--zp-font-family-mono);
116
+ font-size: 11px;
117
+ padding: 2px 8px;
118
+ border-radius: var(--rp-radius-small);
119
+ background: var(--zp-c-bg);
120
+ color: var(--zp-c-text-3);
121
+ border: 1px solid var(--zp-c-divider);
122
+ }
123
+
124
+ .workspace-tag svg {
125
+ width: 14px;
126
+ height: 14px;
127
+ flex-shrink: 0;
128
+ }
129
+
130
+ /* ── Responsive ──────────────────────────────────────────── */
131
+ @media (max-width: 768px) {
132
+ .workspace-grid {
133
+ grid-template-columns: 1fr;
134
+ }
135
+ }
136
+
137
+ @media (min-width: 769px) and (max-width: 1024px) {
138
+ .workspace-grid {
139
+ grid-template-columns: repeat(2, 1fr);
140
+ }
141
+ }
@@ -0,0 +1,116 @@
1
+ import type React from 'react'
2
+ import { match, P } from 'ts-pattern'
3
+
4
+ import type { IconColor } from '../home/feature-card'
5
+ import { Card } from '../shared/card'
6
+ import { Icon } from '../shared/icon'
7
+ import { TechTag } from '../shared/tech-tag'
8
+
9
+ // ── Types ────────────────────────────────────────────────────
10
+
11
+ export interface WorkspaceCardProps {
12
+ /**
13
+ * Display name for the card header.
14
+ */
15
+ readonly text: string
16
+ /**
17
+ * Link target (e.g. "/apps/api").
18
+ */
19
+ readonly href: string
20
+ /**
21
+ * Iconify identifier (e.g. "simple-icons:typescript").
22
+ */
23
+ readonly icon?: string
24
+ /**
25
+ * CSS class suffix for icon background color.
26
+ */
27
+ readonly iconColor?: IconColor
28
+ /**
29
+ * Scope prefix shown above the name (e.g. "apps/").
30
+ */
31
+ readonly scope?: string
32
+ /**
33
+ * Short description rendered below the header.
34
+ */
35
+ readonly description?: string
36
+ /**
37
+ * Technology tag names resolved via the tech map.
38
+ */
39
+ readonly tags?: readonly string[]
40
+ /**
41
+ * Deploy badge image for the card header.
42
+ */
43
+ readonly badge?: { readonly src: string; readonly alt: string }
44
+ }
45
+
46
+ // ── Component ────────────────────────────────────────────────
47
+
48
+ /**
49
+ * Workspace card — renders a clickable link card with icon, name,
50
+ * description, tech tags, and optional deploy badge.
51
+ */
52
+ export function WorkspaceCard({
53
+ text,
54
+ href,
55
+ icon,
56
+ iconColor = 'purple',
57
+ scope,
58
+ description,
59
+ tags,
60
+ badge,
61
+ }: WorkspaceCardProps): React.ReactElement {
62
+ const name = text.toLowerCase()
63
+
64
+ const iconEl = match(icon)
65
+ .with(P.nonNullable, (id) => <Icon icon={id} />)
66
+ .otherwise(() => null)
67
+
68
+ const scopeEl = match(scope)
69
+ .with(
70
+ P.when((s): s is string => s !== undefined && s.length > 0),
71
+ (s) => <span className="workspace-scope">{s}</span>
72
+ )
73
+ .otherwise(() => null)
74
+
75
+ const badgeEl = match(badge)
76
+ .with(P.nonNullable, (b) => (
77
+ <span className="deploy-badge" title={`Deployed on ${b.alt}`}>
78
+ <img src={b.src} alt={b.alt} className="deploy-logo" />
79
+ </span>
80
+ ))
81
+ .otherwise(() => null)
82
+
83
+ const descEl = match(description)
84
+ .with(P.nonNullable, (d) => <span className="workspace-desc">{d}</span>)
85
+ .otherwise(() => null)
86
+
87
+ const tagsEl = match(tags)
88
+ .with(
89
+ P.when((t): t is readonly string[] => t !== undefined && t.length > 0),
90
+ (t) => (
91
+ <div className="workspace-tags">
92
+ {t.map((tag) => (
93
+ <TechTag key={tag} name={tag} />
94
+ ))}
95
+ </div>
96
+ )
97
+ )
98
+ .otherwise(() => null)
99
+
100
+ return (
101
+ <Card href={href} className="workspace-card">
102
+ <div className="workspace-header">
103
+ <div className="workspace-identity">
104
+ <span className={`home-card-icon home-card-icon--${iconColor}`}>{iconEl}</span>
105
+ <div className="workspace-title">
106
+ {scopeEl}
107
+ <span className="workspace-name">{name}</span>
108
+ </div>
109
+ </div>
110
+ {badgeEl}
111
+ </div>
112
+ {descEl}
113
+ {tagsEl}
114
+ </Card>
115
+ )
116
+ }
@@ -0,0 +1,40 @@
1
+ import type React from 'react'
2
+
3
+ import './card.css'
4
+
5
+ // ── Types ────────────────────────────────────────────────────
6
+
7
+ export interface WorkspaceGridProps {
8
+ /**
9
+ * Section heading (e.g. "Apps", "Packages").
10
+ */
11
+ readonly heading: string
12
+ /**
13
+ * Brief description rendered below the heading.
14
+ */
15
+ readonly description: string
16
+ /**
17
+ * WorkspaceCard elements.
18
+ */
19
+ readonly children: React.ReactNode
20
+ }
21
+
22
+ // ── Component ────────────────────────────────────────────────
23
+
24
+ /**
25
+ * Grid container for workspace cards — renders a heading, description,
26
+ * and a CSS grid wrapping its children.
27
+ */
28
+ export function WorkspaceGrid({
29
+ heading,
30
+ description,
31
+ children,
32
+ }: WorkspaceGridProps): React.ReactElement {
33
+ return (
34
+ <>
35
+ <h2>{heading}</h2>
36
+ <p className="workspace-group-desc">{description}</p>
37
+ <div className="workspace-grid">{children}</div>
38
+ </>
39
+ )
40
+ }
@@ -0,0 +1 @@
1
+ declare module '*.css' {}
@@ -0,0 +1,57 @@
1
+ import { useSite } from '@rspress/core/runtime'
2
+
3
+ import type { IconColor } from '../components/home/feature-card'
4
+
5
+ // ── Sidebar types ───────────────────────────────────────────
6
+
7
+ export interface ZpressSidebarItem {
8
+ readonly text?: string
9
+ readonly link?: string
10
+ readonly icon?: string
11
+ readonly items?: readonly ZpressSidebarItem[]
12
+ }
13
+
14
+ // ── Workspace types ─────────────────────────────────────────
15
+
16
+ export interface WorkspaceCardData {
17
+ readonly text: string
18
+ readonly href: string
19
+ readonly icon: string | undefined
20
+ readonly iconColor: IconColor | undefined
21
+ readonly scope: string | undefined
22
+ readonly description: string | undefined
23
+ readonly tags: readonly string[]
24
+ readonly badge: { readonly src: string; readonly alt: string } | undefined
25
+ }
26
+
27
+ export interface WorkspaceGroupData {
28
+ readonly type: 'apps' | 'packages' | 'workspaces'
29
+ readonly heading: string
30
+ readonly description: string
31
+ readonly cards: readonly WorkspaceCardData[]
32
+ }
33
+
34
+ // ── Theme config ────────────────────────────────────────────
35
+
36
+ interface ZpressThemeConfig {
37
+ readonly sidebar: Record<string, readonly ZpressSidebarItem[]>
38
+ readonly workspaces: readonly WorkspaceGroupData[] | undefined
39
+ }
40
+
41
+ // ── Hook ────────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Typed wrapper around Rspress `useSite()` that exposes
45
+ * zpress-specific themeConfig fields.
46
+ *
47
+ * The double cast is necessary because Rspress types `themeConfig` as
48
+ * `NormalizedThemeConfig`, but zpress injects custom fields (sidebar,
49
+ * workspaces) via spread at build time. No Zod schema exists for runtime
50
+ * validation yet.
51
+ *
52
+ * @returns zpress theme config with sidebar and workspace data.
53
+ */
54
+ export function useZpress(): ZpressThemeConfig {
55
+ const { site } = useSite()
56
+ return site.themeConfig as unknown as ZpressThemeConfig
57
+ }
@@ -0,0 +1,2 @@
1
+ export { TECH_ICONS } from './tech-map.ts'
2
+ export type { TechName } from './tech-map.ts'
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Predefined technology tag to Iconify identifier + display label.
3
+ *
4
+ * Uses `devicon` as the primary source for colored icons, with `logos`,
5
+ * `vscode-icons`, and `material-icon-theme` filling gaps. A small number
6
+ * of entries fall back to `simple-icons` (monochrome) when no colored
7
+ * alternative exists.
8
+ *
9
+ * Add new entries here when new technologies need card support.
10
+ */
11
+ export const TECH_ICONS = {
12
+ // -- Languages --
13
+ typescript: { icon: 'devicon:typescript', label: 'TypeScript' },
14
+ javascript: { icon: 'devicon:javascript', label: 'JavaScript' },
15
+ python: { icon: 'devicon:python', label: 'Python' },
16
+ go: { icon: 'devicon:go', label: 'Go' },
17
+ rust: { icon: 'devicon:rust', label: 'Rust' },
18
+ java: { icon: 'devicon:java', label: 'Java' },
19
+ csharp: { icon: 'devicon:csharp', label: 'C#' },
20
+ ruby: { icon: 'devicon:ruby', label: 'Ruby' },
21
+ php: { icon: 'devicon:php', label: 'PHP' },
22
+ swift: { icon: 'devicon:swift', label: 'Swift' },
23
+ kotlin: { icon: 'devicon:kotlin', label: 'Kotlin' },
24
+ elixir: { icon: 'devicon:elixir', label: 'Elixir' },
25
+ dart: { icon: 'devicon:dart', label: 'Dart' },
26
+ scala: { icon: 'devicon:scala', label: 'Scala' },
27
+ c: { icon: 'devicon:c', label: 'C' },
28
+ cplusplus: { icon: 'devicon:cplusplus', label: 'C++' },
29
+ r: { icon: 'devicon:r', label: 'R' },
30
+ lua: { icon: 'devicon:lua', label: 'Lua' },
31
+ perl: { icon: 'devicon:perl', label: 'Perl' },
32
+ haskell: { icon: 'devicon:haskell', label: 'Haskell' },
33
+ clojure: { icon: 'devicon:clojure', label: 'Clojure' },
34
+ erlang: { icon: 'devicon:erlang', label: 'Erlang' },
35
+ fsharp: { icon: 'devicon:fsharp', label: 'F#' },
36
+ julia: { icon: 'devicon:julia', label: 'Julia' },
37
+ groovy: { icon: 'devicon:groovy', label: 'Groovy' },
38
+
39
+ // -- Frontend frameworks --
40
+ react: { icon: 'devicon:react', label: 'React' },
41
+ nextjs: { icon: 'devicon:nextjs', label: 'Next.js' },
42
+ vue: { icon: 'devicon:vuejs', label: 'Vue' },
43
+ angular: { icon: 'devicon:angular', label: 'Angular' },
44
+ svelte: { icon: 'devicon:svelte', label: 'Svelte' },
45
+ astro: { icon: 'devicon:astro', label: 'Astro' },
46
+ solid: { icon: 'devicon:solidjs', label: 'Solid' },
47
+ remix: { icon: 'devicon:remix', label: 'Remix' },
48
+ qwik: { icon: 'devicon:qwik', label: 'Qwik' },
49
+ ember: { icon: 'devicon:ember', label: 'Ember' },
50
+ gatsby: { icon: 'devicon:gatsby', label: 'Gatsby' },
51
+ nuxtjs: { icon: 'devicon:nuxtjs', label: 'Nuxt' },
52
+ preact: { icon: 'logos:preact', label: 'Preact' },
53
+ lit: { icon: 'logos:lit', label: 'Lit' },
54
+
55
+ // -- Backend frameworks --
56
+ hono: { icon: 'logos:hono', label: 'Hono' },
57
+ express: { icon: 'devicon:express', label: 'Express' },
58
+ fastify: { icon: 'devicon:fastify', label: 'Fastify' },
59
+ nestjs: { icon: 'devicon:nestjs', label: 'NestJS' },
60
+ django: { icon: 'logos:django-icon', label: 'Django' },
61
+ flask: { icon: 'devicon:flask', label: 'Flask' },
62
+ rails: { icon: 'devicon:rails-wordmark', label: 'Rails' },
63
+ spring: { icon: 'devicon:spring', label: 'Spring' },
64
+ fastapi: { icon: 'devicon:fastapi', label: 'FastAPI' },
65
+ laravel: { icon: 'devicon:laravel', label: 'Laravel' },
66
+ phoenix: { icon: 'devicon:phoenix', label: 'Phoenix' },
67
+ fiber: { icon: 'devicon:fiber', label: 'Fiber' },
68
+ gin: { icon: 'logos:gin', label: 'Gin' },
69
+ akka: { icon: 'devicon:akka', label: 'Akka' },
70
+
71
+ // -- Mobile --
72
+ flutter: { icon: 'devicon:flutter', label: 'Flutter' },
73
+ reactnative: { icon: 'devicon:reactnative', label: 'React Native' },
74
+ ionic: { icon: 'devicon:ionic', label: 'Ionic' },
75
+
76
+ // -- Databases --
77
+ postgresql: { icon: 'devicon:postgresql', label: 'PostgreSQL' },
78
+ mysql: { icon: 'devicon:mysql', label: 'MySQL' },
79
+ mongodb: { icon: 'devicon:mongodb', label: 'MongoDB' },
80
+ redis: { icon: 'devicon:redis', label: 'Redis' },
81
+ sqlite: { icon: 'devicon:sqlite', label: 'SQLite' },
82
+ dynamodb: { icon: 'devicon:dynamodb', label: 'DynamoDB' },
83
+ elasticsearch: { icon: 'devicon:elasticsearch', label: 'Elasticsearch' },
84
+ neo4j: { icon: 'devicon:neo4j', label: 'Neo4j' },
85
+ cassandra: { icon: 'devicon:cassandra', label: 'Cassandra' },
86
+ couchdb: { icon: 'devicon:couchdb', label: 'CouchDB' },
87
+ mariadb: { icon: 'devicon:mariadb', label: 'MariaDB' },
88
+ influxdb: { icon: 'devicon:influxdb', label: 'InfluxDB' },
89
+ cockroachdb: { icon: 'simple-icons:cockroachlabs', label: 'CockroachDB' },
90
+ vitess: { icon: 'devicon:vitess', label: 'Vitess' },
91
+ oracle: { icon: 'devicon:oracle', label: 'Oracle' },
92
+
93
+ // -- ORM / Data tools --
94
+ prisma: { icon: 'devicon:prisma', label: 'Prisma' },
95
+ graphql: { icon: 'logos:graphql', label: 'GraphQL' },
96
+ drizzle: { icon: 'logos:drizzle', label: 'Drizzle' },
97
+ typeorm: { icon: 'logos:typeorm', label: 'TypeORM' },
98
+ sequelize: { icon: 'logos:sequelize', label: 'Sequelize' },
99
+ sqlalchemy: { icon: 'devicon:sqlalchemy', label: 'SQLAlchemy' },
100
+
101
+ // -- Cloud & hosting --
102
+ vercel: { icon: 'devicon:vercel', label: 'Vercel' },
103
+ aws: { icon: 'devicon:amazonwebservices', label: 'AWS' },
104
+ azure: { icon: 'devicon:azure', label: 'Azure' },
105
+ gcp: { icon: 'devicon:googlecloud', label: 'GCP' },
106
+ cloudflare: { icon: 'devicon:cloudflare', label: 'Cloudflare' },
107
+ digitalocean: { icon: 'devicon:digitalocean', label: 'DigitalOcean' },
108
+ heroku: { icon: 'devicon:heroku', label: 'Heroku' },
109
+ netlify: { icon: 'devicon:netlify', label: 'Netlify' },
110
+ firebase: { icon: 'devicon:firebase', label: 'Firebase' },
111
+ supabase: { icon: 'devicon:supabase', label: 'Supabase' },
112
+ railway: { icon: 'devicon:railway', label: 'Railway' },
113
+ pulumi: { icon: 'devicon:pulumi', label: 'Pulumi' },
114
+ fly: { icon: 'logos:fly-icon', label: 'Fly.io' },
115
+
116
+ // -- CI/CD & DevOps --
117
+ docker: { icon: 'devicon:docker', label: 'Docker' },
118
+ kubernetes: { icon: 'devicon:kubernetes', label: 'Kubernetes' },
119
+ github: { icon: 'devicon:github', label: 'GitHub' },
120
+ 'github-actions': { icon: 'devicon:githubactions', label: 'GitHub Actions' },
121
+ gitlab: { icon: 'devicon:gitlab', label: 'GitLab' },
122
+ circleci: { icon: 'logos:circleci', label: 'CircleCI' },
123
+ terraform: { icon: 'devicon:terraform', label: 'Terraform' },
124
+ ansible: { icon: 'devicon:ansible', label: 'Ansible' },
125
+ jenkins: { icon: 'devicon:jenkins', label: 'Jenkins' },
126
+ argocd: { icon: 'devicon:argocd', label: 'Argo CD' },
127
+
128
+ // -- Build & package tools --
129
+ vite: { icon: 'devicon:vite', label: 'Vite' },
130
+ webpack: { icon: 'devicon:webpack', label: 'Webpack' },
131
+ npm: { icon: 'devicon:npm', label: 'npm' },
132
+ pnpm: { icon: 'devicon:pnpm', label: 'pnpm' },
133
+ yarn: { icon: 'devicon:yarn', label: 'Yarn' },
134
+ bun: { icon: 'devicon:bun', label: 'Bun' },
135
+ eslint: { icon: 'devicon:eslint', label: 'ESLint' },
136
+ babel: { icon: 'devicon:babel', label: 'Babel' },
137
+ turborepo: { icon: 'logos:turborepo-icon', label: 'Turborepo' },
138
+ biome: { icon: 'devicon:biome', label: 'Biome' },
139
+ prettier: { icon: 'logos:prettier', label: 'Prettier' },
140
+ esbuild: { icon: 'logos:esbuild', label: 'esbuild' },
141
+ rollup: { icon: 'devicon:rollup', label: 'Rollup' },
142
+ swc: { icon: 'logos:swc', label: 'SWC' },
143
+ gradle: { icon: 'devicon:gradle', label: 'Gradle' },
144
+ maven: { icon: 'devicon:maven', label: 'Maven' },
145
+
146
+ // -- UI & styling --
147
+ tailwindcss: { icon: 'devicon:tailwindcss', label: 'Tailwind CSS' },
148
+ css: { icon: 'devicon:css3', label: 'CSS' },
149
+ html: { icon: 'devicon:html5', label: 'HTML' },
150
+ sass: { icon: 'devicon:sass', label: 'Sass' },
151
+ bootstrap: { icon: 'devicon:bootstrap', label: 'Bootstrap' },
152
+ materialui: { icon: 'devicon:materialui', label: 'Material UI' },
153
+ 'shadcn-ui': { icon: 'vscode-icons:file-type-shadcn', label: 'shadcn/ui' },
154
+ storybook: { icon: 'devicon:storybook', label: 'Storybook' },
155
+ figma: { icon: 'devicon:figma', label: 'Figma' },
156
+
157
+ // -- Testing --
158
+ jest: { icon: 'logos:jest', label: 'Jest' },
159
+ vitest: { icon: 'devicon:vitest', label: 'Vitest' },
160
+ cypress: { icon: 'devicon:cypressio', label: 'Cypress' },
161
+ playwright: { icon: 'devicon:playwright', label: 'Playwright' },
162
+ selenium: { icon: 'devicon:selenium', label: 'Selenium' },
163
+ mocha: { icon: 'devicon:mocha', label: 'Mocha' },
164
+ puppeteer: { icon: 'devicon:puppeteer', label: 'Puppeteer' },
165
+ cucumber: { icon: 'logos:cucumber', label: 'Cucumber' },
166
+
167
+ // -- Auth & integrations --
168
+ oauth: { icon: 'devicon:oauth', label: 'OAuth' },
169
+ auth0: { icon: 'logos:auth0', label: 'Auth0' },
170
+ stripe: { icon: 'logos:stripe', label: 'Stripe' },
171
+ twilio: { icon: 'devicon:twilio', label: 'Twilio' },
172
+
173
+ // -- AI / ML --
174
+ openai: { icon: 'logos:openai-icon', label: 'OpenAI' },
175
+ tensorflow: { icon: 'devicon:tensorflow', label: 'TensorFlow' },
176
+ pytorch: { icon: 'devicon:pytorch', label: 'PyTorch' },
177
+ huggingface: { icon: 'devicon:huggingface', label: 'Hugging Face' },
178
+ anthropic: { icon: 'logos:anthropic-icon', label: 'Anthropic' },
179
+ jupyter: { icon: 'devicon:jupyter', label: 'Jupyter' },
180
+ numpy: { icon: 'devicon:numpy', label: 'NumPy' },
181
+ pandas: { icon: 'devicon:pandas', label: 'Pandas' },
182
+ scikitlearn: { icon: 'devicon:scikitlearn', label: 'scikit-learn' },
183
+ matplotlib: { icon: 'devicon:matplotlib', label: 'Matplotlib' },
184
+
185
+ // -- Monitoring & observability --
186
+ grafana: { icon: 'devicon:grafana', label: 'Grafana' },
187
+ prometheus: { icon: 'devicon:prometheus', label: 'Prometheus' },
188
+ datadog: { icon: 'devicon:datadog', label: 'Datadog' },
189
+ sentry: { icon: 'devicon:sentry', label: 'Sentry' },
190
+ newrelic: { icon: 'devicon:newrelic', label: 'New Relic' },
191
+
192
+ // -- Message queues --
193
+ kafka: { icon: 'devicon:apachekafka', label: 'Kafka' },
194
+ rabbitmq: { icon: 'devicon:rabbitmq', label: 'RabbitMQ' },
195
+ nats: { icon: 'devicon:nats', label: 'NATS' },
196
+
197
+ // -- CMS --
198
+ strapi: { icon: 'logos:strapi', label: 'Strapi' },
199
+ contentful: { icon: 'logos:contentful', label: 'Contentful' },
200
+ sanity: { icon: 'devicon:sanity', label: 'Sanity' },
201
+ wordpress: { icon: 'devicon:wordpress', label: 'WordPress' },
202
+ shopify: { icon: 'logos:shopify', label: 'Shopify' },
203
+ ghost: { icon: 'devicon:ghost', label: 'Ghost' },
204
+
205
+ // -- Infrastructure --
206
+ nginx: { icon: 'devicon:nginx', label: 'Nginx' },
207
+ apache: { icon: 'devicon:apache', label: 'Apache' },
208
+ linux: { icon: 'devicon:linux', label: 'Linux' },
209
+
210
+ // -- Project-specific (label-only fallback when icon not in any set) --
211
+ 'trigger-dev': { icon: 'material-icon-theme:trigger', label: 'Trigger.dev' },
212
+ 'ai-sdk': { icon: 'simple-icons:vercel', label: 'AI SDK' },
213
+ openrouter: { icon: 'simple-icons:openrouter', label: 'OpenRouter' },
214
+ liquid: { icon: 'vscode-icons:file-type-liquid', label: 'Liquid' },
215
+ zod: { icon: 'logos:zod', label: 'Zod' },
216
+ } as const satisfies Record<string, { readonly icon: string; readonly label: string }>
217
+
218
+ /**
219
+ * Union of all supported technology tag names.
220
+ */
221
+ export type TechName = keyof typeof TECH_ICONS
@@ -0,0 +1,46 @@
1
+ /**
2
+ * zpress Rspress theme entry.
3
+ *
4
+ * Re-exports the default Rspress theme and extends it with
5
+ * zpress-specific components (branch tag, feature cards).
6
+ *
7
+ * Global styles are imported here so Rspress includes them
8
+ * in the site bundle when this theme entry is loaded.
9
+ */
10
+
11
+ // Global override styles — imported for side-effects
12
+ import './styles/overrides/fonts.css'
13
+ import './styles/overrides/tokens.css'
14
+ import './styles/overrides/rspress.css'
15
+ import './styles/overrides/details.css'
16
+ import './styles/overrides/scrollbar.css'
17
+ import './styles/overrides/sidebar.css'
18
+ import './styles/overrides/home.css'
19
+ import './styles/overrides/home-card.css'
20
+ import './styles/overrides/section-card.css'
21
+
22
+ // Re-export everything from the original Rspress theme
23
+ // (theme-original avoids circular resolution when used inside a themeDir)
24
+ export * from '@rspress/core/theme-original'
25
+
26
+ // zpress components
27
+ export { FeatureCard, FeatureGrid } from './components/home/feature-card'
28
+ export type { FeatureCardProps, FeatureItem, IconColor } from './components/home/feature-card'
29
+ export { WorkspaceCard } from './components/workspaces/card'
30
+ export type { WorkspaceCardProps } from './components/workspaces/card'
31
+ export { WorkspaceGrid } from './components/workspaces/grid'
32
+ export type { WorkspaceGridProps } from './components/workspaces/grid'
33
+
34
+ export { SectionCard } from './components/shared/section-card'
35
+ export type { SectionCardProps } from './components/shared/section-card'
36
+ export { SectionGrid } from './components/shared/section-grid'
37
+ export type { SectionGridProps } from './components/shared/section-grid'
38
+ export { TechTag } from './components/shared/tech-tag'
39
+ export type { TechTagProps } from './components/shared/tech-tag'
40
+ export { TechIconTable } from './components/shared/tech-icon-table'
41
+ export type { TechIconEntry, TechIconTableProps } from './components/shared/tech-icon-table'
42
+ export { Icon } from './components/shared/icon'
43
+
44
+ // Home page overrides — shadow the wildcard re-exports from theme-original
45
+ export { HomeFeature } from './components/home/feature'
46
+ export { HomeLayout } from './components/home/layout'